| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 1595 人关注过本帖
标题:【实现】Huffman树及Huffman编码的实现
取消只看楼主 加入收藏
leizisdu
Rank: 2
等 级:论坛游民
帖 子:22
专家分:24
注 册:2011-10-17
收藏
 问题点数:0 回复次数:2 
【实现】Huffman树及Huffman编码的实现
根据《数据结构》(C语言版,严蔚敏、吴伟民编著)算法6.12,实现的Huffman树创建及Huffman编码函数HuffmanCoding。源文件如下:“
程序代码:
#include <iostream>
using std::cout;
using std::cin;
using std::endl;

#include <iomanip>
using std::setw;

// ------------赫夫曼树和赫夫曼编码的存储表示-------------
typedef  struct
{
   unsigned int weight;
   unsigned int parent, lchild, rchild;
} HTNode, * HuffmanTree;         // 动态分配数组存储赫夫曼树
typedef  char * HuffmanCodeLine;
typedef  char * * HuffmanCode;   // 动态分配数组存储赫夫曼编码表

void Select(HuffmanTree &HT, int count, int &min1, int &min2);

void HuffmanCoding(HuffmanTree &HT, HuffmanCode &HC, int * w, int n) // 用"引用"!!!??? SLL, 2011-11-06
{                                                                    // !!!指针本身的在存储空间中的位置是一直没变啊. 2011-11-06
   // w存放n个字符的权值(均>0), 构造赫夫曼树HT, 
   // 并求出n个字符的赫夫曼编码HC.
   if (n <= 1)
   {
      return;
   }
   int m = 2*n-1;          // n个叶子结点的赫夫曼树共有2*n-1个结点.
   HT = new HTNode[m+1];   // 0号单元未用.
   int i;                  // 循环变量
   HTNode * p;
   for (p=HT+1, i=1; i<=n; ++i, ++p, ++w) // 0号单元未用.
   {
      (*p).weight = *w;
      (*p).parent = 0;
      (*p).lchild = 0;
      (*p).rchild = 0;
   }
   for (; i<=m; ++i, ++p)
   {
      (*p).weight = 0;
      (*p).parent = 0;
      (*p).lchild = 0;
      (*p).rchild = 0;
   }
   int s1, s2;
   for (i=n+1; i<=m; ++i)
   {
      // 建赫夫曼树:
      // 在HT[1...i-1]选择parent为0且weight最小的两个结点, 
      // 其序号分别为s1和s2.
      Select(HT, i-1, s1, s2);
      HT[s1].parent = i;
      HT[s2].parent = i;
      HT[i].lchild = s1;
      HT[i].rchild = s2;
      HT[i].weight = HT[s1].weight + HT[s2].weight;
   }
#if 1
   // ---------从叶子到根逆向求每个字符的赫夫曼编码---------
   HC = new HuffmanCodeLine[n+1];   // 分配n个字符编码的头指针向量
                                    // 也是0号单元未用!!!
   char * cd = new char[n];         // 分配求编码的工作空间
   cd[n-1] = '\0';                  // 编码结束码
   int start;
   for (i=1; i<=n; ++i)
   {
      start = n-1;   // 编码结束符位置
      int l;
      unsigned int f;
      for (l=i, f=HT[i].parent; f!=0; l=f, f=HT[f].parent)
      {
         if (HT[f].lchild == l)
         {
            cd[--start] = '0';
         }
         else
         {
            cd[--start] = '1';
         }
      }
      HC[i] = new char[n - start];
      strcpy(HC[i], &cd[start]);
   }
   delete [] cd;     // 释放工作空间
#else
   // ---------无栈非递归遍历赫夫曼树, 求赫夫曼编码---------
   // ...
#endif
}

void Select(HuffmanTree &HT, int count, int &min1, int &min2)
{
   int i = 0;
   int c = 0;
   int minWeight1 = 0xffff;
   int minWeight2 = 0xffff;
   int * order = new int[count];
   for (i=1; i<=count; ++i)
   {
      if (HT[i].parent == 0)  // 统计parent为0的结点的个数及下标
      {
         order[c++] = i;
      }
   }
   for (i=0; i<c; ++i)
   {  // 在该循环之前, minWeight1==minWeight2;
      // 在每次循环中, 始终将较小值存入minWeight1, 较大值存入minWeight2;
      // 执行完毕后, minWeight1中是最小值, minWeight2中是次小值.
      int d = HT[order[i]].weight;
      if (d < minWeight1)
      {
         minWeight2 = minWeight1;
         min2 = min1;
         minWeight1 = d;
         min1 = order[i];
      }
      else if (d < minWeight2)
      {
         minWeight2 = d;
         min2 = order[i];
      }
   }
   delete [] order;
}

int main()
{
   int i = 0;
   int cntLeaf = 0;
   int cntNode = 0;

   cout << "请输入叶子个数: ";
   cin >> cntLeaf;
   while (cntLeaf == 0)
   {
      cout << "叶子个数不能为0, 请重新输入: ";
      cin >> cntLeaf;
   }

   cntNode = cntLeaf*2-1;
   char * pLetter = new char[cntLeaf];
   int * pWeight = new int[cntLeaf];
   for (i=0; i<cntLeaf; ++i)
   {
      cout << "请分别输入叶子结点的字符值和权值: ";
      cin >> pLetter[i] >> pWeight[i];
   }

   HuffmanTree HT = NULL;
   HuffmanCode HC = NULL;
   HuffmanCoding(HT, HC, pWeight, cntLeaf);

   cout << "Huffman树结构如下:\n";
   cout << setw(7) << "No."
      << setw(6+1) << "weight"
      << setw(6+1) << "parent"
      << setw(6+1) << "lchild"
      << setw(6+1) << "rchild"
      << '\n';
   for (i=0; i<cntNode; ++i)
   {
      cout << setw(6+1) << i+1 
         << setw(6+1) << HT[i+1].weight
         << setw(6+1) << HT[i+1].parent 
         << setw(6+1) << HT[i+1].lchild
         << setw(6+1) << HT[i+1].rchild
         << '\n';
   }

   cout << "\n各叶子结点的Huffman编码如下:\n";
   for (i=0; i<cntLeaf; ++i)
   {
      cout << pLetter[i] << ' ' << HC[i+1] << '\n';
   }
   return 0;
}

”。
希望各位大虾们对上述代码进行改善
搜索更多相关主题的帖子: 源文件 C语言 
2011-11-06 22:03
leizisdu
Rank: 2
等 级:论坛游民
帖 子:22
专家分:24
注 册:2011-10-17
收藏
得分:0 
真不好意思,第一次发表帖子,不太敢给分,
给的分确实太少了。
2011-11-08 08:49
leizisdu
Rank: 2
等 级:论坛游民
帖 子:22
专家分:24
注 册:2011-10-17
收藏
得分:0 
回复 4楼 小鱼儿c
2011-11-21 21:40
快速回复:【实现】Huffman树及Huffman编码的实现
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.039549 second(s), 8 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved