520礼物(利用权重数组建赫夫曼树)

简介: 520礼物(利用权重数组建赫夫曼树)

求赫夫曼编码长度


题目描述

每行一个大小写英文字母组成的字符串,长度不大于 1000,通过前缀编码后最短的编码长度。

输入

第一行输入一个整数t,表示有t组测试数据;

接下来输入t组测试数据,每组数据一行,大小写英文字母。

输出

每组数据输出赫夫曼编码长度

样例输入
4
AABBCCDEEEE
AAABCCC
BBACB
tPvlQHFbPN
样例输出
25
11
7
32
提示
  • 解题思路
  1. 将字符串转换成权重数组
for( int i=0, l= strlen(s); i<l; i++){
    a[ s[i]- 'A']++; // 在ascill里面大写的字母比小
}
  1. 初始化赫夫曼树节点的初始权重
// 初始化w数组
 int wl=1;
 w[0] = big;
 for(int i=0 ; i<99; i++  ){
     if( a[i] != 0 ){
         w[wl++] = a[i];
     }
 }
 wl--;
 root = 2*wl-1;
  1. 搜索最小权重的两棵子树,合并成一棵新树,并入权重数组
  2. dfs 计算赫夫曼编码长度
  • 完整代码
#include<iostream>
#include<cstring>
using namespace std;
const int big = 999;
struct Node{
    int parent,weight,left, right; 
};
Node node[100];
int a[99];
int w[99];
char s[1005];
int root;           // 赫夫曼树根节点下标
int ans;            //赫夫曼树编码的长度
// 搜索权重最小的数组下标
void search(int w[],int &m1,int  &m2, int len){
    for(int i=1; i <= len; i++ ){
        if( w[m1] > w[i] ){
            m1 = i;
        }
    }
    w[m1] = big;
    for(int i=1; i<=len; i++){
        if( w[m2] > w[i] ){
            m2 = i;
        }
    }
    w[m2] = big;
};
// 深搜求长度
void dfs(int index, int cnt){
    int l = node[index].left;
    int r = node[index].right;
    if(l==-1 && r==-1){
        // cout<<"index="<<index<<" cnt="<<cnt<<endl;
        ans += node[index].weight * cnt;
    }
    if(l!=-1){
        dfs(l,++cnt);
        cnt--;  // 注意搜索回溯的时候要将计数器 -1 
    }
    if(r!=-1){
        dfs(r,++cnt);
        cnt--;
    }
}
int main(){
    int t;
    cin >> t;
    while(t--){
        memset(s,'\0', sizeof(s));
        memset(a, 0, sizeof(a));
        memset(w, 0, sizeof(w));
        cin >> s;
        for( int i=0, l= strlen(s); i<l; i++){
            a[ s[i]- 'A']++; // 在ascill里面大写的字母比较小
        }
        // 初始化w数组
        int wl=1;
        w[0] = big;
        for(int i=0 ; i<99; i++  ){
            if( a[i] != 0 ){
                w[wl++] = a[i];
            }
        }
        wl--;
        root = 2*wl-1;
        for(int i=1; i<=root; i++){
            node[i].parent = node[i].left = node[i].right = node[i].weight = -1;
        }
        for(int i=1; i<=wl; i++){
            node[i].weight = w[i];
        }
        // 建树
        for(int i = wl+1; i<=root; i++){
            int m1=0, m2=1;
            search(w, m1, m2, wl);
            node[i].left = m1;
            node[i].right = m2;
            node[i].weight = node[m1].weight + node[m2].weight;
            node[m1].parent = node[m2].parent = i;
            w[++wl] = node[m1].weight + node[m2].weight; 
        }
        // for(int i=root; i>0; i--){
        //     cout<<"i="<<i<<"node[i].parent="<<node[i].parent<<" weight="<<node[i].weight<<" left="<<node[i].left<<" right=" <<node[i].right<<endl;
        // }
        dfs(root,0);
        cout<< ans <<endl;
        ans = 0;
    }
    return 0;
}


相关文章
|
7月前
|
存储 人工智能 算法
图与树的遍历:探索广度优先、深度优先及其他遍历算法的原理与实现
图与树的遍历:探索广度优先、深度优先及其他遍历算法的原理与实现
463 0
|
7月前
|
测试技术
【动态规划】【组合数学】1866. 恰有 K 根木棍可以看到的排列数目
【动态规划】【组合数学】1866. 恰有 K 根木棍可以看到的排列数目
|
6月前
二叉树中的深度搜索
二叉树中的深度搜索
|
6月前
|
存储 算法
算法训练,牛客.判断是不是平衡二叉树 牛客.最大子矩阵两个数组的交集牛客.数组中两个字符串的最小距离
算法训练,牛客.判断是不是平衡二叉树 牛客.最大子矩阵两个数组的交集牛客.数组中两个字符串的最小距离
算法训练,牛客.判断是不是平衡二叉树 牛客.最大子矩阵两个数组的交集牛客.数组中两个字符串的最小距离
|
7月前
|
算法 测试技术 C#
【树 图论 阶乘 组合 深度优先搜索】1916. 统计为蚁群构筑房间的不同顺序
【树 图论 阶乘 组合 深度优先搜索】1916. 统计为蚁群构筑房间的不同顺序
|
7月前
|
人工智能 算法 BI
【图论】【树】 【拓扑排序】2603. 收集树中金币
【图论】【树】 【拓扑排序】2603. 收集树中金币
|
7月前
|
人工智能 算法 BI
【深度优先搜索】【树】【图论】2973. 树中每个节点放置的金币数目
【深度优先搜索】【树】【图论】2973. 树中每个节点放置的金币数目
|
7月前
|
机器学习/深度学习 测试技术
【图论】【状态压缩】【树】【深度优先搜索】1617. 统计子树中城市之间最大距离
【图论】【状态压缩】【树】【深度优先搜索】1617. 统计子树中城市之间最大距离
|
7月前
|
人工智能 算法 BI
【深度优先搜索】【C++算法】834 树中距离之和
【深度优先搜索】【C++算法】834 树中距离之和
|
7月前
|
存储 算法
哈夫曼树(赫夫曼树、最优树)详解
哈夫曼树(赫夫曼树、最优树)详解
172 0