哈夫曼树
前言
学习贪心算法的时候复习了一下哈夫曼树的构造,这里记录一下,参考链接: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; } }
后记
参考我之前写的那篇博客效果更佳!