Binomial Queue

Time complexity

Find min: O(logN)
Merge: O(logN)
Insert: average time is const, worst case is O(N)
A binomial queue of N elements can be built by N successive insertions in O(N) time.
T w o r s t = O ( l o g N ) , T_{worst} = O(log N), Tworst=O(logN), but T a m o r t i z e d = 2 T_{amortized} = 2 Tamortized=2

methods

left-child-next-sibling
the new tree will be the largest
maintain the subtrees in decreasing order

code
#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 = (BinQueue)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) {//h2合并到h1当中
	if (h1 == h2)
		return h1;
	BinTree t1, t2;
	BinTree carry = NULL;
	int carrt_tag;
	if (h1->currentSize + h2->currentSize > CAPACITY)
		Error("TOO MUCH ELEM");
	if (h1->currentSize < h2->currentSize) {
		//互换
		BinQueue temp;
		temp = h1;
		h1 = h2;
		h2 = temp;
	}
	h1->currentSize += h2->currentSize;
	int h2Size = 0;
	for (int i = 0, j = 1; j <= h1->currentSize; i++, j *= 2) {//统计h2中树的数量
		if (h2->theTrees[i] != NULL)
			h2Size++;
	}
	for (int i = 0, j = 1; (carry || h2Size) && 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;
			h2Size--;
			break;
		case 3://t1,t2非空
			carry = combineTrees(t1, t2);
			h1->theTrees[i] = NULL;
			h2->theTrees[i] = NULL;
			h2Size--;
			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;
			h2Size--;
			break;
		case 7:
			h1->theTrees[i] = carry;
			carry = combineTrees(t1, t2);
			h2->theTrees[i] = NULL;
			h2Size--;
			break;
		default:
			Error("error");
			break;
		}
	}
	return h1;
}
 
void insert(ElementType X, BinQueue h) {
	BinTree t1;
	BinTree carry = (BinTree)malloc(sizeof(struct BinNode));
	if (carry == NULL)
		Error("EMPTY MEOERY");
	carry->element = X;
	carry->leftChild = carry->nextSibling = NULL;
	int carrt_tag;
	if (h->currentSize + 1 > CAPACITY)
		Error("TOO MUCH ELEM");
	h->currentSize += 1;
	int i = 0;
	while (carry != NULL) {
		t1 = h->theTrees[i];
		if (carry)
			carrt_tag = 1;
		else
			carrt_tag = 0;
		switch (!!t1 + 2 * !!carrt_tag) {
		case 0://t1,t2,carry空
			break;
		case 1://t1非空
			break;
		case 2://carry非空
			h->theTrees[i] = carry;
			carry = NULL;
			break;
		case 3://t1,carry非空
			carry = combineTrees(t1, carry);
			h->theTrees[i] = NULL;
			break;
		default:
			Error("error");
			break;
		}
		i++;
	}
}
 
BinQueue 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);
	return h;
}

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值