基于visual Studio2013解决算法导论之045斐波那契堆




题目

斐波那契堆


解决代码及点评

// 斐波那契堆.cpp : 定义控制台应用程序的入口点。
//

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<climits>
using namespace std;

//斐波那契结点ADT
struct FibonacciHeapNode {
	int key;       //结点
	int degree;    //度
	FibonacciHeapNode * left;  //左兄弟
	FibonacciHeapNode * right; //右兄弟
	FibonacciHeapNode * parent; //父结点
	FibonacciHeapNode * child;  //第一个孩子结点
	bool marked;           //是否被删除第1个孩子
};

typedef FibonacciHeapNode FibNode;

//斐波那契堆ADT
struct FibonacciHeap {
	int keyNum;   //堆中结点个数
	FibonacciHeapNode * min;//最小堆,根结点
	int maxNumOfDegree;   //最大度
	FibonacciHeapNode * * cons;//指向最大度的内存区域
};

typedef FibonacciHeap FibHeap;

/*****************函数申明*************************/
//将x从双链表移除
inline void FibNodeRemove(FibNode * x);

//将x堆结点加入y结点之前(循环链表中)
void FibNodeAdd(FibNode * x, FibNode * y);

//初始化一个空的Fibonacci Heap
FibHeap * FibHeapMake() ;

//初始化结点x
FibNode * FibHeapNodeMake();

//堆结点x插入fibonacci heap中
void FibHeapInsert(FibHeap * heap, FibNode * x);

//将数组内的值插入Fibonacci Heap
void FibHeapInsertKeys(FibHeap * heap, int keys[], int keyNum);

//将值插入Fibonacci Heap
static void FibHeapInsertKey(FibHeap * heap, int key);

//抽取最小结点
FibNode * FibHeapExtractMin(FibHeap * heap);

//合并左右相同度数的二项树
void FibHeapConsolidate(FibHeap * heap);

//将x根结点链接到y根结点
void FibHeapLink(FibHeap * heap, FibNode * x, FibNode *y);

//开辟FibHeapConsolidate函数哈希所用空间
static void FibHeapConsMake(FibHeap * heap);

//将堆的最小结点移出,并指向其有兄弟
static FibNode *FibHeapMinRemove(FibHeap * heap);

//减小一个关键字
void FibHeapDecrease(FibHeap * heap, FibNode * x, int key);

//切断x与父节点y之间的链接,使x成为一个根
static void FibHeapCut(FibHeap * heap, FibNode * x, FibNode * y);

//级联剪切
static void FibHeapCascadingCut(FibHeap * heap, FibNode * y);

//修改度数
void renewDegree(FibNode * parent, int degree);

//删除结点
void FibHeapDelete(FibHeap * heap, FibNode * x);

//堆内搜索关键字
FibNode * FibHeapSearch(FibHeap * heap, int key);

//被FibHeapSearch调用
static FibNode * FibNodeSearch(FibNode * x, int key);

//销毁堆
void FibHeapDestory(FibHeap * heap);

//被FibHeapDestory调用
static void FibNodeDestory(FibNode * x);

//输出打印堆
static void FibHeapPrint(FibHeap * heap);

//被FibHeapPrint调用
static void FibNodePrint(FibNode * x);
/************************************************/

//将x从双链表移除
inline void FibNodeRemove(FibNode * x) {
	x->left->right = x->right;
	x->right->left = x->left;
}

/*
将x堆结点加入y结点之前(循环链表中)
a …… y
a …… x …… y
*/
inline void FibNodeAdd(FibNode * x, FibNode * y) {
	x->left = y->left;
	y->left->right = x;
	x->right = y;
	y->left = x;
}

//初始化一个空的Fibonacci Heap
FibHeap * FibHeapMake() {
	FibHeap * heap = NULL;
	heap = (FibHeap *) malloc(sizeof(FibHeap));
	if (NULL == heap) {
		puts("Out of Space!!");
		exit(1);
	}
	memset(heap, 0, sizeof(FibHeap));
	return heap;
}

//初始化结点x
FibNode * FibHeapNodeMake() {
	FibNode * x = NULL;
	x = (FibNode *) malloc(sizeof(FibNode));
	if (NULL == x) {
		puts("Out of Space!!");
		exit(1);
	}
	memset(x, 0, sizeof(FibNode));
	x->left = x->right = x;
	return x;
}

//堆结点x插入fibonacci heap中
void FibHeapInsert(FibHeap * heap, FibNode * x) {
	if (0 == heap->keyNum) {
		heap->min = x;
	} else {
		FibNodeAdd(x, heap->min);
		x->parent = NULL;
		if (x->key < heap->min->key) {
			heap->min = x;
		}
	}
	heap->keyNum++;
}

//将数组内的值插入Fibonacci Heap
void FibHeapInsertKeys(FibHeap * heap, int keys[], int keyNum) {
	for (int i = 0; i < keyNum; i++) {
		FibHeapInsertKey(heap, keys[i]);
	}
}

//将值插入Fibonacci Heap
static void FibHeapInsertKey(FibHeap * heap, int key) {
	FibNode * x = NULL;
	x = FibHeapNodeMake();
	x->key = key;
	FibHeapInsert(heap, x);
}

//抽取最小结点
FibNode * FibHeapExtractMin(FibHeap * heap) {
	FibNode * x = NULL, * z = heap->min;
	if (z != NULL) {

		//删除z的每一个孩子
		while (NULL != z->child) {
			x = z->child;
			FibNodeRemove(x);
			if (x->right == x) {
				z->child = NULL;
			} else {
				z->child = x->right;
			}
			FibNodeAdd(x, z);//add x to the root list heap
			x->parent = NULL;
		}

		FibNodeRemove(z);
		if (z->right == z) {
			heap->min = NULL;
		} else {
			heap->min = z->right;
			FibHeapConsolidate(heap);
		}
		heap->keyNum--;
	}
	return z;
}

//合并左右相同度数的二项树
void FibHeapConsolidate(FibHeap * heap) {
	int D, d;
	FibNode * w = heap->min, * x = NULL, * y = NULL;
	FibHeapConsMake(heap);//开辟哈希所用空间
	D = heap->maxNumOfDegree + 1;
	for (int i = 0; i < D; i++) {
		*(heap->cons + i) = NULL;
	}

	//合并相同度的根节点,使每个度数的二项树唯一
	while (NULL != heap->min) {
		x = FibHeapMinRemove(heap);
		d = x->degree;
		while (NULL != *(heap->cons + d)) {
			y = *(heap->cons + d);
			if (x->key > y->key) {//根结点key最小
				swap(x, y);
			}
			FibHeapLink(heap, y, x);
			*(heap->cons + d) = NULL;
			d++;
		}
		*(heap->cons + d) = x;
	}
	heap->min = NULL;//原有根表清除

	//将heap->cons中结点都重新加到根表中,且找出最小根
	for (int i = 0; i < D; i++) {
		if (*(heap->cons + i) != NULL) {
			if (NULL == heap->min) {
				heap->min = *(heap->cons + i);
			} else {
				FibNodeAdd(*(heap->cons + i), heap->min);
				if ((*(heap->cons + i))->key < heap->min->key) {
					heap->min = *(heap->cons + i);
				}//if(<)
			}//if-else(==)
		}//if(!=)
	}//for(i)
}

//将x根结点链接到y根结点
void FibHeapLink(FibHeap * heap, FibNode * x, FibNode *y) {
	FibNodeRemove(x);
	if (NULL == y->child) {
		y->child = x;
	} else {
		FibNodeAdd(x, y->child);
	}
	x->parent = y;
	y->degree++;
	x->marked = false;
}

//开辟FibHeapConsolidate函数哈希所用空间
static void FibHeapConsMake(FibHeap * heap) {
	int old = heap->maxNumOfDegree;
	heap->maxNumOfDegree = int(log(heap->keyNum * 1.0) / log(2.0)) + 1;
	if (old < heap->maxNumOfDegree) {
		//因为度为heap->maxNumOfDegree可能被合并,所以要maxNumOfDegree + 1
		heap->cons = (FibNode **) realloc(heap->cons,
			sizeof(FibHeap *) * (heap->maxNumOfDegree + 1));
		if (NULL == heap->cons) {
			puts("Out of Space!");
			exit(1);
		}
	}
}

//将堆的最小结点移出,并指向其有兄弟
static FibNode *FibHeapMinRemove(FibHeap * heap) {
	FibNode *min = heap->min;
	if (heap->min == min->right) {
		heap->min = NULL;
	} else {
		FibNodeRemove(min);
		heap->min = min->right;
	}
	min->left = min->right = min;
	return min;
}

//减小一个关键字
void FibHeapDecrease(FibHeap * heap, FibNode * x, int key) {
	FibNode * y = x->parent;
	if (x->key < key) {
		puts("new key is greater than current key!");
		exit(1);
	}
	x->key = key;

	if (NULL != y && x->key < y->key) {
		//破坏了最小堆性质,需要进行级联剪切操作
		FibHeapCut(heap, x, y);
		FibHeapCascadingCut(heap, y);
	}
	if (x->key < heap->min->key) {
		heap->min = x;
	}
}

//切断x与父节点y之间的链接,使x成为一个根
static void FibHeapCut(FibHeap * heap, FibNode * x, FibNode * y) {
	FibNodeRemove(x);
	renewDegree(y, x->degree);
	if (x == x->right) {
		y->child = NULL;
	} else {
		y->child = x->right;
	}
	x->parent = NULL;
	x->left = x->right = x;
	x->marked = false;
	FibNodeAdd(x, heap->min);
}

//级联剪切
static void FibHeapCascadingCut(FibHeap * heap, FibNode * y) {
	FibNode * z = y->parent;
	if (NULL != z) {
		if (y->marked == false) {
			y->marked = true;
		} else {
			FibHeapCut(heap, y, z);
			FibHeapCascadingCut(heap, z);
		}
	}
}

//修改度数
void renewDegree(FibNode * parent, int degree) {
	parent->degree -= degree;
	if (parent-> parent != NULL) {
		renewDegree(parent->parent, degree);
	}
}

//删除结点
void FibHeapDelete(FibHeap * heap, FibNode * x) {
	FibHeapDecrease(heap, x, INT_MIN);
	FibHeapExtractMin(heap);
}

//堆内搜索关键字
FibNode * FibHeapSearch(FibHeap * heap, int key) {
	return FibNodeSearch(heap->min, key);
}

//被FibHeapSearch调用
static FibNode * FibNodeSearch(FibNode * x, int key) {
	FibNode * w = x, * y = NULL;
	if (x != NULL) {
		do {
			if (w->key == key) {
				y = w;
				break;
			} else if (NULL != (y = FibNodeSearch(w->child, key))) {
				break;
			}
			w = w->right;
		} while (w != x);
	}
	return y;
}

//销毁堆
void FibHeapDestory(FibHeap * heap) {
	FibNodeDestory(heap->min);
	free(heap);
	heap = NULL;
}

//被FibHeapDestory调用
static void FibNodeDestory(FibNode * x) {
	FibNode * p = x, *q = NULL;
	while (p != NULL) {
		FibNodeDestory(p->child);
		q = p;
		if (p == x) {
			p = NULL;
		} else {
			p = p->left;
		}
		free(q->right);
	}
}

//输出打印堆
static void FibHeapPrint(FibHeap * heap) {
	printf("The keyNum = %d\n", heap->keyNum);
	FibNodePrint(heap->min);
	puts("\n");
};

//被FibHeapPrint调用
static void FibNodePrint(FibNode * x) {
	FibNode * p = NULL;
	if (NULL == x) {
		return ;
	}
	p = x;
	do {
		printf(" (");
		printf("%d", p->key);
		if (p->child != NULL) {
			FibNodePrint(p->child);
		}
		printf(") ");
		p = p->left;
	}while (x != p);
}

int keys[10] = {1, 2, 3, 4, 5, 6, 7, 9, 10, 11};

int main() {
	FibHeap * heap = NULL;
	FibNode * x = NULL;
	heap = FibHeapMake();
	FibHeapInsertKeys(heap, keys, 10);
	FibHeapPrint(heap);

	x = FibHeapExtractMin(heap);
	printf("抽取最小值%d之后:\n", x->key);
	FibHeapPrint(heap);

	x = FibHeapSearch(heap, 11);
	if (NULL != x) {
		printf("查找%d成功,", x->key);
		FibHeapDecrease(heap, x, 8);
		printf("减小到%d后:\n", x->key);
		FibHeapPrint(heap);
	}

	x = FibHeapSearch(heap, 7);
	if (NULL != x) {
		printf("删除%d成功:\n", x->key);
		FibHeapDelete(heap, x);
		FibHeapPrint(heap);
	}

	FibHeapDestory(heap);
	system("pause");
	return 0;
} 



代码下载及其运行

代码下载地址:http://download.csdn.net/detail/yincheng01/6858815

解压密码:c.itcast.cn


下载代码并解压后,用VC2013打开interview.sln,并设置对应的启动项目后,点击运行即可,具体步骤如下:

1)设置启动项目:右键点击解决方案,在弹出菜单中选择“设置启动项目”


2)在下拉框中选择相应项目,项目名和博客编号一致

3)点击“本地Windows调试器”运行


程序运行结果









转载于:https://www.cnblogs.com/new0801/p/6177245.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值