用哈弗曼树对输入的字符串进行编码

该博客介绍了如何使用哈弗曼树对输入的字符串进行编码,但指出该方法存在不支持英文单引号的缺陷。

结果为:
在这里插入图片描述缺陷:对英文单引号不支持

//构造哈夫曼树和哈夫曼编码的算法实现
//统计下面一段英文的不同字符个数和每个字符的出现频率,利用统计数据构造构造哈夫曼树和哈夫曼编码
#include <iostream>
#include<string>
#include <map>

using namespace std;

map<char, int> mapData;
map<char, int>::iterator it;

struct HuffManNode {
    string data;

    int parent{};

    int leftChild{};
    int rightChild{};

    int weight{};
};

void findTheSmallest(HuffManNode tree[], int range, int &target1, int &target2) {
    //找一个没有双亲的结点赋值给target1
    for (int i = 1; i <= range; ++i) {
        if (tree[i].parent == 0) {
            target1 = i;
            break;
        }
    }

    for (int i = 1; i <= range; ++i) {
        if (tree[i].parent != 0) {
            continue;
        } else if (tree[i].weight < tree[target1].weight) {
            target1 = i;
        }
    }

    //找一个没有双亲的结点赋值给target2且target2 != target1
    for (int i = 1; i <= range; ++i) {
        if (tree[i].parent == 0 && i != target1) {
            target2 = i;
            break;
        }
    }

    for (int i = 1; i <= range; ++i) {
        if (tree[i].parent != 0) {
            continue;
        } else if (tree[i].weight < tree[target2].weight && i != target1) {
            target2 = i;
        }
    }
}

void buildHuffManTree(HuffManNode *&tree, int nodeNum) {
    //对二叉树的节点进行初始化
    int allNodeNum = 2 * nodeNum - 1;
    tree = new HuffManNode[allNodeNum + 1];

    for (int i = 1; i <= allNodeNum; ++i) {
        tree[i].rightChild = 0;
        tree[i].leftChild = 0;
        tree[i].parent = 0;
        tree[i].weight = 0;
    }

    //对二叉树进行赋值
    it = mapData.begin();
    for (int j = 1; j <= nodeNum; ++j) {
        tree[j].data = it->first;
        tree[j].weight = it->second;
        ++it;
    }


    //开始构建二叉树
    int target1;
    int target2;
    for (int k = nodeNum + 1; k <= allNodeNum; ++k) {
        //选取权重最小的双亲为0的两个节点的下标
        findTheSmallest(tree, k - 1, target1, target2);

        tree[target1].parent = k;
        tree[target2].parent = k;

        tree[k].leftChild = target1;
        tree[k].rightChild = target2;
        tree[k].weight = tree[target1].weight + tree[target2].weight;
    }
}

void travelHuffManTree(HuffManNode *&tree, int targetPosition) {
    cout << tree[targetPosition].weight << " 、";

    if (tree[targetPosition].leftChild != 0) {
        travelHuffManTree(tree, tree[targetPosition].leftChild);
    }
    if (tree[targetPosition].rightChild != 0) {
        travelHuffManTree(tree, tree[targetPosition].rightChild);
    }
}

void codingHuffManTree(HuffManNode *&tree, int targetPosition, const string &codingData) {
    if (tree[targetPosition].rightChild == 0 && tree[targetPosition].leftChild == 0) {
        cout << tree[targetPosition].data << " : " << codingData << endl;
    } else {
        string data = codingData + "0";
        codingHuffManTree(tree, tree[targetPosition].leftChild, codingData + "0");
        codingHuffManTree(tree, tree[targetPosition].rightChild, codingData + "1");
    }

}

int main() {
    int nodeNum;
    string inputData;
    cout << "(1)请输入字符串:";
    getline(cin, inputData);

    {
        //替换所有空格
        int index = 0;
        while ((index = inputData.find(' ', index)) != string::npos) {
            inputData[index] = '/';
        }

        int inputDataSize = inputData.size();
        for (int i = 0; i < inputDataSize; ++i) {
            if (mapData.find(inputData[i]) == mapData.end()) {
                mapData[inputData[i]] = 1;
            } else {
                ++mapData[inputData[i]];
            }
        }

        cout<<"(2)各字符出现次数为:";
        for (it = mapData.begin(); it != mapData.end(); it++)
            cout << it->first << ":" << it->second << "、";
        cout<<endl;
    }

    nodeNum = mapData.size();

    HuffManNode *tree1;
    //开始构建哈夫曼树
    buildHuffManTree(tree1, nodeNum);

//    cout << "先序遍历输出哈弗曼树各结点的权:";
//    travelHuffManTree(tree1, 2 * nodeNum - 1);
//    cout << endl;

    cout<<"(3)编码结果为(其中空格使用‘/’代替):";
    codingHuffManTree(tree1, 2 * nodeNum - 1, "");
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值