最小-最大堆

来源:互联网 发布:网络上调查公司可靠吗 编辑:程序博客网 时间:2024/06/01 17:27

《数据结构与算法分析——c语言描述》 练习6.15 答案


根据题目的两条要求,可以推出:

1.偶数层的儿子比父亲大(注意,不是偶数层的全部逐渐增大)

2.奇数层的儿子比父亲小(注意,不是奇数层的全部逐渐增大)

3.有1.2两条,可以知道,根节点是偶数层中最小的,第二层的两个结点其中一个是奇数层最大的(另一个可不一定是第二大!,因为这是两个不同的分支)。最低端的偶数层小于奇数层,由大小关系递推,所以知道最小元就是根节点。最大元位于第二层。


插入:

插入一个节点,根据层数判断符不符合小于(或大于)父亲,(可能存在交换),再和祖父比较,若符合则停止(可以根据插入法则推出偶数层奇数层是符合上面的1,2的)。不符合则上滤。


删除:

找出要找的元,然后根据层进行下滤。下滤的时候要判断是否符合规则,同时利用堆原有的大小关系。。。我也不知道怎么说。。。。反正自己推一下就行了。。。。。


这道题难的是想出来方法。。代码实现并不难。


参考:

blog.csdn.net/kinado/article/details/8552739     //这个代码好像是错的

josephpei.github.io/2013/12/23/minmaxheap-%E6%9C%80%E5%B0%8F%E6%9C%80%E5%A4%A7%E5%A0%86/           这个是正确的。


五月总结:

1-21日代码写得挺嗨的。最开心是10-20日。后面十天各种琐碎作业考试什么鬼的都要应付。。。

六月要考英语了。。。计划这个月发31篇吧。。。。

本来这篇是计划六月开始之前发的。凑够五月的30篇。可是要考汇编语言。当然最主要的原因是自己懒。



minmaxheap.h

#ifndef _MinMaxHeap_H#define _MinMaxHeap_Htypedef int ElementType;struct HeapStruct;typedef struct HeapStruct *PriorityQueue;PriorityQueue initialize(int maxElements);PriorityQueue buildHeap(ElementType *arr, int n);void destroy(PriorityQueue h);void makeEmpty(PriorityQueue h);void insert(ElementType X, PriorityQueue h);ElementType deleteMin(PriorityQueue h);ElementType deleteMax(PriorityQueue h);int isEmpty(PriorityQueue h);int isFull(PriorityQueue h);//void decreaseKey(int pos, ElementType delta, PriorityQueue h);//void increaseKey(int pos, ElementType delta, PriorityQueue h);//void Delete(int pos, PriorityQueue h);#endif // !_BinHeap_H




minmaxheap.cpp

#include"minmaxheap.h"#include"fatal.h"#define MinPQSize 1#define MinData INT_MINstruct HeapStruct {int capacity;int size;ElementType* elements;};PriorityQueue initialize(int maxElements) {PriorityQueue h;if (maxElements < MinPQSize)Error("Priority queue size is too small");h = (PriorityQueue)malloc(sizeof(struct HeapStruct));if (h == NULL)Error("OUT OF MEMORY");h->elements = (ElementType *)malloc(sizeof(ElementType)*(maxElements + 1));//多出来的一个用于存放最小的元素,其用来和堆顶比较if (h->elements == NULL)Error("OUT OF MEMORY");h->capacity = maxElements;h->size = 0;h->elements[0] = MinData;return h;}static int isEvenDepth(int pos) {//是不是偶数层while (pos > 1)//不是根节点pos = pos >> 2;//获得祖父return pos == 1;//此时pos只能在第一层和第二层}static void evenPercolateUp(int pos, PriorityQueue h) {//上滤,在偶数层逐渐向上ElementType elem = h->elements[pos];int i;for (i = pos; h->elements[i / 4] > elem; i /= 4)h->elements[i] = h->elements[i / 4];h->elements[i] = elem;}static void oddPercolateUp(int pos, PriorityQueue h) {//下滤,在奇数层逐渐向上ElementType elem = h->elements[pos];int i;for (i = pos; i > 3 && h->elements[i / 4] < elem; i /= 4)//i>3是为了不要冲过第二层h->elements[i] = h->elements[i / 4];h->elements[i] = elem;}static int evenPercolateDown(int pos, PriorityQueue h) {//偶数层下滤ElementType elem = h->elements[pos];int i, firstGrandChild, minGrandChild;for (i = pos; i < h->size; i = minGrandChild) {minGrandChild = firstGrandChild = i * 4;if (firstGrandChild > h->size) {//孙子越界int child = i * 2;if (child <= h->size) {//有孩子,child此时奇数层if (child<h->size && h->elements[child]>h->elements[child + 1]) //获得最小儿子child++;if (h->elements[child] < elem) {//奇数层儿子比偶数层父亲大,不符合规则,互换ElementType temp = h->elements[child];h->elements[child] = elem;elem = temp;}}break;}for (int i = 1; i < 4; i++) {//找最小的孙子if (firstGrandChild + i <= h->size&& h->elements[minGrandChild] > h->elements[firstGrandChild + i])minGrandChild = firstGrandChild + i;}if (elem > h->elements[minGrandChild]) {//要下滤h->elements[i] = h->elements[minGrandChild];int child = i * 2;//elem比最小孙子大,可能大于奇数层的两个儿子if (h->elements[child + 1] < h->elements[child])//找出最小儿子child++;if (h->elements[child] < elem)//奇数层父亲小于偶数层孙子,交换{ElementType temp = h->elements[child];h->elements[child] = elem;elem = temp;}}elsebreak;}h->elements[i] = elem;return i;}static int oddPercolateDown(int pos, PriorityQueue h) {//奇数层下滤ElementType elem = h->elements[pos];int i, firstGrandChild, maxGrandChild;for (i = pos; i < h->size; i = maxGrandChild) {maxGrandChild = firstGrandChild = i * 4;if (firstGrandChild > h->size) {//孙子越界int child = i * 2;if (child <= h->size) {//有孩子,child此时偶数层if (child<h->size && h->elements[child]<h->elements[child + 1]) //获得最大儿子child++;if (h->elements[child] > elem) {//偶数层儿子比奇数层父亲大,不符合规则,互换ElementType temp = h->elements[child];h->elements[child] = elem;elem = temp;}}break;}for (int i = 1; i < 4; i++) {//找最大的孙子if (firstGrandChild + i <= h->size&& h->elements[maxGrandChild] < h->elements[firstGrandChild + i])maxGrandChild = firstGrandChild + i;}if (elem < h->elements[maxGrandChild]) {//要下滤h->elements[i] = h->elements[maxGrandChild];int child = i * 2;//elem比最大孙子小,可能小于偶数层的两个儿子if (h->elements[child + 1] > h->elements[child])//找出最大儿子child++;if (h->elements[child] >  elem)//偶数层父亲小于奇数层孙子,交换{ElementType temp = h->elements[child];h->elements[child] = elem;elem = temp;}}elsebreak;}h->elements[i] = elem;return i;}PriorityQueue buildHeap(ElementType *arr, int n) {PriorityQueue h = initialize(n);h->size = n;for (int i = 0; i < n; i++) {h->elements[i + 1] = arr[i];}for (int i = n / 2; i > 0; i--) {if (isEvenDepth(i))evenPercolateDown(i, h);elseoddPercolateDown(i, h);}return h;}void destroy(PriorityQueue h) {free(h->elements);free(h);}void makeEmpty(PriorityQueue h) {h->size = 0;}void insert(ElementType X, PriorityQueue h) {if (isFull(h))Error("priority queue is full");int i = ++h->size;h->elements[i] = X;if (i == 1)return;if (isEvenDepth(i)) {if (h->elements[i / 2] > h->elements[i])//父亲在奇数层evenPercolateUp(i, h);else {//奇数层父亲比偶数层儿子小ElementType temp = h->elements[i];h->elements[i] = h->elements[i / 2];h->elements[i / 2] = temp;oddPercolateUp(i / 2, h);}}else {//奇数层if (h->elements[i / 2] < h->elements[i])//父亲在偶数层oddPercolateUp(i, h);else {//偶数父亲比奇数层儿子大ElementType temp = h->elements[i];h->elements[i] = h->elements[i / 2];h->elements[i / 2] = temp;evenPercolateUp(i / 2, h);}}}ElementType deleteMin(PriorityQueue h) {//int i;ElementType minElement, lastElement;if (isEmpty(h))Error("priority queue is empty");minElement = h->elements[1];lastElement = h->elements[h->size--];//删除右下的元素h->elements[1] = lastElement;i = evenPercolateDown(1, h);return minElement;}int isEmpty(PriorityQueue h) {return h->size == 0;}int isFull(PriorityQueue h) {return h->size == h->capacity;}ElementType deleteMax(PriorityQueue h) {if (isEmpty(h))Error("EMPTY HEAP");if (h->size<=2)return h->elements[h->size--];else {int maxPos = 2;if (h->elements[3] > h->elements[2]) {maxPos = 3;}ElementType maxElement = h->elements[maxPos];ElementType lastElement = h->elements[h->size--];h->elements[maxPos] = lastElement;oddPercolateDown(maxPos, h);return maxElement;}}/*void decreaseKey(int pos, ElementType delta, PriorityQueue h) {if (pos<1 || pos>h->size)Error("Positon Error");ElementType changedElem = h->elements[pos] - delta;int i;for (i = pos; h->elements[i / 2] > changedElem; i /= 2) {h->elements[i] = h->elements[i / 2];}h->elements[i] = changedElem;}void increaseKey(int pos, ElementType delta, PriorityQueue h) {if (pos<1 || pos>h->size)Error("Positon Error");ElementType changedElem = h->elements[pos] + delta;int i, child;for (i = pos; i < h->size; i = child) {child = i * 2;if (child > h->size)break;if (child != h->size&&h->elements[child] > h->elements[child + 1])child++;if (changedElem > h->elements[child])h->elements[i] = h->elements[child];elsebreak;}h->elements[i] = changedElem;}void Delete(int pos, PriorityQueue h) {if (pos<1 || pos>h->size)Error("Positon Error");for (int i = pos; i > 1; i /= 2) {h->elements[i] = h->elements[i / 2];}deleteMin(h);}*/




main.cpp


#include"minmaxheap.h"#include<stdlib.h>#include<stdio.h>#include"fatal.h"#define N 20222int RandInt(int i, int j) {int temp;temp = (int)(i + (1.0*rand() / RAND_MAX)*(j - i));return temp;}void getRandomInt(int *A, int n) {for (int i = 0; i < n; i++) {A[i] = i + 1;}for (int i = 1; i < n; i++) {//std::swap(A[i], A[RandInt(0, i)]);  int randAdrr = RandInt(0, i);int t = A[i];A[i] = A[randAdrr];A[randAdrr] = t;}}int main() {int a[N];getRandomInt(a, N);PriorityQueue h1 = initialize(N);PriorityQueue h2= buildHeap(a, N);for (int i = 0; i < N; i++) {insert(a[i], h1);}int cnt = 1;for (int i = 0; i < N; i++)if (cnt == deleteMin(h1) && cnt == deleteMin(h2))cnt++;elseError("error");destroy(h1);destroy(h2);PriorityQueue h3 = initialize(N);PriorityQueue h4 = buildHeap(a, N);for (int i = 0; i < N; i++) {insert(a[i], h3);}cnt = N;for (int i = 0; i < N; i++)if (cnt == deleteMax(h3) && cnt == deleteMax(h4))cnt--;elseError("error");destroy(h3);destroy(h4);}




0 0
原创粉丝点击