1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <string.h> 4 ////////////////////////////////////////////////////////////////////////////// 5 /*定义赫夫曼树结点的结构体变量,存放结点的权值、字符、双亲、坐孩子和右孩子*/ 6 typedef struct{ 7 int weight; 8 char ch; //增加一个域用于存放该节点的字符 9 int parent, lchild, rchild; 10 }HTNode, *HuffmanTree; 11 typedef char **HuffmanCode; //指向赫夫曼编码的指针 12 ////////////////////////////////////////////////////////////////////////////// 13 /*本程序用到的函数原型*/ 14 void welcome(); //打印操作选择界面 15 void HuffmanCoding(HuffmanTree &, char *, int *, int);//建立赫夫曼树的算法 16 void select(HuffmanTree HT, int j, int *s1, int *s2); //从目前已建好的赫夫曼树中选择parent为0且weight最小的两个结点 17 void Init(); //输入n个字符及其对应的权值,根据权值建立哈夫曼树 18 void Coding(); //编码 19 void Decoding(); //译码 20 void Print_code(); //打印译码好的代码文件 21 void Print_tree(); //以凹凸表形式打印哈夫曼树 22 int Read_tree(HuffmanTree &HT); //从文件中读入赫夫曼树 23 void find(HuffmanTree &HT, char *code, char *text, int i, int m);//译码时根据01字符串寻找相应叶子节点的递归算法 24 void Convert_tree(unsigned char T[100][100], int s, int *i, int j);//将内存中的赫夫曼树转换成凹凸表形式的赫夫曼树 25 HuffmanTree HT; //全局变量,指向存放赫夫曼树的存储空间 26 int n = 0; //全局变量,存放赫夫曼树叶子结点的数目 27 int main() 28 { 29 char select; 30 while (1) 31 { 32 welcome(); 33 scanf("%c", &select); 34 switch (select) 35 { 36 case 'i': 37 case 'I':Init(); break; 38 case 'c': 39 case 'C':Coding(); break; 40 case 'd': 41 case 'D':Decoding(); break; 42 case 'p': 43 case 'P':Print_code(); break; 44 case 't': 45 case 'T':Print_tree(); break; 46 case 'e': 47 case 'E':exit(1); 48 default:printf("Input error! "); 49 } 50 getchar(); 51 } 52 return 0; 53 } 54 void welcome() //打印操作选择界面 55 { 56 printf("*-----------------------------------------------------* "); 57 printf("| What do you want to do? | "); 58 printf("|-----------------------------------------------------| "); 59 printf("| | "); 60 printf("| I--------------------------Init the Huffman tree. | "); 61 printf("| C--------------------------Code your file. | "); 62 printf("| D--------------------------Decode the code. | "); 63 printf("| P--------------------------Print the codefile. | "); 64 printf("| T--------------------------Print the Huffman tree. | "); 65 printf("| | "); 66 printf("*-----------------------------------------------------* "); 67 } 68 ////////////////////////////////////////////////////////////////////////////////////// 69 /*初始化函数,输入n个字符及其对应的权值,根据权值建立哈夫曼树,并将其存于文件hfmtree中*/ 70 void Init() 71 { 72 FILE *fp; 73 int i, n, w[52]; //w数组存放n个字符的权值 74 char character[52]; //存放n个字符 75 printf(" 输入字符个数 n:"); 76 scanf("%d", &n); //输入字符集大小 77 printf("输入%d个字符及其对应的权值: ", n); 78 for (i = 0; i < n; i++) 79 { 80 char b = getchar(); 81 scanf("%c", &character[i]); 82 scanf("%d", &w[i]); //输入n个字符和对应的权值 83 } 84 HuffmanCoding(HT, character, w, n); //建立赫夫曼树 85 if ((fp = fopen("hfmtree.txt", "w")) == NULL) 86 printf("Open file hfmtree.txt error! "); 87 for (i = 1; i <= 2 * n - 1; i++) 88 { 89 if (fwrite(&HT[i], sizeof(HTNode), 1, fp) != 1) //将建立的赫夫曼树存入文件hfmtree.txt中 90 printf("File write error! "); 91 } 92 printf(" 建立赫夫曼树成功,已将其存于文件hfmtree.txt中 "); 93 fclose(fp); 94 } 95 /////////////////////////////////////////////////////////////////////////////////// 96 //////建立赫夫曼树的算法/////////////////////////////////////////////////////////// 97 void HuffmanCoding(HuffmanTree &HT, char *character, int *w, int n) 98 { 99 int m, i, s1, s2; 100 HuffmanTree p; 101 if (n <= 1) return; 102 m = 2 * n - 1; 103 HT = (HuffmanTree) malloc((m + 1)*sizeof(HTNode)); 104 for (p = HT + 1, i = 1; i <= n; ++i, ++p, ++character, ++w) 105 { 106 p->ch = *character; 107 p->weight = *w; 108 p->parent = 0; 109 p->lchild = 0; 110 p->rchild = 0; 111 } 112 for (; i <= m; ++i, ++p) 113 { 114 p->ch = 0; 115 p->weight = 0; 116 p->parent = 0; 117 p->lchild = 0; 118 p->rchild = 0; } 119 for (i = n + 1; i <= m; ++i) 120 { 121 select(HT, i - 1, &s1, &s2); 122 HT[s1].parent = i; 123 HT[s2].parent = i; 124 HT[i].lchild = s1; 125 HT[i].rchild = s2; 126 HT[i].weight = HT[s1].weight + HT[s2].weight; 127 } 128 } 129 /////////////////////////////////////////////////////////////////////////////// 130 /*从HT[1]到HT[j]中选择parent为0且weight最小的两个结点,用s1和s2返回其序号*/ 131 void select(HuffmanTree HT, int j, int *s1, int *s2) 132 { 133 int i; 134 //找weight最小的结点 135 for (i = 1; i <= j; i++) 136 if (HT[i].parent == 0) 137 { 138 *s1 = i; 139 break; 140 } 141 for (; i <= j; i++) 142 if ((HT[i].parent == 0) && (HT[i].weight < HT[*s1].weight)) 143 *s1 = i; 144 HT[*s1].parent = 1; 145 //找weight次小的结点 146 for (i = 1; i <= j; i++) 147 if (HT[i].parent == 0) 148 { 149 *s2 = i; break; 150 } 151 for (; i <= j; i++) 152 if ((HT[i].parent == 0) && (i != *s1) && (HT[i].weight < HT[*s2].weight)) 153 *s2 = i; 154 } 155 /////////////////////////////////////////////////////////////////////////////// 156 /*对文件tobetrans中的正文进行编码,然后将结果存入文件codefile中*/ 157 void Coding() 158 { 159 FILE *fp, *fw; 160 int i, f, c, start; 161 char *cd; 162 HuffmanCode HC; 163 if (n == 0) 164 n = Read_tree(HT);//从文件hfmtree.txt中读入赫夫曼树,返回叶子结点数 165 /////以下程序段求赫夫曼树中各叶子节点的字符对应的的编码,并存于HC指向的空间中 166 { 167 HC = (HuffmanCode) malloc((n + 1)*sizeof(char*) ); 168 cd = (char *) malloc(n*sizeof(char) ); 169 cd[n - 1] = '