赫夫曼树的创建

赫夫曼树,即最优二叉树。

给定n个权值作为n个叶子结点,构造一棵二叉树,若该树的带权路径长度达到最小,称这样的二叉树为最优二叉树,也称为哈夫曼树(Huffman Tree)。哈夫曼树是带权路径长度最短的树,权值较大的结点离根较近。

构造赫夫曼树:

赫夫曼树的创建_第1张图片

  1. 把节点的权值按从小到大的顺序排列。
  2. 从序列中取出前两个(最小),作为孩子节点,求出其父节点的权重并加入到序列。
  3. 重复1,2,直到序列中只剩一个节点。这个节点就是赫夫曼树的根节点。

C++实现:

#include 
#include 
using namespace std;
//赫夫曼树
typedef struct Hfmtree {
    char node_val;
    unsigned int weight;
    Hfmtree *lchild, *rchild;
}*pHfmtree;
//队列节点(链表实现)
typedef struct link_node {
    pHfmtree ptree;
    link_node *next;
}Lnode,*pLnode;


//得到权重
int* get_weight( char *inputString );
//初始化链表
void init_link( pLnode &p );
//按照权重,插入链表
void insert_into_linklist ( pLnode &head, pLnode val );
//从链表中取出节点
pHfmtree remove_from_list( pLnode &head );
//生成赫夫曼树
pHfmtree createHfmtree( char *inputString, int *weight, pLnode &head );
//释放内存
void clearTree ( pHfmtree head );
//编码
void encode( pHfmtree root , char *res ,int index );
//解码
void decode( char *code, pHfmtree root );



int main(int argc, char const *argv[])
{
    char input[50];
    cin>>input;
    //得到输入字符对应的权重
    int *weight_res = get_weight( input );

    pLnode head;
    init_link( head );
    //cout << "init_link success\n";

    pHfmtree root = createHfmtree( input, weight_res, head );
    //cout << "CreateHfmtree success\n"<ptree = NULL;
    p->next = NULL;
}


//按照权重,插入链表队列
void insert_into_linklist ( pLnode &head, pLnode val ){

    pLnode temp = new Lnode;
    temp->ptree = val->ptree;
    temp->next = NULL;

    //如果队列为空,则直接插在头节点的后面
    if( NULL==head->next ){
        //cout << "list is empty.\n";
        head->next = temp;
    }
    //否则,根据权重比较,p最终指向
    else{

        pLnode p = head;
        while( NULL!=p->next && p->next->ptree->weightptree->weight )
            p = p->next;
        temp->next = p->next;
        p->next = temp;
    }
    //cout << "insert one.\n";
}

//从队列中取出节点
pHfmtree remove_from_list( pLnode &head ){

    if( NULL==head->next ){
        cout << "List is empty! Fail to remove."<next->ptree;

    pLnode todel = head->next;
    head->next = todel->next;
    delete todel;

    //cout << "remove ing\n";
    return first;
}

//生成赫夫曼树
pHfmtree createHfmtree( char *inputString, int *weight_res, pLnode &head ){

    //生成链表
    for( int i=0; i<256; ++i ) {

        if( weight_res[ i ]>0 ) {
            pHfmtree tempTree = new Hfmtree;
            tempTree->node_val = (char)i;
            tempTree->weight = weight_res[ i ];

            //cout << (char)i<<"    "<ptree = tempTree;

            insert_into_linklist( head, tempNode );
        }
    }
    //cout << "insert success...."<next->next ) {

        //每次取出前两个(权重最小),并插入一个新的节点(权重是这两个的权重之和)
        node_1 = remove_from_list( head );
        node_2 = remove_from_list( head );
        sum_node = new Hfmtree;
        sum_node->weight = node_1->weight + node_2->weight;

        sum_node->lchild = node_1;
        sum_node->rchild = node_2;

        pLnode sum_link_node = new Lnode;
        sum_link_node->ptree = sum_node;
        insert_into_linklist( head, sum_link_node );
    }

    //最后,队列中只剩头结点和赫夫曼树的根节点,将其释放,这个队列也就清理了。
    delete head->next;
    delete head;

    return head->next->ptree;//返回赫夫曼树的根
}

//清理赫夫曼树
void clearTree ( pHfmtree head ) {

    if( NULL==head )
        return;
    if( NULL!=head->lchild )
        clearTree( head->lchild );
    if( NULL!=head->rchild )
        clearTree( head->rchild );
    delete head;
}

//编码
void encode( pHfmtree node , char *res, int index ){

    if( NULL==node->lchild&&NULL==node->rchild ){
        cout<< node->node_val <<" :   "<< res <lchild;
    if( NULL!=left ){
        res[index] = '0';
        encode( left, res,index+1 );
        res[index] = '\0';
    }


    pHfmtree right = node->rchild;
    if( NULL!=right ){
        res[index] = '1';
        encode( right, res , index+1 );
        res[index] = '\0';
    }
}

//解码
void decode( char *code, pHfmtree root ){

    //如果赫夫曼树只有一个跟节点
    if( NULL==root->lchild&&NULL==root->rchild ) {
        for( int i=0; inode_val;
        }
        cout << endl;
        return;
    }
    //有多个节点
    pHfmtree p = root;
    for( int i=0; ilchild;
        if( NULL==p->lchild&&NULL==p->rchild ) {

            cout << p->node_val;
            p = root;
            continue;
        }

        if( code[i]=='1' )
            p = p->rchild;
        if( NULL==p->lchild&&NULL==p->rchild ) {

            cout << p->node_val;
            p = root;
            continue;
        }
    }
    cout << endl;
}

运行结果:

赫夫曼树的创建_第2张图片

你可能感兴趣的:(数据结构)