3人对饮

导航

 
  1 #include <iostream>
  2  using std::cout;
  3  using std::cin;
  4  using std::endl;
  5  
  6 #include <iomanip>
  7  using std::setw;
  8  
  9 // ------------赫夫曼树和赫夫曼编码的存储表示-------------
 10  typedef  struct
 11  {
 12     unsigned int weight;
 13     unsigned int parent, lchild, rchild;
 14  } HTNode, * HuffmanTree;         // 动态分配数组存储赫夫曼树
 15  typedef  char * HuffmanCodeLine;
 16  typedef  char * * HuffmanCode;   // 动态分配数组存储赫夫曼编码表
 17  typedef struct{
 18      unsigned int weight;
 19      int index;
 20  }Non_parent;                     //存储没有父节点的HuffmanTree的权重和序号
 21  
 22 void Select(HuffmanTree &HT, int count, int &min1, int &min2);
 23  
 24 void HuffmanCoding(HuffmanTree &HT, HuffmanCode &HC, int * w, int n) 
 25  {                                                  
 26     // w存放n个字符的权值(均>0), 构造赫夫曼树HT, 
 27    // 并求出n个字符的赫夫曼编码HC.
 28     if (n <= 1)
 29     {
 30        return;
 31     }
 32     int m = 2*n-1;          // n个叶子结点的赫夫曼树共有2*n-1个结点.
 33     HT = new HTNode[m+1];   // 0号单元未用.
 34     int i;                  // 循环变量
 35     HTNode * p;
 36     for (p=HT+1, i=1; i<=n; ++i, ++p, ++w) // 0号单元未用.
 37     {
 38        (*p).weight = *w;
 39        (*p).parent = 0;
 40        (*p).lchild = 0;
 41        (*p).rchild = 0;
 42     }
 43     for (; i<=m; ++i, ++p)
 44     {
 45        (*p).weight = 0;
 46        (*p).parent = 0;
 47        (*p).lchild = 0;
 48        (*p).rchild = 0;
 49     }
 50     int s1, s2;
 51     for (i=n+1; i<=m; ++i)
 52     {
 53        // 建赫夫曼树:

 54        // 在HT[1...i-1]选择parent为0且weight最小的两个结点, 
 55       // 其序号分别为s1和s2.
 56        Select(HT, i-1, s1, s2);
 57        HT[s1].parent = i;
 58        HT[s2].parent = i;
 59        HT[i].lchild = s1;
 60        HT[i].rchild = s2;
 61        HT[i].weight = HT[s1].weight + HT[s2].weight;
 62     }
 63  #if 1
 64     // ---------从叶子到根逆向求每个字符的赫夫曼编码---------
 65     HC = new char*[n+1];             // 分配n个字符编码的头指针向量
 66                                      // 也是0号单元未用!!!
 67     char * cd = new char[n];         // 分配求编码的工作空间
 68     cd[n-1] = '\0';                  // 编码结束码
 69     int start;
 70     for (i=1; i<=n; ++i)
 71     {
 72        start = n-1;   // 编码结束符位置
 73        int l;
 74        unsigned int f;
 75        for (l=i, f=HT[i].parent; f!=0; l=f, f=HT[f].parent)
 76        {
 77           if (HT[f].lchild == l)
 78           {
 79              cd[--start] = '0';
 80           }
 81           else
 82           {
 83              cd[--start] = '1';
 84           }
 85        }
 86        HC[i] = new char[n - start];
 87        strcpy(HC[i], &cd[start]);
 88     }
 89     delete [] cd;     // 释放工作空间
 90  #else
 91     // ---------无栈非递归遍历赫夫曼树, 求赫夫曼编码---------
 92     // ...
 93  #endif
 94  }131  void Select(HuffmanTree &HT, int count, int &min1, int &min2){
132      int j=0;
133      int j_index=0;
134      Non_parent* n_parent=nullptr;
135      n_parent=new Non_parent[count];
136      for(int i=1;i<=count;i++){         
137          if(HT[i].parent==0){
138              n_parent[j].weight=HT[i].weight;
139              n_parent[j].index=i;
140              j++;
141          }
142      }
143      int jMax=j;
144      unsigned int temp=n_parent[0].weight;
145      min1=n_parent[0].index;
146      for(j=1;j<jMax;j++){                              //找出权重最小的节点
147          if(n_parent[j].weight<temp){
148              temp=n_parent[j].weight;
149              min1=n_parent[j].index;
150              j_index=j;
151          }     
152      }
153      for(int i=j_index;i<jMax-1;i++){                  //去掉权重最小的节点
154          n_parent[i]=n_parent[i+1];
155      }
156      temp=n_parent[0].weight;
157      min2=n_parent[0].index;
158      for(j=1;j<jMax-1;j++){                              //找出权重第二小的节点
159          if(n_parent[j].weight<temp){
160              temp=n_parent[j].weight;
161              min2=n_parent[j].index;
162          }     
163      }
164      delete[] n_parent;
165      n_parent=nullptr;
166 
167 
168  }
169      
170 
171     
172 
173 
174 
175 
176          
177 
178 
179 int main()
180  {
181     int i = 0;
182     int cntLeaf = 0;
183     int cntNode = 0;
184  
185    cout << "请输入叶子个数(正整数): ";
186     cin >> cntLeaf;
187     while (cntLeaf <= 0)
188     {
189        cout << "叶子个数不能为0, 请重新输入: ";
190        cin >> cntLeaf;
191     }
192  
193    cntNode = cntLeaf*2-1;
194     char * pLetter = new char[cntLeaf];
195     int * pWeight = new int[cntLeaf];
196     for (i=0; i<cntLeaf; ++i)
197     {
198        cout << "请分别输入叶子结点的字符值和权值: ";
199        cin >> pLetter[i] >> pWeight[i];
200     }
201  
202    HuffmanTree HT = NULL;
203     HuffmanCode HC = NULL;
204     HuffmanCoding(HT, HC, pWeight, cntLeaf);
205  
206    cout << "Huffman树结构如下:\n";
207     cout << setw(7) << "No."
208        << setw(6+1) << "weight"
209        << setw(6+1) << "parent"
210        << setw(6+1) << "lchild"
211        << setw(6+1) << "rchild"
212        << '\n';
213     for (i=0; i<cntNode; ++i)
214     {
215        cout << setw(6+1) << i+1 
216          << setw(6+1) << HT[i+1].weight
217           << setw(6+1) << HT[i+1].parent 
218          << setw(6+1) << HT[i+1].lchild
219           << setw(6+1) << HT[i+1].rchild
220           << '\n';
221     }
222  
223    cout << "\n各叶子结点的Huffman编码如下:\n";
224     for (i=0; i<cntLeaf; ++i)
225     {
226        cout << pLetter[i] << ' ' << HC[i+1] << '\n';
227     }
228     
229     for(int i=1;i<cntLeaf+1;i++){
230         delete[] HC[i];
231         HC[i]==nullptr;
232     }
233     
234     delete[] HT;
235     HT=nullptr;
236     delete[] HC;
237     HC=nullptr;
238     delete[] pLetter;
239     pLetter=nullptr;
240     delete[] pWeight;
241     pWeight=nullptr;
242     
243     return 0;
244  }
245  

 

posted on 2012-07-24 08:17  3人对饮  阅读(387)  评论(0编辑  收藏  举报