哈夫曼树的构建c/c++实现

备考期末,懂得都懂,不懂就别看了,挺浪费时间的;

结构定义

typedef char ElemType;

typedef struct{
    ElemType data;
    int weight;
    int parent, lchild, rchild;
} HuffNode;

初始化哈夫曼树结构

HuffNode *initial_hufT(){
    int n = 0;
    cin >> n; //叶子结点数n 
    int numNode = 2 * n - 1;
    HuffNode *HT = new HuffNode[numNode + 1];
    //结点初始化
    for (int i = 1; i <= numNode; i++) // 将所有结点的双亲和孩子信息置为0
        HT[i].weight = HT[i].data = HT[i].lchild = HT[i].rchild = HT[i].parent = 0;

    //对结点设置权值
    for (int i = 1; i <= n; i++)
        cin >> HT[i].weight;

    for (int i = 1; i <= n; i++)
        cin >> HT[i].data;

    //树的节点数记录
    HT[0].data = n;
    HT[0].weight = numNode;
    return HT;
}

选择权值最小两个结点(生成哈夫曼树用)

//从HT[1]~HT[n]中选取parent为0的,对weight进行排序,并找出最小的两个weight的下标存进s1和s2
void Select(HuffNode *HT, int n, int &T1, int &T2){
    map<int, int> m;
    for (int i = 1; i <= n; i++)
        if (!HT[i].parent)
            m.insert(make_pair(HT[i].weight, i)); // insert 函数插入 pair 数据
    map<int, int>::iterator mTemp = m.begin();
    T1 = (*mTemp++).second;
    T2 = (*mTemp).second;
}

生成哈夫曼树

void createHuFTree(HuffNode *HT){
    int T1, T2;
    for (int i = HT[0].data + 1; i <= HT[0].weight; i++){
        Select(HT, i - 1, T1, T2);
        HT[T1].parent = HT[T2].parent = i; //删除结点
        //合并结点
        HT[i].lchild = T1;
        HT[i].rchild = T2;
        HT[i].weight = HT[T1].weight + HT[T2].weight;
    }
}

打印输出哈夫曼树存储结构所有结点的信息(debug用)

void PrintHuFTree(HuffNode *HT)
{
    cout << "index" << '\t' << "data" << '\t' << "weight" << '\t' << "parent" << '\t' << "lChild" << '\t' << "rChild" << endl;
    for (int i = 1; i <= HT[0].weight; ++i)
    {
        cout << i << "\t";
        cout << HT[i].data << '\t';
        cout << HT[i].weight << '\t';
        cout << HT[i].parent << "\t";
        cout << HT[i].lchild << "\t";
        cout << HT[i].rchild << endl;
    }
}

生成哈夫曼编码表

注意是从数据结点(通过父亲结点下标)向上遍历到root;借助栈来实现正向输出编码,然后将其存放到map中;

void PrintHuFTreeCode(HuffNode *HT , map<char , string> &codeDict){
    for (int i = 1; i <= HT[0].data; i++){
        stack<char> CodeStack;
        HuffNode *TempNode = &HT[i];
        HuffNode *TF = &HT[TempNode->parent];
        while (true){
            if (&HT[TF->lchild] == TempNode)   CodeStack.push('0'); //判断当前结点是父亲节点的左节点还是右节点
            else   CodeStack.push('1');
            TempNode = TF;
             if(!TF->parent) break;
            TF = &HT[TF->parent];
        } //从叶子结点向上遍历到root

        // 输出 哈夫曼编码
        // cout<< HT[i].weight << ": ";
        string t = "";
        while (!CodeStack.empty()){
            // cout << CodeStack.top();
            t += CodeStack.top();
            CodeStack.pop();
        }
        // cout << endl;
        codeDict.insert( make_pair( HT[i].data, t) );
    }
}

根据哈夫曼编码表解码字符串

void DehufCode(HuffNode *HT , map<char , string> codeDict){
    for(auto i = codeDict.begin();i!=codeDict.end() ;i++)	 // 输出编码表
        cout<< i->first << ": " << i->second << endl;

    string cT;
    cin >> cT;
    cout << "cipherText:  " << "{" << cT << "}" << endl;
    cout << "decode Text: " << "{" ;
    while (cT.length() )
        for(auto i = codeDict.begin();i!=codeDict.end() ;i++){
            int index = cT.find(i->second);
            if(!index)  //匹配
            {
                cout << i->first;
                cT.erase(0, i->second.length() );
            }
        }
    cout << "}" << endl;
}

总代码

#include <map>
#include <stack>
#include <string>
#include <iostream>
using namespace std;

typedef char ElemType;

typedef struct{
    ElemType data;
    int weight;
    int parent, lchild, rchild;
} HuffNode;


HuffNode *initial_hufT(){
    int n = 0;
    cin >> n; //叶子结点数n 
    int numNode = 2 * n - 1;
    HuffNode *HT = new HuffNode[numNode + 1];
    //结点初始化
    for (int i = 1; i <= numNode; i++) // 将所有结点的双亲和孩子信息置为0
        HT[i].weight = HT[i].data = HT[i].lchild = HT[i].rchild = HT[i].parent = 0;

    //对结点设置权值
    for (int i = 1; i <= n; i++)
        cin >> HT[i].weight;

    for (int i = 1; i <= n; i++)
        cin >> HT[i].data;

    //树的节点数记录
    HT[0].data = n;
    HT[0].weight = numNode;
    return HT;
}

//从HT[1]~HT[n]中选取parent为0的,对weight进行排序,并找出最小的两个weight的下标存进s1和s2
void Select(HuffNode *HT, int n, int &T1, int &T2){
    map<int, int> m;
    for (int i = 1; i <= n; i++)
        if (!HT[i].parent)
            m.insert(make_pair(HT[i].weight, i)); // insert 函数插入 pair 数据
    map<int, int>::iterator mTemp = m.begin();
    T1 = (*mTemp++).second;
    T2 = (*mTemp).second;
}

// 创建哈夫曼树
void createHuFTree(HuffNode *HT){
    int T1, T2;
    for (int i = HT[0].data + 1; i <= HT[0].weight; i++){
        Select(HT, i - 1, T1, T2);
        HT[T1].parent = HT[T2].parent = i; //删除结点
        //合并结点
        HT[i].lchild = T1;
        HT[i].rchild = T2;
        HT[i].weight = HT[T1].weight + HT[T2].weight;
    }
}

//打印输出哈夫曼树所有叶子结点信息
void PrintHuFTree(HuffNode *HT)
{
    cout << "index" << '\t' << "data" << '\t' << "weight" << '\t' << "parent" << '\t' << "lChild" << '\t' << "rChild" << endl;
    for (int i = 1; i <= HT[0].weight; ++i)
    {
        cout << i << "\t";
        cout << HT[i].data << '\t';
        cout << HT[i].weight << '\t';
        cout << HT[i].parent << "\t";
        cout << HT[i].lchild << "\t";
        cout << HT[i].rchild << endl;
    }
}

void PrintHuFTreeCode(HuffNode *HT , map<char , string> &codeDict){
    for (int i = 1; i <= HT[0].data; i++){
        stack<char> CodeStack;
        HuffNode *TempNode = &HT[i];
        HuffNode *TF = &HT[TempNode->parent];
        while (true){
            if (&HT[TF->lchild] == TempNode)   CodeStack.push('0'); //判断当前结点是父亲节点的左节点还是右节点
            else   CodeStack.push('1');
            TempNode = TF;
             if(!TF->parent) break;
            TF = &HT[TF->parent];
        } //从叶子结点向上遍历到root

        // 输出 哈夫曼编码
        // cout<< HT[i].weight << ": ";
        string t = "";
        while (!CodeStack.empty()){
            // cout << CodeStack.top();
            t += CodeStack.top();
            CodeStack.pop();
        }
        // cout << endl;
        codeDict.insert( make_pair( HT[i].data, t) );
    }
}

// 根据哈夫曼树解码字符串 
void DehufCode(HuffNode *HT , map<char , string> codeDict){
    // 演示用
    for(auto i = codeDict.begin();i!=codeDict.end() ;i++)
        cout<< i->first << ": " << i->second << endl;

    string cT;
    cin >> cT;
    cout << "cipherText:  " << "{" << cT << "}" << endl;
    cout << "decode Text: " << "{" ;
    while (cT.length() )
        for(auto i = codeDict.begin();i!=codeDict.end() ;i++){
            int index = cT.find(i->second);
            if(!index)  //匹配
            {
                cout << i->first;
                cT.erase(0, i->second.length() );
            }
        }
    cout << "}" << endl;
}


int main(){
    HuffNode *HT = initial_hufT();
    map<char , string> codeDict;
    createHuFTree(HT);
    PrintHuFTree(HT);
    PrintHuFTreeCode(HT, codeDict);
    DehufCode(HT,  codeDict);

    cin.get();
    cin.get();
    return 0;
}   

运行示例

5 15 7 6 6 5 A B C D E
index   data    weight  parent  lChild  rChild
1       A       15      9       0       0
2       B       7       7       0       0
3       C       6       6       0       0
4       D       6       7       0       0
5       E       5       6       0       0
6               11      8       5       3
7               13      8       4       2
8               24      9       6       7
9               39      0       1       8
A: 0
B: 111
C: 101
D: 110
E: 100
1001101011110
cipherText:  {1001101011110}
decode Text: {EDCBA}
  • 3
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

键盘侠伍十七

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值