//使用weigh数组构建一个huffman树 HuffmanTree CreateTree(int* weight, int n) { int total = 2 * n - 1; HuffmanTree HT = (HuffmanTree)malloc(total * sizeof(HTNode)); if (!HT) { printf("HuffmanTree malloc faild!\n"); exit(-1); } int i; //HT[0...n-1]存放的是需要编码的n个叶子节点 //初始情况下父节点和左右子节点都为-1 for (i = 0; i < n; ++i) { HT[i].parent = -1; HT[i].lchild = -1; HT[i].rchild = -1; HT[i].weight = *weight; weight++; } //HT[n ... 2n-2]存放的是中间构造的二叉树的节点 for (; i<total; ++i) { HT[i].parent = -1; HT[i].lchild = -1; HT[i].rchild = -1; HT[i].weight = -1; } int min1, min2; for (i = n; i < total; ++i) { SelectMin(HT, i, min1, min2); HT[min1].parent = i; HT[min2].parent = i; HT[i].lchild = min1; HT[i].rchild = min2; HT[i].weight = HT[min1].weight + HT[min2].weight; } return HT; }
void HuffmanCodding(HuffTree &hufftree,HuffCode &huffCode,int* w,int n) { //建立哈夫曼树 int lchild, rchild; int start; int m = 2 * n - 1;//总结点个数 int i; //初始化n个子节点 for (i = 1; i <=n; i++) { hufftree[i].weight = w[i];//权重赋值 hufftree[i].parent = 0;//无父节点 hufftree[i].lchild = 0;//无左孩子节点 hufftree[i].rchild = 0;//无右孩子节点 } //初始化非叶子节点 for (i = n+1; i <=m; i++) { hufftree[i].weight = 0; hufftree[i].parent = 0; hufftree[i].lchild = 0; hufftree[i].rchild = 0; } //使用n+1至m的节点建立哈夫曼树 for (i = n+1; i <=m; i++) { //这里从i-1开始,因为父节点也会不断地加入 SelectMin(hufftree,i-1,lchild);//拿到权重小的左节点下标 hufftree[lchild].parent = i; //printf("lchild = %d-->parent = %d\n",lchild, hufftree[lchild].parent); hufftree[i].lchild = lchild; SelectMin(hufftree,i-1,rchild);//拿到权重小的右节点下标 //更新hufftree的各种数值 hufftree[rchild].parent = i; //printf("rchild = %d-->parent = %d\n", rchild, hufftree[rchild].parent); hufftree[i].rchild = rchild; hufftree[i].weight = hufftree[lchild].weight + hufftree[rchild].weight; //printf("parent = %d-->lchild = %d-->rchild = %d\n", hufftree[rchild].parent,lchild,rchild); } //逆向保存每个字符的哈夫曼编码 char *temp;//保存 //对于n个叶子节点 for ( i = 1; i <=n; i++) { temp = (char*)malloc(sizeof(char)*n);//暂时性地保存编码,逆向保存 temp[n - 1] = '\0';//最后保存的结束字符 int c = i; int parentIndex; start = n-1;//从结束字符的前一位开始,start指向的是填入的那个空 parentIndex = hufftree[i].parent; while (parentIndex!=0)//判断父节点是否有parent下标,是否为根节点 { //printf("child = %d-->parent = %d\n", c, parentIndex); if (hufftree[parentIndex].lchild == c)//说明该子节点是其父节点的左孩子 { temp[--start] = '0';//保存‘0’字符 } if (hufftree[parentIndex].rchild == c)//说明该子节点是其父节点的右孩子 { temp[--start] = '1'; } c = parentIndex;//!!!!坑爹2,这个也要更新 parentIndex = hufftree[parentIndex].parent;//迭代,更新为目前节点的父节点 } //获取到总的编码后 int length = n-start;//总长度 huffCode[i] = (char*)malloc(sizeof(char)*length); //复制!!注意是从start开始复制 strcpy(huffCode[i],&temp[start]); free(temp); } }