最大最小堆

来源:互联网 发布:天猫淘宝网商城首页 编辑:程序博客网 时间:2024/06/11 15:50

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;elselarge = 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;elsesmallIndex = 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;}