一、堆
堆结构是一种数组对象,可以被视为一棵完全二叉树。数中每个节点与数组中存放该点中值的那个元素对应。表示一个堆的数组具有两个属性:
length[A]:数组中的元素个数
heap_size[A]:存放在A中的堆的元素个数。
树的根为A[1],给定某个节点的下标i,其父结点PARENT(i),左儿子LEFT(i),右儿子RIGHT(i)。
堆结构还满足堆性质(最大堆):对除根以外的每个节点i,
A[PARENT(i)] >= A[i]
Heapfy:维持堆性质,O(lgn)时间;
BuildHeap:从无序的输入数组中构造出一个堆来,O(1)时间;
HeapSort:对数组进行排序,O(nlgn)时间;
ExtractMax和Insert:使堆结构可以作为一个优先级队列来用,O(lgn)时间。
二、优先级队列
优先级队列是一种用来维护由一组元素构成的集合S的数据结构,这一组元素中的每一个都有个关键字Key。作用于优先级队列上的操作有:
Insert(S, x)
Maximum(S)
ExtractMax(S)
IncreaseKey(S, x, k)

/**//*
*Copyright(c) 2008 All rights reserved.
*
*Heap Sort
*Author:Greentea
*Date:01.20
*/
#include <stdio.h>
#include <assert.h>
#include <limits.h>
#define PARENT(i) ((i-1)>>1) /*节点i的父结点*/
#define LEFT(i) ((i<<1)+1) /*节点i的左孩子*/
#define RIGHT(i) ((i<<1)+2) /*节点i的右孩子*/

void exchange(int *a, int *b);
void MaxHeapify(int *a, int i, int heapSize);
void BuildMaxHeap(int *a, int heapSize);
void HeapSort(int *a, int heapSize);
void HeapIncreaseKey(int *a, int i, int key);
void MaxHeapInsert(int *a, int heapSize, int key);
int HeapMaximum(int *a);
int HeapExtractMax(int *a, int heapSize);


/**//*
*交换a和b指向的值
*/
void exchange(int *a, int *b)

...{
int temp;
temp = *a;
*a = *b;
*b = temp;
}


/**//*
*Input:a:数组
* i:下标
* heapSize:数组大小
*pre: 该函数调用时,LEFT(i)和RIGHT(i)为根的两棵子树都已是堆
*post: 以i为根的子树成为一个堆
*/
void MaxHeapify(int *a, int i, int heapSize)

...{
int L, R;
int largest;

L = LEFT(i);
R = RIGHT(i);
if(L < heapSize && a[L] > a[i])
largest = L;
else
largest = i;
if(R < heapSize && a[R] > a[largest])
largest = R;
if(largest != i)

...{
exchange(&a[i], &a[largest]);
MaxHeapify(a, largest, heapSize);
}
}

/**//*
*自底向上地用Heapify来讲一个数组a[0...n](n=heapSize-1)变成一个堆
*Input:a:数组
* heapSize:数组大小
*/
void BuildMaxHeap(int *a, int heapSize)

...{
int i;

for(i = PARENT(heapSize); i >= 0; i--)
MaxHeapify(a, i, heapSize);
}


/**//*
*Input:a:数组
* heapSize:数组大小
*调用BuildHeap将输入数组a[0...n]构造成一个堆,因数组中最大元素
*是在根a[0]上,则可通过把它与a[n]互换来达到最终的正确位置,再将
*a[0...n-1],通过Heapify函数调整,继续上面过程,直到堆的大小从n-1
*变为1为止
*/
void HeapSort(int *a, int heapSize)

...{
int i;

BuildMaxHeap(a, heapSize);
for(i = heapSize - 1; i > 0; i--)

...{
exchange(&a[0], &a[i]);
heapSize--;
MaxHeapify(a, 0, heapSize);
}
}


/**//*实例*/
int main(int argc, char **argv)

...{
int i, heapSize;

int a[10]=...{2, 6, 3, 8, 9, 7, 1, 4, 0, 5};

heapSize = 10;
HeapSort(a, heapSize);
for(i=0; i<10; i++)

...{
printf("%d ", a[i]);
}
printf(" ");

return 0;
}


/**//******************************************************************
*优先级队列操作
*HeapMaximum:返回堆的最大元素
*HeapExtractMax:删除堆的最大元,并调整重建堆
*HeapIncreaseKey:堆中某元素值增加,并调整重建堆
*MaxHeapInsert:将一个节点插入到堆中
******************************************************************/
int HeapMaximum(int *a)

...{
return a[0];
}

int HeapExtractMax(int *a, int heapSize)

...{
int max;

assert(heapSize>=1);
max = a[0];
a[0] = a[heapSize-1];
heapSize--;
MaxHeapify(a, 0, heapSize);

return max;
}

void HeapIncreaseKey(int *a, int i, int key)

...{
assert(key >= a[i]);
a[i] = key;
while((i > 0) && (a[PARENT(i)] < a[i]))

...{
exchange(&a[PARENT(i)], &a[i]);
i = PARENT(i);
}
}

void MaxHeapInsert(int *a, int heapSize, int key)

...{
heapSize++;
a[heapSize-1] = INT_MIN;
HeapIncreaseKey(a, heapSize-1, key);
}
堆结构是一种数组对象,可以被视为一棵完全二叉树。数中每个节点与数组中存放该点中值的那个元素对应。表示一个堆的数组具有两个属性:
length[A]:数组中的元素个数
heap_size[A]:存放在A中的堆的元素个数。
树的根为A[1],给定某个节点的下标i,其父结点PARENT(i),左儿子LEFT(i),右儿子RIGHT(i)。
堆结构还满足堆性质(最大堆):对除根以外的每个节点i,
A[PARENT(i)] >= A[i]
Heapfy:维持堆性质,O(lgn)时间;
BuildHeap:从无序的输入数组中构造出一个堆来,O(1)时间;
HeapSort:对数组进行排序,O(nlgn)时间;
ExtractMax和Insert:使堆结构可以作为一个优先级队列来用,O(lgn)时间。
二、优先级队列
优先级队列是一种用来维护由一组元素构成的集合S的数据结构,这一组元素中的每一个都有个关键字Key。作用于优先级队列上的操作有:
Insert(S, x)
Maximum(S)
ExtractMax(S)
IncreaseKey(S, x, k)

/**//*
*Copyright(c) 2008 All rights reserved.
*
*Heap Sort
*Author:Greentea
*Date:01.20
*/
#include <stdio.h>
#include <assert.h>
#include <limits.h>
#define PARENT(i) ((i-1)>>1) /*节点i的父结点*/
#define LEFT(i) ((i<<1)+1) /*节点i的左孩子*/
#define RIGHT(i) ((i<<1)+2) /*节点i的右孩子*/
void exchange(int *a, int *b);
void MaxHeapify(int *a, int i, int heapSize);
void BuildMaxHeap(int *a, int heapSize);
void HeapSort(int *a, int heapSize);
void HeapIncreaseKey(int *a, int i, int key);
void MaxHeapInsert(int *a, int heapSize, int key);
int HeapMaximum(int *a);
int HeapExtractMax(int *a, int heapSize);

/**//*
*交换a和b指向的值
*/
void exchange(int *a, int *b)
...{
int temp;
temp = *a;
*a = *b;
*b = temp;
}

/**//*
*Input:a:数组
* i:下标
* heapSize:数组大小
*pre: 该函数调用时,LEFT(i)和RIGHT(i)为根的两棵子树都已是堆
*post: 以i为根的子树成为一个堆
*/
void MaxHeapify(int *a, int i, int heapSize)
...{
int L, R;
int largest;
L = LEFT(i);
R = RIGHT(i);
if(L < heapSize && a[L] > a[i])
largest = L;
else
largest = i;
if(R < heapSize && a[R] > a[largest])
largest = R;
if(largest != i)
...{
exchange(&a[i], &a[largest]);
MaxHeapify(a, largest, heapSize);
}
}
/**//*
*自底向上地用Heapify来讲一个数组a[0...n](n=heapSize-1)变成一个堆
*Input:a:数组
* heapSize:数组大小
*/
void BuildMaxHeap(int *a, int heapSize)
...{
int i;
for(i = PARENT(heapSize); i >= 0; i--)
MaxHeapify(a, i, heapSize);
}

/**//*
*Input:a:数组
* heapSize:数组大小
*调用BuildHeap将输入数组a[0...n]构造成一个堆,因数组中最大元素
*是在根a[0]上,则可通过把它与a[n]互换来达到最终的正确位置,再将
*a[0...n-1],通过Heapify函数调整,继续上面过程,直到堆的大小从n-1
*变为1为止
*/
void HeapSort(int *a, int heapSize)
...{
int i;
BuildMaxHeap(a, heapSize);
for(i = heapSize - 1; i > 0; i--)
...{
exchange(&a[0], &a[i]);
heapSize--;
MaxHeapify(a, 0, heapSize);
}
}

/**//*实例*/
int main(int argc, char **argv)
...{
int i, heapSize;
int a[10]=...{2, 6, 3, 8, 9, 7, 1, 4, 0, 5};
heapSize = 10;
HeapSort(a, heapSize);
for(i=0; i<10; i++)
...{
printf("%d ", a[i]);
}
printf(" ");
return 0;
}

/**//******************************************************************
*优先级队列操作
*HeapMaximum:返回堆的最大元素
*HeapExtractMax:删除堆的最大元,并调整重建堆
*HeapIncreaseKey:堆中某元素值增加,并调整重建堆
*MaxHeapInsert:将一个节点插入到堆中
******************************************************************/
int HeapMaximum(int *a)
...{
return a[0];
}
int HeapExtractMax(int *a, int heapSize)
...{
int max;
assert(heapSize>=1);
max = a[0];
a[0] = a[heapSize-1];
heapSize--;
MaxHeapify(a, 0, heapSize);
return max;
}
void HeapIncreaseKey(int *a, int i, int key)
...{
assert(key >= a[i]);
a[i] = key;
while((i > 0) && (a[PARENT(i)] < a[i]))
...{
exchange(&a[PARENT(i)], &a[i]);
i = PARENT(i);
}
}
void MaxHeapInsert(int *a, int heapSize, int key)
...{
heapSize++;
a[heapSize-1] = INT_MIN;
HeapIncreaseKey(a, heapSize-1, key);
}
本文介绍了堆数据结构及其在实现优先级队列中的应用。首先详细解释了堆的定义和性质,接着给出了堆排序算法的具体实现。最后,探讨了如何使用堆结构实现基本的优先级队列操作。
2210

被折叠的 条评论
为什么被折叠?



