2010北邮上机真题——哈夫曼树

题目描述:

哈夫曼树,第一行输入一个数n,表示叶结点的个数。需要用这些叶结点生成哈夫曼树,根据哈夫曼树的概念,这些结点有权值,即weight,题目需要输出所有结点的值与权值的乘积之和。

输入:

输入有多组数据。
每组第一行输入一个数n,接着输入n个叶节点(叶节点权值不超过100,2<=n<=1000)。

输出:

输出权值。

样例输入:
5  
1 2 2 5 9
样例输出:
37


我的困惑

(1)用的数组建立哈夫曼树,然后求出wpl,但是九度上总是报出runtime error的错误,太困惑了,求指导啊,为什嘛啊
(2)用链表实现的哈夫曼树就可以ac,蛋疼啊!

实现代码


顺序表未ac代码

#include <stdio.h>
#include <stdlib.h>
#define N 2000
#define M 2 * N - 1
#define MAX 1000

struct hfm
{
	int weight;
	int lchild;
	int rchild;
	int parent;
};

void initHfmtree(struct hfm *);
void createHfmtree(struct hfm*, int, int);
void calculateLength(struct hfm*, int);

int main()
{
	int n, m, i;
	struct hfm htree[M];
	while(scanf("%d", &n) != EOF)
	{
		m = 2 * n - 1;
		initHfmtree(htree);

		for(i = 0; i < n; i ++)
		{
			scanf("%d", &htree[i].weight);
		}

		createHfmtree(htree, n, m);

		calculateLength(htree, n);
	}

	return 0;
}

void initHfmtree(struct hfm *htree)
{
	int i;

	for(i = 0; i < M; i ++)
	{
		htree[i].weight = 0;
		htree[i].lchild = htree[i].rchild = htree[i].parent = -1;
	}
}

void createHfmtree(struct hfm *htree, int n, int m)
{
	int m1, m2, loc1, loc2, i, k;
	for(i = n; i < m; i ++)
	{
		m1 = m2 = MAX;
		loc1 = loc2 = -1;

		for(k = 0; k < i; k ++)
		{
			if(htree[k].parent == -1)
			{
				if(htree[k].weight < m1)
				{
					m2 = m1;
					loc2 = loc1;
					m1 = htree[k].weight;
					loc1 = k;	
				}else if(htree[k].weight < m2)
				{
					loc2 = k;
					m2 = htree[k].weight;
				}
			}
		}

		htree[loc1].parent = i;
		htree[loc2].parent = i;

		htree[i].weight = m1 + m2;
		htree[i].lchild = loc1;
		htree[i].rchild = loc2;
	}
}

void calculateLength(struct hfm *htree, int n)
{
	int p, i, count, sum;

	sum = 0;

	for(i = 0; i < n; i ++)
	{
		count = 0;
		p = htree[i].parent;

		while(p != -1)
		{
			count ++;
			p = htree[p].parent;
		}

		sum += count * htree[i].weight;
	}
	printf("%d\n", sum);
}

链表ac代码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

//哈夫曼结点类型定义
struct huffmancode
{
	int power;
	struct huffmancode *lchild;
	struct huffmancode *rchild;
	struct huffmancode *next;
};

//栈类型定义
struct stack
{
	struct huffmancode* data[100];
	int top;
};

//函数声明
void addNode(struct huffmancode*, struct huffmancode *);
struct huffmancode* createHuffmanTree(int, int *);
void preTraverse(struct huffmancode*);
int getWPL(struct huffmancode*, int);
void freeHuffmantree(struct huffmancode *);


int main()
{
	int n, i, wpl;
	int weight[1001];
	struct huffmancode *root;

	while(scanf("%d", &n) != EOF)
	{
		//接收权值数据
		for(i = 0; i < n; i ++)
		{
			scanf("%d", weight + i);
		}

		//构建哈夫曼树
		root = createHuffmanTree(n, weight);

		//获取wpl
		wpl = getWPL(root, 0);
		printf("%d\n", wpl);

		//清理哈夫曼树
		freeHuffmantree(root);
	}

	return 0;
}

/**
 * Description:构建哈夫曼树
 */
struct huffmancode* createHuffmanTree(int n, int *weight)
{
	int i;
	struct huffmancode *head, *pl, *pr, *proot;
	head = (struct huffmancode *)malloc(sizeof(struct huffmancode));
	head->next = NULL;

	//初始化森林
	for(i = 0; i < n; i ++)
	{	
		struct huffmancode *pnode = (struct huffmancode *)malloc(sizeof(struct huffmancode));
		pnode->power = *(weight + i);
		pnode->lchild = pnode->rchild = pnode->next = NULL;
		addNode(head, pnode);
	}

	//构造哈夫曼树
	while(head->next->next)
	{
		//只有一个节点的情况
		if(!head->next->next)
		{
			break;
		}

		//从单链表中取出节点最小的两个点
		pl = head->next;
		pr = pl->next;

		//删除pl、pr结点,加入到哈夫曼树中
		head->next = pr->next;
		proot = (struct huffmancode *)malloc(sizeof(struct huffmancode));
		proot->power = pl->power + pr->power;
		proot->lchild = pl;
		proot->rchild = pr;
		addNode(head, proot);
	}		

	return head->next;
}

/**
 * Description:添加节点
 */
void addNode(struct huffmancode *head, struct huffmancode *pnode)
{
	struct huffmancode *t = head;

	//找到第一个权值大于给定结点的结点,t指定该结点的前一结点
	while(t->next && t->next->power < pnode->power)
	{
		t = t->next;
	}
	pnode->next = t->next;
	t->next = pnode;
}

/**
 * Description:前序遍历
 */
void preTraverse(struct huffmancode *root)
{
	struct huffmancode *head = root;
	struct stack *s = (struct stack *)malloc(sizeof(struct stack));
	s->top = 0;

	while(head || s->top > 0)
	{
		if(head)
		{
			printf("%d ", head->power);
			s->data[s->top ++] = head;
			head = head->lchild;
		}else
		{
			head = s->data[-- s->top];
			head = head->rchild;
		}

	}
}

/**
 * Description:获取哈夫曼树的带权路径长度
 */
int getWPL(struct huffmancode *root, int level)
{
	if(!root)
	{
		return 0;
	}
	if(!root->lchild && !root->rchild)
	{
		return root->power * level;
	}
	
	return getWPL(root->lchild, level + 1) + getWPL(root->rchild, level + 1);
}

/**
 * Description:清理哈夫曼树
 */
void freeHuffmantree(struct huffmancode *root)
{
	if(!root)
	{
		return;
	}
	freeHuffmantree(root->lchild);
	freeHuffmantree(root->rchild);
	free(root);
}


后记

各位,留言指导我一下吧,真心是求指导啊,不知道哪里就数组越界了!!
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值