数据结构-树-哈夫曼树

来源:互联网 发布:淘宝今日推荐怎么上 编辑:程序博客网 时间:2024/05/16 03:06

最优树-哈夫曼树

哈夫曼树就是一个从叶子节点开始建立树的过程,每次都根据给定的节点找到两个最小的节点,小的作为左孩子,第二小的作为右孩子建立一个子树,根节点为两个子节点权值的和。然后重复这个过程,知道将给出的节点全部作为叶子节点建立出一棵完整的二叉树为止。

这里有个简单例题:


题目描述

编写一个程序实现构造一颗哈夫曼树的功能和给出哈夫曼编码的编码功能。其中要求,哈夫曼树是自左到右按结点的权值从小到大的排列,如果结点的权值相等时,非终端结点优先与终端结点,即终端结点排在右边,如果都是同类型的结点,则按输入的顺序和子结点的顺序自左到右排列。

输入

输入包括多组测试数据,每组测试数据包括多个字符和相应的权值,

输出

计算出每个字符的哈夫曼编码并输出。

样例输入

A(5) B(29) C(7) D(8) E(14) F(23) G(3) H(11)

样例输出

A( 5) : 0001
B(29) : 10
C( 7) : 1110
D( 8) : 1111
E(14) : 110
F(23) : 01
G( 3) : 0000
H(11) : 001
/* *哈夫曼书-从叶子节点到根节点-一个倒过来建树的过程 *从给出的节点中找到最小的两个节点,构建一个子树 *根为两个节点的和,记录节点之间“父子关系” *重复上述过程,直到所有节点都被加入一棵完整的树中 */#include <iostream>#include <cstdlib>#include <cstdio>#include <cstring>using namespace std;#define MAXN 1024typedef struct HuffTree{    char node;    int lchild,rchild,parent,v,state;//state is record the size of node}HuffTree;HuffTree tree_node[MAXN];int tn_count;int node_count;//find two min node indexvoid find(int &min_1,int &min_2){    int m = 32767,mm = 32767;    min_1 = 0;min_2 = 0;    //cout<<"node_count "<<node_count<<endl;    for(int i = 0;i < node_count;i++){        if(mm > tree_node[i].v&&!(~tree_node[i].parent)){                mm = tree_node[i].v;                min_1 = i;        }    }    for(int i = 0;i < node_count;i ++){        if(m > tree_node[i].v&&!(~tree_node[i].parent)&&min_1!=i){            m = tree_node[i].v;            min_2 = i;        }    }}int main(){    char str[MAXN];    int ans[MAXN];    while(fgets(str,sizeof(str),stdin)){        tn_count = 0;        //构建多个节点        for(int i = 0;str[i]!='\0';i++){            if(str[i]<='Z'&&str[i]>='A'){                tree_node[tn_count].node = str[i];                tree_node[tn_count].v = 0;                tree_node[tn_count].parent = tree_node[tn_count].lchild = tree_node[tn_count].rchild = -1;            }            if(str[i]>='0'&&str[i]<='9'){                tree_node[tn_count].v = tree_node[tn_count].v*10+str[i]-'0';            }            if(str[i] == ')'){                tn_count++;            }        }        /*tn_count 叶子节点数,node_count 所有节点数         *这里有个性质:         *一个满二叉树,叶子节点为n那么非叶子节点为n-1         *节点总数为2*n-1         */        node_count = tn_count;        int min_1,min_2;        while(node_count < tn_count*2-1){            find(min_1,min_2);            //cout<<min_1<<" "<<min_2<<endl;            //建新节点            tree_node[node_count].v = tree_node[min_1].v+tree_node[min_2].v;            tree_node[min_1].state = 0;            tree_node[min_2].state = 1;            tree_node[min_1].parent = node_count;            tree_node[min_2].parent = node_count;            tree_node[node_count].lchild = min_1;            tree_node[node_count].rchild = min_2;            tree_node[node_count].parent = -1;            node_count++;        }        //cout<<tn_count<<endl;//        for(int i = 0;i < node_count;i++){//            cout<<tree_node[i].node<<"("<<tree_node[i].v<<")"<<tree_node[i].lchild<<" "<<tree_node[i].rchild<<tree_node[i].parent<<endl;//        }        //输出哈夫曼编码        for(int i = 0;i < tn_count;i++){            int k = i,j = 0;            printf("%c(%2d) : ",tree_node[i].node,tree_node[i].v);            while(tree_node[k].parent!=-1){                ans[j++] = tree_node[k].state;                k = tree_node[k].parent;            }            for(k = j-1;k>=0;k --)                printf("%d",ans[k]);            printf("\n");        }    }    return 0;}



原创粉丝点击