赫夫曼树

#include <conio.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>


typedef struct{
    int weight;
    int parent, lchild,rchild;
}HTNode, *HuffmanTree;

typedef char ** HuffmanCode;

void HuffmanCoding(HuffmanTree &HT, HuffmanCode &HC, int *w, int n);    //w存放n个字符的权值,构造赫夫曼书HT,并求出n个字符的赫夫曼编码HC
void select(const HuffmanTree &HT, int n, int &s1, int &s2);    //选择parent为0且weiht最小的两个结点,其序号分别为s1,s2

int main(){
    HuffmanTree HT;
    HuffmanCode HC;
    int i;
    const int n = 8;
    int weight[n] = {5,29,7,8,14,23,3,11};

    HuffmanCoding(HT, HC, weight, n);
    for(i=1; i<=n; i++)
        printf("%d %s\n",HT[i].weight, HC[i]);

    return 0;
}

void HuffmanCoding(HuffmanTree &HT, HuffmanCode &HC, int *w, int n){    //w存放n个字符的权值,构造赫夫曼书HT,并求出n个字符的赫夫曼编码HC
    int i,m,s1,s2;
//    HuffmanTree p;
    int start,f,c;//start指向当前编码位置,f为parent结点序号,c为当前的结点序号

    if(n <= 1)    return ;
    m = 2*n-1;
    HT = (HuffmanTree)malloc((m+1) * sizeof(HTNode));    //0号单元未用
    memset(HT,0,(m+1)*sizeof(HTNode));

    for(i=1; i<=n; ++i, ++w)    HT[i].weight = *w;
    for(i = n+1; i<=m; i++){    //建赫夫曼树
        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;
    }
    
    //求赫夫曼编码
    HC = (HuffmanCode)malloc((n+1) * sizeof(char *));    //分配n个字符编码的头指针向量
    char *cd = (char *)malloc(n * sizeof(char));    //分配求编码的工作空间
    cd[n-1] = '\0';//编码结束符
    for(i=1; i<=n; i++){    //逐个字符求赫夫曼编码
        start = n-1;//编码结束符位置
        for(c=i, f=HT[i].parent; f!=0; c=f, f=HT[f].parent)    //从叶子到根你想求编码
            if(HT[f].lchild == c)    cd[--start] = '0';
            else    cd[--start] = '1';
            HC[i] = (char *)malloc((n-start) * sizeof(char));    //为第i个字符编码分配空间
            strcpy(HC[i], &cd[start]);    //从cd复制编码到HC
    }
    free(cd); 
}

void select(const HuffmanTree &HT, int n, int &s1, int &s2){    //选择parent为0且weiht最小的两个结点,其序号分别为s1,s2
    if(n < 1) return ;
    int i,min1,min2;    //min1为最小,min2为第二小
    int ic=0;    //主要用来处理初始时的情况 和 当!=0 的数仅剩2个的情况
    for(i=1; i<=n; i++){
        if(HT[i].parent != 0)    continue;
        if(ic == 0){
            min1 = i; min2 = i;    ic++;
        }
        else if(ic == 1){
            if(HT[min1].weight > HT[i].weight){
                min2 = min1;    min1 = i;    ic++;
            }
            else{
                min2 = i;    ic++;
            }
        }
        else{
            if(HT[min1].weight > HT[i].weight){
                    min2 = min1;
                    min1 = i;
            }
            else if(HT[min2].weight > HT[i].weight)    min2= i;
            else if(HT[min2].weight == HT[i].weight && min1 == min2)    min2 = i;
        }
    }
    s1 = min1;    s2 = min2;
}

 

posted on 2012-11-23 19:53  Still_Raining  阅读(299)  评论(0编辑  收藏  举报