1 最大最小堆定义
堆的定义是:n个元素的序列{k1,k2,…,kn},当且仅当满足如下关系时被称为堆
(1)Ki <= k2i 且 ki <= k2i+1
或 (2) Ki >= k2i 且 ki >= k2i+1 (i = 1,2,…[n/2])
当满足(1)时,为最小堆,当满足(2)时,为最大堆。
若将序列对应成二叉树,便是一颗完全二叉树,2i和2i+1节点分别是节点i的左右子节点,下图所示便是一个最大堆例子:
最小堆例子:
2 建立最大最小堆
最大最小堆的建立方式,较为常见的是,从最后一个元素开始,对堆中元素进行逐层下移。
最大堆建立:
/*
*@func: down shift element in heap
*@param heap: heap to shift
*@param index: the start location of element to shift
*@param len: number of elements already in heap
*/
void maxHeapDownShift(int heap[], int index, int len)
{
if (heap == NULL || index <= 0 || len <= 0 || index > len)
return;
int large = 0;
int left = index * 2;
int right = index *2 + 1;
if (left <= len && heap[left] > heap[index])
large = left;
else
large = index;
if (right <= len && heap[right] > heap[large])
large = right;
if (large != index)
{
int tmp = heap[index];
heap[index] = heap[large];
heap[large] = tmp;
maxHeapDownShift(heap, large, len);
}
}
/*
*@func: create max heap
*@param heap: the target heap
*@param len: number of elements in heap to be created
*/
void createMaxHeap(int heap[], int len)
{
if (heap == NULL || len < 0)
return;
int index = len / 2;
for (; index >= 1; -- index)
{
maxHeapDownShift(heap, index, len);
}
}
最小堆建立:
void minHeapShift(int heap[], int index, int len)
{
if (heap == NULL || index <=0 || len <=0 || index > len)
return;
int smallIndex = -1;
int left = index * 2;
int right = index * 2 + 1;
if (left <= len && heap[left] < heap[index])
smallIndex = left;
else
smallIndex = index;
if (right <= len && heap[right] < heap[smallIndex])
smallIndex = right;
if (smallIndex != index)
{
int temp = heap[index];
heap[index] = heap[smallIndex];
heap[smallIndex] = temp;
minHeapShift(heap, smallIndex, len);
}
}
void createMinHeap(int heap[], int len)
{
if (heap == NULL || len <= 0)
return;
int index = len / 2;
for(; index >= 1; -- index)
{
minHeapShift(heap, index, len);
}
}
3 向堆中插入一个元素
/*
*@func:insert new element into heap
*@param heap, the heap we insert to
*@param value, the element to be inserted
*@param currentLen, number of elements already in the heap
*@param maxLen, max number of elements the heap can contain
*@return: -1 error in heap, -2 no more sapce in heap, 1 insert success
*/
int insertToHeap(int heap[], int value, int *currentLen, int maxLen)
{
if (heap == NULL || maxLen <= 0 || currentLen == NULL)
return -1;
if (*currentLen >= maxLen)
return -2;
int index = *currentLen + 1;
int root = index >> 1;
for (; root >= 1 && value > heap[root];)
{
heap[index] = heap[root];
index >>= 1;
root = index >> 1;
}
heap[index] = value;
++ (*currentLen);
return 1;
}
4 删除堆顶元素
/*
*@func: remove root of heap
*@param heap: the heap remove from
*@param currentLen: number of elements already in the heap
*@return: -1 error in heap, 1 remove success
*/
int removeFromHeap(int heap[], int *currentLen)
{
if (heap == NULL || currentLen == NULL || (*currentLen) <= 0)
return -1;
if (*currentLen == 1)
{
heap[1] = 0;
-- (*currentLen);
return 1;
}
int index = *currentLen;
int last = heap[index --];
int current = 1, child = 2;
while (child <= index)
{
if (child < index && heap[child] < heap[child + 1])
++ child;
if (last >= heap[child])
break;
heap[current] = heap[child];
current = child;
child *= 2;
}
heap[current] = last;
-- (*currentLen);
return 1;
}
5 删除堆中指定位置的元素
void maxHeapUpShift(int heap[], int index, int len)
{
if (heap == NULL || index <= 0 || len <= 0 || index > len)
return;
int tmp = 0;
int i = index;
int root = i >> 1;
for (; root >= 1 && heap[root] < heap[i];)
{
tmp = heap[i];
heap[i] = heap[root];
heap[root] = tmp;
i >> 1;
root = i >> 1;
}
}
/*
*@func: remove element from given index
*@param heap: pointer to heap array
*@param index: given location contain the element to be removed
*@param currentSize: pointer to current size of heap
*@return: -1 error in heap, -2 error index,
*/
int removeFromIndex(int heap[], int index, int *currentSize)
{
if (heap == NULL || index <= 0 || currentSize == NULL || *currentSize <= 0)
return -1;
if (index > *currentSize)
return -2;
int last = heap[*currentSize];
if (last == heap[index])
{
heap[*currentSize] = 0;
-- (*currentSize);
return 1;
}
else if (last < heap[index])
{
heap[index] = last;
heap[*currentSize] = 0;
maxHeapDownShift(heap, index, *currentSize);
-- (*currentSize);
return 1;
}
else
{
heap[index] = last;
heap[*currentSize] = 0;
maxHeapUpShift(heap, index, *currentSize);
-- (*currentSize);
return 1;
}
}
6 堆排序
void heapSort(int heap[], int len)
{
if (heap == NULL || len <= 0)
return;
createMaxHeap(heap, len);
int temp = heap[1];
heap[1] = heap[len];
heap[len] = temp;
heapSort(heap, len - 1);
}
7 一个测试例子
找出n个数中最小的k个。
int main()
{
int k = 10;
int currentSize = k;
int maxSize = k * 2;
int *maxHeap = (int*)malloc(sizeof(int) * (maxSize+1));
int *minHeap = (int*)malloc(sizeof(int) * (maxSize+1));
FILE *fp = fopen("data.txt", "r");
if (maxHeap == NULL || fp == NULL || minHeap == NULL)
return 0;
int i;
for (i = 1; i <= k; ++ i)
{
fscanf(fp, "%d", &maxHeap[i]);
minHeap[i] = maxHeap[i];
}
createMaxHeap(maxHeap, k);
createMinHeap(minHeap, k);
int newData;
while (fscanf(fp, "%d", &newData) != EOF)
{
if (newData < maxHeap[1])
{
maxHeap[1] = newData;
maxHeapShift(maxHeap, 1, k);
}
else if (newData > minHeap[1])
{
minHeap[1] = newData;
minHeapShift(minHeap, 1, k);
}
}
for (i = 1; i <= k; ++ i)
printf("%d ", maxHeap[i]);
printf("\n");
for (i = 1; i <= k; ++ i)
printf("%d ", minHeap[i]);
printf("\n");
heapSort(maxHeap, k);
for (i = 1; i <= k; ++ i)
printf("%d ", maxHeap[i]);
printf("\n");
heapSort(minHeap, k);
for (i = 1; i <= k; ++ i)
printf("%d ", minHeap[i]);
printf("\n");
createMaxHeap(maxHeap, k);
printf("max heap\n");
for (i = 1; i <= currentSize; ++ i)
printf("%d ", maxHeap[i]);
printf("\n");
int res = insertToHeap(maxHeap, 2013, ¤tSize, maxSize);
printf("insert %d\n", res);
for (i = 1; i <= currentSize; ++ i)
printf("%d ", maxHeap[i]);
printf("\n");
printf("delete root\n");
removeFromHeap(maxHeap, ¤tSize);
for (i = 1; i <= currentSize; ++ i)
printf("%d ", maxHeap[i]);
printf("\n");
res = removeFromIndex(maxHeap,6, ¤tSize);
printf("remove from index %d\n", res);
for (i = 1; i <= currentSize; ++ i)
printf("%d ", maxHeap[i]);
printf("\n");
fclose(fp);
free(maxHeap);
free(minHeap);
return 0;
}