代码参考严蔚敏《数据结构》
1 #include<string.h> 2 #include<stdlib.h> 3 #include<stdio.h> 4 5 int m,s1,s2; 6 7 typedef struct 8 { 9 unsigned int weight; 10 unsigned int parent,lchild,rchild; 11 } HTNode,*HuffmanTree; //动态分配数组存储哈夫曼树 12 typedef char *HuffmanCode; //动态分配数组存储哈夫曼编码表 13 14 void Select(HuffmanTree HT,int n) 15 { 16 int i,j; 17 for(i = 1; i <= n; i++) 18 if(!HT[i].parent) 19 { 20 s1 = i; 21 break; 22 } 23 for(j = i+1; j <= n; j++) 24 if(!HT[j].parent) 25 { 26 s2 = j; 27 break; 28 } 29 for(i = 1; i <= n; i++) 30 if((HT[s1].weight>HT[i].weight)&&(!HT[i].parent)&&(s2!=i)) 31 s1=i; 32 for(j = 1; j <= n; j++) 33 if((HT[s2].weight>HT[j].weight)&&(!HT[j].parent)&&(s1!=j)) 34 s2=j; 35 } 36 37 void HuffmanCoding(HuffmanTree &HT, HuffmanCode HC[], int *w, int n) 38 { 39 // 算法6.13 40 // w存放n个字符的权值(均>0),构造哈夫曼树HT, 41 // 并求出n个字符的哈夫曼编码HC 42 int i, j; 43 char *cd; 44 int p; 45 int cdlen; 46 47 if (n<=1) 48 return; 49 m = 2 * n - 1; 50 HT = (HuffmanTree)malloc((m+1) * sizeof(HTNode)); // 0号单元未用 51 for (i=1; i<=n; i++) //初始化 52 { 53 HT[i].weight=w[i-1]; 54 HT[i].parent=0; 55 HT[i].lchild=0; 56 HT[i].rchild=0; 57 } 58 for (i=n+1; i<=m; i++) //初始化 59 { 60 HT[i].weight=0; 61 HT[i].parent=0; 62 HT[i].lchild=0; 63 HT[i].rchild=0; 64 } 65 puts("\n哈夫曼树的构造过程如下所示:"); 66 printf("HT初态:\n 结点 weight parent lchild rchild"); 67 for (i=1; i<=m; i++) 68 printf("\n%4d%8d%8d%8d%8d",i,HT[i].weight, 69 HT[i].parent,HT[i].lchild, HT[i].rchild); 70 for (i=n+1; i<=m; i++) // 建哈夫曼树 71 { 72 // 在HT[1..i-1]中选择parent为0且weight最小的两个结点, 73 // 其序号分别为s1和s2。 74 Select(HT, i-1); 75 HT[s1].parent = i; 76 HT[s2].parent = i; 77 HT[i].lchild = s1; 78 HT[i].rchild = s2; 79 HT[i].weight = HT[s1].weight + HT[s2].weight; 80 printf("\nselect: s1=%d s2=%d\n", s1, s2); 81 printf(" 结点 weight parent lchild rchild"); 82 for (j=1; j<=i; j++) 83 printf("\n%4d%8d%8d%8d%8d",j,HT[j].weight, 84 HT[j].parent,HT[j].lchild, HT[j].rchild); 85 86 } 87 88 //------无栈非递归遍历哈夫曼树,求哈夫曼编码 89 cd = (char *)malloc(n*sizeof(char)); // 分配求编码的工作空间 90 p = m; 91 cdlen = 0; 92 for (i=1; i<=m; ++i) // 遍历哈夫曼树时用作结点状态标志 93 HT[i].weight = 0; 94 while (p) 95 { 96 if (HT[p].weight==0) // 向左 97 { 98 HT[p].weight = 1; 99 if (HT[p].lchild != 0) 100 { 101 p = HT[p].lchild; 102 cd[cdlen++] =‘0‘; 103 } 104 else if (HT[p].rchild == 0) // 登记叶子结点的字符的编码 105 { 106 HC[p] = (char *)malloc((cdlen+1) * sizeof(char)); 107 cd[cdlen] =‘\0‘; 108 strcpy(HC[p], cd); // 复制编码(串) 109 } 110 } 111 else if (HT[p].weight==1) // 向右 112 { 113 HT[p].weight = 2; 114 if (HT[p].rchild != 0) 115 { 116 p = HT[p].rchild; 117 cd[cdlen++] =‘1‘; 118 } 119 } 120 else // HT[p].weight==2,退回退到父结点,编码长度减1 121 { 122 HT[p].weight = 0; 123 p = HT[p].parent; 124 --cdlen; 125 } 126 } 127 } // HuffmanCoding 128 int main() 129 { 130 HuffmanTree HT; 131 HuffmanCode *HC; 132 int *w,n,i; 133 puts("输入结点数:"); 134 scanf("%d",&n); 135 HC = (HuffmanCode *)malloc(n*sizeof(HuffmanCode)); 136 w = (int *)malloc(n*sizeof(int)); 137 printf("输入%d个结点的权值\n",n); 138 for(i = 0; i < n; i++) 139 scanf("%d",&w[i]); 140 HuffmanCoding(HT,HC,w,n); 141 puts("\n各结点的哈夫曼编码:"); 142 for(i = 1; i <= n; i++) 143 printf("%2d(%4d):%s\n",i,w[i-1],HC[i]); 144 getchar(); 145 }
运行结果:
原文地址:https://www.cnblogs.com/FengZeng666/p/10043955.html
时间: 2024-10-07 03:00:43