贪心算法-哈夫曼编码

《算法导论》引理16.2:令C为一个字母表,其中每个字符c属于C都有一个频率c.freq。令x和y是C中频率最低的两个字符,那么存在C的一个最优前缀码,x和y的码字长度相同,且只有最后一个二进制位不同。(证明问题具有贪心选择性质

引理16.3 令C为一个给定的字符表,其中每个字符c属于C都定义了一个频率c.freq。令x和y是C中频率最低的两个字符。令C1为C去掉字符x和y,加入一个新字符z后得到的字母表。这里z.freq=x.freq+y.freq。令T1为C1的任意一个最优前缀对应的编码树。于是我们将T1中叶结点z替换为一个以x和y为孩子的内部结点,得到树T,T表示字母表C的一个最优前缀码。(证明了构造最优前缀码的问题具有最优子结构性质

字母表每个元素的结构

struct word {
    char c;
    int freq;
    string b;
    string code;
    int parents;
    int left;
    int right;
    word() {
        c = ' ';
        parents = -1;
        left = -1;
        right = -1;
    }
    word(char ch, int f) :c(ch), freq(f) {
        parents=-1;
        left=-1;
        right=-1;
    }
};
  • 1
//构造哈夫曼树
word huffman(word *w,int n) {
    int s = n;
    for (int i = 1; i <= n-1; i++) {
        int minL = 0, minR = 0;
        for (int j = 1; j <= s; j++) {
            //数组中的最小值
            if (w[j].freq < w[minL].freq&&w[j].parents == -1)
                minL = j;
        }
        for (int j = 1; j <= s; j++) {
            //数组中的次小值(可以与最小值相等)
            if (w[j].freq >= w[minL].freq&&w[j].freq<w[minR].freq&&j!=minL&&w[j].parents == -1)
                minR = j;
        }
        s++;
        w[s].freq = w[minL].freq + w[minR].freq;
        w[s].left = minL;
        w[s].right = minR;
        w[minL].parents = s;
        //左孩子与父结点连接的边对应编码0
        w[minL].b = "0";
        w[minR].parents = s;
        //右孩子与父结点连接的边对应编码1
        w[minR].b = "1";
    }
    //if (s == 2 * n - 1) cout << "-----------right";
    cout << w[s].freq;
    return w[s - 1];
}

void huffmanCode(word *w,int n) {
    for (int i = 1; i <= n; i++) {
        int j = i;
        while (w[j].parents != -1) {
            w[i].code += w[j].b;
            j = w[j].parents;
        }
        //因为上面的循环过程是从叶子结点向根节点遍历,因此最后得到的编码要将顺序调换
        reverse(w[i].code.begin(), w[i].code.end());
    }
}

int main() {
    //这个元素便于后面比较
    word w0(' ', 0x7fffffff);
    word w1('a', 45);
    word w2('b', 13);
    word w3('c', 12);
    word w4('d', 16);
    word w5('e', 9);
    word w6('f', 5);
    int n = 6;
    //哈夫曼树一定有2*n-1个结点,将树的结点都存到数组w中
    word w[12] = { w0,w1,w2,w3,w4,w5,w6 };
    huffman(w, 6);
    huffmanCode(w, 6);
    return 0;

}
  • 1
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

苦茶子12138

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

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

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

打赏作者

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

抵扣说明:

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

余额充值