code of huffman(参考)

来源:互联网 发布:jtl 文件java 解析 编辑:程序博客网 时间:2024/06/01 08:02

source:http://blog.csdn.net/yinxusen/article/details/6261549

这是别人写的Huffman

 

比我的功能全点,主要是欣赏一下别人的内存分配方式,它使用的指针动态分配

 

[cpp] view plaincopyprint?
  1. #include <iostream.h>   
  2. #include <string.h>   
  3. /* 
  4. 哈夫曼编码示例程序 
  5. 作者:杨勇 
  6. 哈夫曼建树算法描述: 
  7. 1. 将所有权值分别构造一个只有一个结点的二叉树结点,将这些结点加入集合A(哈夫曼森林) 
  8. 2. 检查集合A成员的个数,如果为1,则算法结束,集合A中唯一的结点为哈夫曼树的根。 
  9. 3. 从集合A中取出根结点权值最小的两棵树a, b,集合中不再保留这两棵树。 
  10. 4. 由a和b分别为左、右子树构造一个新的二叉树r, 令r的权值等于a的权值与b的权值之和。 
  11. 5. 将r加入到集合A中,返回第 2 步。 
  12. */  
  13.   
  14. struct HuffmanNode //哈夫曼树结点类型   
  15. {  
  16.     char data; //结点上的数据   
  17.     int power; //结点的权值   
  18.     HuffmanNode *lchild; //左分支(作为二叉树结点时用)   
  19.     HuffmanNode *rchild; //右分支(作为二叉树结点时用)   
  20.     HuffmanNode *next; //后继指针(作为单链表结点时用)   
  21. };  
  22.   
  23. //给Huffman森林(按各树根结点的值升序排列的带头结点的链表)添加一棵Huffman树   
  24. //使得链表仍然有序   
  25. void AddNode(HuffmanNode *headNode, HuffmanNode *pNode)   
  26. {  
  27.     HuffmanNode *p = headNode;  
  28.     //找到第一个权值小于给定结点的结点,p指定该结点的前一个结点   
  29.     while (p->next && p->next->power < pNode->power) p = p->next;  
  30.     pNode->next = p->next;  
  31.     p->next = pNode;  
  32. }  
  33. //功能:构造哈夫曼树   
  34. //参数说明   
  35. //n: 字符的个数   
  36. //datas: 要统计的字符   
  37. //powers: 字符对应的权值(出现的次数)   
  38. HuffmanNode* CreateHuffmanTree(int n, char datas[], int powers[])  
  39. {  
  40.     HuffmanNode head;  
  41.     head.next = NULL; //初始化森林   
  42.     for (int i = 0; i < n; i++)  
  43.     {  
  44.         HuffmanNode *pNode = new HuffmanNode;  
  45.         pNode->data = datas[i];  
  46.         pNode->power = powers[i];  
  47.         pNode->lchild = pNode->rchild = pNode->next = NULL;  
  48.         AddNode(&head, pNode);  
  49.     }  
  50.     //开始构造   
  51.     while (head.next)  
  52.     {  
  53.         if (!head.next->next) //只剩最后一个结点,这就是根   
  54.         {  
  55.             return head.next;  
  56.         }  
  57.         //取前两个出来构造一棵新树(因为链表已经按权值升序排列了,前两个就是最小的两个)   
  58.         HuffmanNode *pN1, *pN2, *pRoot;  
  59.         pN1 = head.next; //第一个结点   
  60.         pN2 = pN1->next; //第二个结点   
  61.         head.next = pN2->next; //将这两个结点从链表中删除   
  62.         pRoot = new HuffmanNode; //为这两个结点建立根结点   
  63.         pRoot->power = pN1->power + pN2->power; //权值相加   
  64.         pRoot->lchild = pN1; //左分支为第一个结点   
  65.         pRoot->rchild = pN2; //右分支为第二个结点   
  66.         //将新的根加入哈夫曼森林   
  67.         AddNode(&head, pRoot);  
  68.     }  
  69.     return NULL;  
  70. }  
  71.   
  72. //计算哈夫曼树的带权路径长度PWL   
  73. //node: 树结点   
  74. //level: 当前层数   
  75. int GetPWL(HuffmanNode *node, int level)  
  76. {  
  77.     if (!node) return 0;  
  78.     if (!node->lchild && !node->rchild) return node->power * level; //是叶结点   
  79.     return GetPWL(node->lchild, level + 1) + GetPWL(node->rchild, level+1);  
  80. }  
  81.   
  82. //获取所有叶点的哈夫曼编码   
  83. //node: 树结点   
  84. //code: 上层前缀   
  85. void GetCodes(HuffmanNode *node, const char *code)  
  86. {  
  87.     if (!node->lchild && !node->rchild)  
  88.     {  
  89.         //是叶结点,打印编码   
  90.         cout << node->data << " " << node->power << " " << code << endl;  
  91.         return;  
  92.     }  
  93.   
  94.     int len = strlen(code);  
  95.     char *newcode = new char[len+2];  
  96.     strcpy(newcode, code);  
  97.     newcode[len+1] = '/0';  
  98.     if (node->lchild) //左分支分配'1'   
  99.     {  
  100.         newcode[len] = '1';  
  101.         GetCodes(node->lchild, newcode);  
  102.     }  
  103.     if (node->rchild) //右分支分配'0'   
  104.     {  
  105.         newcode[len] = '0';  
  106.         GetCodes(node->rchild, newcode);  
  107.     }  
  108.     delete[] newcode;  
  109. }  
  110.   
  111. //释放所有结点,要按二叉树的方式   
  112. void FreeNodes(HuffmanNode *node)  
  113. {  
  114.     if (!node) return;  
  115.     FreeNodes(node->lchild);  
  116.     FreeNodes(node->rchild);  
  117.     delete node;  
  118. }  
  119. //请尝试改变主函数,使之能统计指定文本文件中的各字母出现的次数,然后给这些字母编码,并将文本文件的内容编码后输出到out.txt中   
  120. void main()  
  121. {  
  122.     int n, pow;  
  123.     char ch;  
  124.     do  
  125.     {  
  126.         cout << "请输入字母个数:";  
  127.         cin >> n;  
  128.     } while (n < 1);  
  129.     char *datas = new char[n];  
  130.     int *pows = new int[n];  
  131.     for (int i = 0; i < n; i++)  
  132.     {  
  133.         cout << "请输入第 " << i+1 << " 个字母及权值:";  
  134.         cin >> ch >> pow;  
  135.         datas[i] = ch;  
  136.         pows[i] = pow;  
  137.     }  
  138.     HuffmanNode *root = CreateHuffmanTree(n, datas, pows);  
  139.     cout << "构造出哈夫曼树的权值为:" << GetPWL(root, 0) << endl;  
  140.     cout << "所有字母的哈夫曼编码如下:" << endl;  
  141.     GetCodes(root, "");  
  142.     FreeNodes(root);  
  143.     delete[] datas;  
  144.     delete[] pows;  
  145. }  

原创粉丝点击