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

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


避免merge(H,H)

H2中没有树留下且Carry树为NULL,修改merge例程以终止合并

修改merge使得较少的树总被合并到较大的树中


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);
BinQueue deleteMin(BinQueue h);
#endif // !_BinHeap_H


binomialqueue.cpp

#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;
}


main.cpp

#include"binomialqueue.h"
#include<stdlib.h>
#include<stdio.h>
#include"fatal.h"
int 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 a[99999999];

int main() {
	int n;
	scanf("%d", &n);
	//int *a = malloc(sizeof(int)*n);
	//if (a == NULL)
	//	fprintf(stderr,"out of memory");
	getRandomInt(a, n);

	


	BinQueue h = initialize();


	for (int i = 0; i < n; i++)
		insert(a[i], h);

	int cnt = 1;
	for (int i = 0; i < n; i++) {
		if (cnt == findMin(h))
			cnt++;
		
		h= deleteMin(h);
	}

	//destroy(h);
	//free(a);

}


你可能感兴趣的:(《数据结构与算法分析——c语言描述》 练习6.32 答案)