哈夫曼树

前言

学习贪心算法的时候复习了一下哈夫曼树的构造,这里记录一下,参考链接:http://blog.csdn.net/zinss26914/article/details/8461596
主要是记录一道九度的哈夫曼树的题目

题目

题目描述:
哈夫曼树,第一行输入一个数n,表示叶结点的个数。需要用这些叶结点生成哈夫曼树,根据哈夫曼树的概念,这些结点有权值,即weight,题目需要输出所有结点的值与权值的乘积之和。
输入:
输入有多组数据。
每组第一行输入一个数n,接着输入n个叶节点(叶节点权值不超过100,2<=n<=1000)。
输出:
输出权值。
样例输入:
5  
1 2 2 5 9
样例输出:
37

ac代码


链表构建哈夫曼树(插入排序)

#include <stdio.h>
#include <stdlib.h>
#define max 1001

struct htree
{
	int weight;
	struct htree *lchild;
	struct htree *rchild;
	struct htree *next;
};

void addNode(struct htree *, struct htree *);
struct htree* createHfmtree(int *, int);
int getWpl(struct htree *, int);

int main()
{
	int w[max];
	int i, n, wpl;
	struct htree *ht;

	while(scanf("%d", &n) != EOF)
	{
		for(i = 0; i < n; i ++)
		{
			scanf("%d", &w[i]);
		}
		
		ht = createHfmtree(w, n);
		wpl = getWpl(ht, 0);
		printf("%d\n", wpl);
	}
	return 0;
}

struct htree* createHfmtree(int *w, int n)
{
	int i;
	struct htree *head, *pl, *pr, *proot;
	head = (struct htree *)malloc(sizeof(struct htree));
	head->next = NULL;

	for(i = 0; i < n; i ++)
	{
		struct htree *pnode = malloc(sizeof(struct htree));
		pnode->weight = *(w + i);
		pnode->lchild = pnode->rchild = pnode->next = NULL;
		addNode(head, pnode);
	}

	while(head->next)
	{
		if(head->next->next == NULL)
			break;
		pl = head->next;
		pr = pl->next;
		head->next = pr->next;
		proot = (struct htree *)malloc(sizeof(struct htree));
		proot->weight = pl->weight + pr->weight;
		proot->lchild = pl;
		proot->rchild = pr;
		addNode(head, proot);
	}
	return head->next;
}

void addNode(struct htree *head, struct htree *pnode)
{
	struct htree *t = head;

	while(t->next && t->next->weight < pnode->weight)
		t = t->next;
	pnode->next = t->next;
	t->next = pnode;
}

int getWpl(struct htree *ht, int level)
{
	if(ht == NULL)
		return 0;
	if(!ht->lchild && !ht->rchild) 
	{
		return ht->weight * level;
	}

	return getWpl(ht->lchild, level + 1) + getWpl(ht->rchild, level + 1);
}

最小堆+贪心(堆排序)

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

#define MAX 1001

void minHeapIfy(int *A, int i, int n);
void buildMinHeap(int *A, int n);
int heapExtractMin(int *A, int n);
void minHeapInsert(int *A, int i, int key);

int main()
{
	int i, j, n, huff[MAX], power, lchild, rchild, parent;

	while(scanf("%d", &n) != EOF)
	{
		//接收参数输入
		for(i = 1; i <= n; i ++)
			scanf("%d", &huff[i]);

		//构建一个最小堆
		buildMinHeap(huff, n);

		//获取wpl
		for(i = 1, j = n, power = 0; i < n; i ++)
		{
			lchild = heapExtractMin(huff, j);
			j -= 1;
			rchild = heapExtractMin(huff, j);
			
			parent = lchild + rchild;
			power += parent;
		
			minHeapInsert(huff, j, parent);
		}

		printf("%d\n", power);
	}

	return 0;
}

/**
 * Description:构建最小堆
 */
void buildMinHeap(int *A, int n)
{
	int i;

	for(i = n / 2; i >= 1; i --)
	{
		minHeapIfy(A, i, n);
	}
}

/**
 * Description:调整以i为根的最小堆
 */
void minHeapIfy(int *A, int i, int n)
{
	int l, r, min, loc, temp;

	for(min = i; min <= n;)
	{
		l = min * 2;
		r = min * 2 + 1;
		loc = min;

		if(l <= n && A[l] < A[min])
			min = l;
		if(r <= n && A[r] < A[min])
			min = r;

		if(min != loc)
		{
			temp = A[min];
			A[min] = A[loc];
			A[loc] = temp;
		}else
		{
			break;
		}
	}
}



int heapExtractMin(int *A, int n)
{
	int min = A[1];
	A[1] = A[n];
	minHeapIfy(A, 1, n);

	return min;
}


/**
 * Description:
 * (1)将元素插入到最小优先队列
 * (2)因为每次i == length(A),都是在对尾插入,因此只考虑i的parent,不考虑i的children
 */
void minHeapInsert(int *A, int i, int key)
{
	int parent, change;

	for(A[i] = key, parent = i / 2; parent >= 1 && A[parent] > A[i];)
	{
		change = A[parent];
		A[parent] = A[i];
		A[i] = change;
		i = parent;
		parent = i / 2;
	}
}


后记

参考我之前写的那篇博客效果更佳!

posted @ 2013-02-17 23:46  java程序员填空  阅读(139)  评论(0编辑  收藏  举报