数据结构--哈弗曼树

来源:互联网 发布:mac mini好吗 编辑:程序博客网 时间:2024/03/28 20:41
// Huffman.cpp : Defines the entry point for the console application./*-----CODE FOR FUN----------------------CREATED BY Dream_Whui-------------2015-2-8-------------------*/#include "stdafx.h"#include <iostream>using namespace std;typedef struct//定义哈弗曼树的结构{    unsigned int weight;//权重    unsigned int parent, lchild, rchild;//双亲结点,做孩子,右孩子}HTNode, *HuffmanTree;typedef char** HuffmanCode;void Select(HuffmanTree HT, int n, int &s1, int &s2)//选出哈弗曼树HT中权值最小,双亲结点序号为0,的两个结点,序号赋值给s1,s2{    int i,f1,f2;    unsigned int k = UINT_MAX;    for(i=1; i<=n; i++)//找到权值最小的结点    {        if(HT[i].parent == 0)            if(HT[i].weight < k)            {                k = HT[i].weight;                f1 = i;            }    }    HT[f1].parent = 1;//双亲结点设为1,做为标记(不会再被选到)    s1 = f1;    k = UINT_MAX;    for(i=1; i<=n; i++)//找到权值第二小的结点    {        if(HT[i].parent == 0)            if(HT[i].weight < k)            {                k = HT[i].weight;                f2 = i;            }    }    HT[f2].parent = 1;    s2 = f2;    int temp;    if(s1>s2)    {        temp = s1;        s1 = s2;        s2 = temp;    }}void HuffmanCoding(HuffmanTree &HT, HuffmanCode &HC, int *w, int n){    //构造哈弗曼树HT,哈弗曼树编码HC,w为结点的权重值,n个字符(即n个结点)    if(n<=1)        return ;    int m = 2*n-1;//n个字符,需要构造2n-1个结点    HT = (HuffmanTree)malloc( (m+1)*sizeof(HTNode) );    HuffmanTree  p;    int i;    int s1,s2;    for(p=HT+1, i=1; i<=n; i++, p++, w++)//n个字符(结点)初始化    {        //*p = {*w,0,0,0};        p->weight = *w;        p->lchild = 0;        p->rchild = 0;        p->parent = 0;    }    for(; i<=m; i++, p++)//后面结点初始化    {        p->weight = 0;        p->lchild = 0;        p->rchild = 0;        p->parent = 0;    }    for(i=n+1; i<=m; i++)// 建赫夫曼树       {                    // 在HT[1~i-1]中选择parent为0且weight最小的两个结点,其序号分别为s1和s2        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;        //cout<<i<<":"<<HT[s1].weight<<" "<<HT[s2].weight<<endl;    }#define HC_1#ifdef HC_1      //从叶子到根逆向求每个字符的哈弗曼编码    cout<<"从叶子到根"<<endl;    HC = (HuffmanCode)malloc( (n+1)*sizeof(char*) );    char *cd = (char*)malloc( n*sizeof(char));    cd[n-1] = '\0';//编码结束符    int start, c, f;    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);#endif//#define HC_2#ifdef HC_2    cout<<"从根到叶子"<<endl;    HC = (HuffmanCode)malloc( (n+1)*sizeof(char*) );    char *cd = (char*)malloc( n*sizeof(char));    int num=m;    int cdlen = 0;    for(int i=1; i<=m; i++)        HT[i].weight = 0;//遍历哈弗曼树时用作结点状态标志    while(num)    {        if(HT[num].weight==0)//向左        {            HT[num].weight=1;            if(HT[num].lchild != 0)            {                num = HT[num].lchild;                cd[cdlen++] = '0';            }            else if(HT[num].rchild == 0)            {                HC[num] = (char*)malloc( (cdlen+1)*sizeof(char) );                cd[cdlen] = '\0';                strcpy(HC[num],cd);            }        }        else if(HT[num].weight == 1)//向右        {            HT[num].weight = 2;            if(HT[num].rchild != 0)            {                num = HT[num].rchild;                cd[cdlen++] = '1';            }        }        else//左右都遍历完后,退回到双亲结点        {            HT[num].weight = 0;            num = HT[num].parent;            --cdlen;        }    }#endif}int main(int argc, char* argv[]){    HuffmanTree T;    HuffmanCode HC;    cout<<"输入字符个数n(0~20):";    int n;    cin>>n;    int *weight = (int*)malloc( n*sizeof(int) );    int i;    for(i=0; i<n; i++)    {        cout<<"输入第"<<i+1<<"个字符的权重值:";        cin>>weight[i];    }    HuffmanCoding(T,HC,weight,n);    cout<<"哈弗曼编码"<<endl;    for(i=1; i<=n; i++)    {        cout<<"第"<<i<<"个字符编码:"<<HC[i]<<endl;    }    cout<<endl;    free(weight);    return 0;}

0 0