二项队列

《数据结构与算法分析——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);
}


你可能感兴趣的:(二项队列)