利用最小堆生成哈弗慢树

#include<stdio.h>

#include<stdlib.h>

struct HaTree {

int weight;

HaTree *left;

HaTree *right;

};

struct MinHeap {

//data代表HaTree的数组,也就是数组,只不过动态指定大小的 

//size记录当前堆的元素个数

//capacity 记录堆的最大容量, 

HaTree *data;

int size;

int capacity;

};

//最小堆的初始化

MinHeap* createMinHeap(int capacity) {

MinHeap * h = (MinHeap *)malloc(sizeof(MinHeap));

h->data = (HaTree *)malloc((capacity + 1) * sizeof(HaTree));

h->size = 0;

h->capacity = capacity;

h->data[0].weight = -100000;

h->data[0].left = NULL;

h->data[0].right = NULL;

return h;

}

//最小堆插入元素,这个是为了提供当构造哈夫曼数产生新的节点时要插入最小堆使用的插入函数

void insertMinHeap(MinHeap *head, HaTree *T) {

//判断该堆是否满了 

if (head->size == head->capacity) {

	printf("该最小堆已经满了\n");
	
	return;
}

int i = head->size;

//表示添加了一个元素 

i++;

head->size++;

for (; head->data[i / 2].weight > T->weight; i = i / 2) {

	head->data[i].weight = head->data[i / 2].weight;
	
	head->data[i].left = head->data[i / 2].left;
	
	head->data[i].right = head->data[i / 2].right;
	
}
//新插入的节点必定有左右子树,所以不为空

head->data[i].weight = T->weight;

head->data[i].left = T->left;

head->data[i].right = T->right;

}

// 最小堆插入元素(个人没有采用另外一种方式,先把数据插入到堆中,然后进行调整)

//个人采用的每次插入一个元素后,此时已经是最小堆啦 ,这种方式比较浪费时间,但是容易理解

void init_insert_heap(MinHeap *head, int w) {

//判断该堆是否满了 

if (head->size == head->capacity) {

	printf("该最小堆已经满了\n");
	
	return;
}

int i = head->size;

//表示添加了一个元素 

i++;

head->size++;

for (; head->data[i / 2].weight > w; i = i / 2) {

	head->data[i].weight = head->data[i / 2].weight;
	

}

//这个地方为啥要把左右子树为空,因为这些点最终都哈夫曼树的叶子节点,左右子树都空

head->data[i].weight = w;

head->data[i].left = NULL;

head->data[i].right = NULL;

}

//删除最小堆中的最小元素

HaTree * delete_min(MinHeap *head) {

if (head->size == 0) {

	printf("最小堆已经空了,请检查下你的操作\n");
	
	return NULL;
}

HaTree *node = (HaTree *)malloc(sizeof(HaTree));

node->weight = head->data[1].weight;

node->left = head->data[1].left;

node->right = head->data[1].right;

int parent, child = 0;

//这么写的目的为了好理解 

int temp = head->data[head->size].weight;

head->size--;

for (parent = 1; parent * 2 <= head->size; parent = child) {

	child = parent * 2;
	
	if (child != head->size && (head->data[child + 1].weight < head->data[child].weight))
	
		child++;

	if (head->data[child].weight > temp)
	
		break;
		
	else {
		head->data[parent].weight = head->data[child].weight;
		
		head->data[parent].left = head->data[child].left;
		
		head->data[parent].right = head->data[child].right;
	}
}

head->data[parent].weight = temp;

//注意理解head->size+1 和head->size++ 

head->data[parent].left = head->data[head->size + 1].left;

head->data[parent].right = head->data[head->size + 1].right;

//返回取出的最小堆的节点 

return node;

}

//建立哈夫曼树

HaTree * buildTree(MinHeap *head) {

HaTree *ha = NULL;

//最后一个直接从最小堆中取出,所以注意判断的条件 

while (head->size>1)

 {
	ha = (HaTree *)malloc(sizeof(HaTree));
	
	ha->left = delete_min(head);
	
	ha->right = delete_min(head);
	
	ha->weight = ha->left->weight + ha->right->weight;
	
	insertMinHeap(head, ha);

}

ha = delete_min(head);

return ha;

}

//遍历下哈夫曼树,先序遍历

void preOrder(HaTree *p) {

if (p) {

	printf("%d\n", p->weight);
	
	preOrder(p->left);
	
	preOrder(p->right);
}

}

int main() {

MinHeap * head = createMinHeap(20);

int a[] = { 1,3,4,5 };

int length = sizeof(a) / sizeof(a[0]);

//对哈夫曼树的进行权重的初始化 

for (int i = 0; i < length; i++) {

	init_insert_heap(head, a[i]);
}

HaTree *p = buildTree(head);

preOrder(p);

printf("hello");

system("pause");

return 0;

}

转载于:https://my.oschina.net/u/2511906/blog/3093392

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
上机实验2 栈和队列及其应用 停车场的管理 [问题描述] 设停车场是一个可停放n辆汽车的狭长通道,且只有一个门可供出入。汽车在停车场内按车辆到达时间的先后顺序,依次由北向南排列(门在最南端,最先到达的第一辆车停放在车场的最北端),若车场内已停满n辆汽车,则后来的汽车只能在门外的便道上等候,一旦有车开走,则排在便道上的第一辆汽车即可开入;当停车场内某辆车要离开时,在它之后进入的车辆必须先退出车场为它让路,待该辆车开出大门外,其他车辆再按原顺序进入车场,每辆停放在车场的车在它离开停车场时必须按它停留的时间长短交纳费用。试为停车场编制按上述要求进行管理的模拟程序。 [基本要求] 以栈来模拟停车场,以队列来模拟车场外的便道。按照从中端读入的输入数据序列进行模拟管理。每一组输入数据包括三个数据项:汽车“到达”或“离去”信息,汽车的牌照号以及汽车到达或离去的时刻。对每一组输入数据进行操作后的输出信息为:若是车辆到达,则输出汽车在停车场内或便道上的停车位置;若是车辆离去,则输出汽车在停车场内停留的时间和应交纳的费用(便道上停留的时间不收费)。栈以顺序结构实现,队列以链表结构实现。 [测试数据] (1) 设n=2,输入数据为:('A',1,5),('A',2,10),('D',1,15),('A',3,20),('A',4,25),('A',5,30),('D',2,35),('D',4,40),('E',0,0).’A'表示Arrival,'D'表示Departure;'E'表示输入结束End. (2) 自定义测试数据 [提示] 需另设一个栈,临时停放为给要离去的汽车让路而从停车场退出来的汽车,也可用顺序存储结构实现。输入数据按到达或离去的时刻有序。栈中每个元素表示一辆汽车,包含两个数据项:汽车的牌照浩和进入停车场的时刻。 [选做] (1) 汽车可有不同种类,根据占地面积收费标准不同。如1辆客车和2辆小汽车的占地面积相当,1辆大型货车的面积相当于3辆小汽车的占地面积,如何修改数据结构,满足上述收费标准。 (2) 若汽车可直接从便道开走,则排在它前面的汽车要先让道,然后按原顺序恢复排队队列,如何实现?

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值