《数据结构与算法分析——c语言描述》 第六章
用到了高中的等比数列求和知识。找最小值的地方稍微改进了一下,首先找到第一个元素。然后再走常规的比较查找最小值。不是所有类型都有最小值。
以前写的代码很少写注释。现在要开始写了。因为不写的话自己也不能很快对上思路。
binomialqueue.h
#ifndef _BinomialQueue_H #define _BinomialQueue_H typedef int ElementType; struct BinNode; typedef struct BinNode *BinTree; typedef struct Collection *BinQueue; BinQueue initialize(void); ElementType findMin(BinQueue h); int isEmpty(BinQueue h); BinQueue merge(BinQueue h1, BinQueue h2); void insert(ElementType X, BinQueue h); void deleteMin(BinQueue h); #endif // !_BinHeap_H
#include"binomialqueue.h" #include"fatal.h" #define MAXTREES 25 #define CAPACITY ((1<<MAXTREES)-1)//容量是2^0+2^1+2^3+2^(MAXTREES-1) typedef struct BinNode *Position; struct BinNode { ElementType element; Position leftChild; Position nextSibling; }; struct Collection { int currentSize; BinTree theTrees[MAXTREES]; }; BinQueue initialize(void) { BinQueue h = malloc(sizeof(struct Collection)); if (h == NULL) Error("OUT OF MEMORY"); for (int i = 0; i < MAXTREES; i++) h->theTrees[i] = NULL; h->currentSize = 0; return h; } ElementType findMin(BinQueue h) { if (isEmpty(h)) Error("EMPTY HEAP"); ElementType minElem; int i,j; for (i = 0,j=1; j <= h->currentSize; i++,j*=2) {//找到第一个的二项树的根,j代表i二项树结点的个数,最大的二项树的下一个二项树的结点的个数比currentSize的最大值大1 if (h->theTrees[i] != NULL) { minElem = h->theTrees[i]->element; break; } } for (; j <= h->currentSize; i++, j *= 2) {//再和剩下的比较 if (h->theTrees[i] && h->theTrees[i]->element < minElem) { minElem = h->theTrees[i]->element; } } return minElem; } int isEmpty(BinQueue h) { return h->currentSize == 0; } static BinTree combineTrees(BinTree t1, BinTree t2) { if (t1->element > t2->element) return combineTrees(t2, t1); else { t2->nextSibling = t1->leftChild;//leftchild指向高度高的二项树,高度依次从nextSibling减少 t1->leftChild = t2; return t1; } } BinQueue merge(BinQueue h1, BinQueue h2) { BinTree t1, t2; BinTree carry = NULL; int carrt_tag; if (h1->currentSize + h2->currentSize > CAPACITY) Error("TOO MUCH ELEM"); h1->currentSize += h2->currentSize; for (int i = 0,j=1; j <= h1->currentSize; i++,j*=2) { t1 = h1->theTrees[i]; t2 = h2->theTrees[i]; if (carry) carrt_tag = 1; else carrt_tag = 0; switch (!!t1 + 2 * !!t2 + 4 * carrt_tag) { case 0://t1,t2,carry空 break; case 1://t1非空 break; case 2://t2非空 h1->theTrees[i] = t2; h2->theTrees[i] = NULL; break; case 3://t1,t2非空 carry = combineTrees(t1, t2); h1->theTrees[i] = NULL; h2->theTrees[i] = NULL; break; case 4://carry非空 h1->theTrees[i] = carry; carry = NULL; break; case 5://t1,carry非空 carry = combineTrees(t1, carry); h1->theTrees[i] = NULL; break; case 6://t2, carry非空 carry = combineTrees(t2, carry); h2->theTrees[i] = NULL; break; case 7: h1->theTrees[i] = carry; carry = combineTrees(t1, t2); h2->theTrees[i] = NULL; break; default: Error("error"); break; } } return h1; } void insert(ElementType X, BinQueue h) { BinQueue temp = initialize(); temp->currentSize = 1; temp->theTrees[0] = malloc(sizeof(struct BinNode)); if (temp->theTrees[0] == NULL) Error("OUT OF MEMORY"); temp->theTrees[0]->element = X; temp->theTrees[0]->leftChild = NULL; temp->theTrees[0]->nextSibling = NULL; merge(h, temp); free(temp); } void deleteMin(BinQueue h) { if (isEmpty(h)) Error("EMPTY HEAP"); int minTree; ElementType minElem; int i,j; for (i = 0,j=1; j<=h->currentSize; i++,j*=2) { if (h->theTrees[i] != NULL) { minElem = h->theTrees[i]->element; minTree = i; i++; break; } } for (; j <= h->currentSize; i++, j *= 2) { if (h->theTrees[i] && h->theTrees[i]->element < minElem) { minElem = h->theTrees[i]->element; minTree = i; } } BinQueue deleteQueue = initialize(); deleteQueue->currentSize = (1 << minTree) - 1;//mintree的儿子有mintree个,结点个数加起来就是 (1 << minTree) - 1 Position p = h->theTrees[minTree]->leftChild;//高度从大到小 for (int i = minTree - 1; i >= 0; i--, p = p->nextSibling) { deleteQueue->theTrees[i] = p; } free(h->theTrees[minTree]); h->theTrees[minTree] = NULL; h->currentSize -= (deleteQueue->currentSize + 1); merge(h, deleteQueue); free(deleteQueue); }