吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 4856|回复: 15
收起左侧

[Python 原创] 霍夫曼编码的python和c++实现

[复制链接]
笙若 发表于 2019-1-15 08:05
本帖最后由 笙若 于 2019-1-15 08:17 编辑

最近在学算法,用python和c++各自写了一遍代码,虽然实现的并不是很好,还是贴出来记录一下吧.

class Node:
    def __init__(self, name=None, value=None):
        self._name = name
        self._value = value
        self._left = None
        self._right = None

class HuffmanTree:

    # 根据Huffman树的思想:以叶子节点为基础,根据value排序,反向创建Huffman树
    def __init__(self, char_weights):
        self.a = [Node(key, value) for key, value in dict.items()]
        # 将字典中的key和值逐个添加到节点列表a中
        while len(self.a) != 1:
            self.a.sort(key=lambda node: node._value, reverse=True)  # 按叶子的值排序
            c = Node(value=(self.a[-1]._value + self.a[-2]._value))  
            # 将最小的两个节点的值相加赋给新节点c
            c._left = self.a.pop(-1)
            c._right = self.a.pop(-1)  # 删掉最小的两个节点
            self.a.append(c)  # 将新节点添加到列表中
        self.root = self.a[0]  # 根节点=a中第一个节点
        self.b = list(range(20))  # b用来存储字符的二进制序列
        self.d = {}

    # 递归的思想生成编码
    def pre(self, tree, length):
        node = tree
        if (not node):
            return  # 树为空则直接返回

        elif node._name:  # 当节点是一个字符时进行编码
            str_num = ""
            for i in range(length):
                str_num += str(self.b[i])
            # print(node._name + '编码为:', str_num)
            self.d[node._name] = str_num
            return
        # 在找到字符节点前进行递归
        self.b[length] = 0
        self.pre(node._left, length+1)

        self.b[length] = 1
        self.pre(node._right, length+1)

    # 生成霍夫曼编码
    def get_code(self):
        self.pre(self.root, 0)
        print(self.d)

def fRead(filename):
    symbolDict = {}
    fl = 0
    f = open(filename, 'r')
    str = f.read()
    f.close()
    for i in str:
        for j, k in symbolDict.items():
            if i == j:
                fl = 1
                k = k + 1
                break
        if fl == 0:
            symbolDict[i] = 1
        else:
            symbolDict[i] = k
    return symbolDict

if __name__ == '__main__':

    dict = fRead('test.py')
    tree = HuffmanTree(dict)
    tree.get_code()

顺便吐槽一下vscode真的很严格,写python时连有几个空行都要管.

~~~c++

#include<iostream>
#include<algorithm>
using namespace std;
#define MAXBIT 100
#define MAXVALUE 1000
#define MAXLEAF 30
#define MAXNODE MAXLEAF*2-1
typedef struct //定义节点
{
        double weight;
        int parent;
        int lchild;
        int rchild;
        char value;
}HNodeType;
typedef struct //定义编码类型
{
        int bit[MAXBIT]; //存储01编码的数组
        int start; //编码在数组中开始的位置,从最后往前减小
}HCodeType;
HNodeType HuffNode[MAXNODE]; //定义一个足够大的节点数组
HCodeType HuffCode[MAXLEAF]; 
void HuffmanTree (HNodeType HuffNode[MAXNODE],int n) //构造霍夫曼树
{
        int i,j,x1,x2;
        double m1,m2;
        for(i=0;i<2*n-1;i++) //初始化节点数据
        {
                HuffNode[i].weight = 0;
                HuffNode[i].parent = -1;
                HuffNode[i].lchild = -1;
                HuffNode[i].rchild = -1;
        }
        for(i=0;i<n;i++) //输入节点数据
        {
                cout<<"please input the value and weight of leaf node "<<i+1<<endl;
                cin>>HuffNode[i].value>>HuffNode[i].weight;
        }
        for(i=0;i<n-1;i++) //循环合并n-1次
        {
                m1=m2=MAXVALUE; 
                x1=x2=0;
                for(j=0;j<n+i;j++) //在已有的节点里找权重最小的且没有parent的节点
                {
                        if(HuffNode[j].weight<m1&&HuffNode[j].parent==-1)
                        {
                                m2=m1;
                                x2=x1;
                                m1=HuffNode[j].weight;
                                x1=j;
                        }
                        else if (HuffNode[j].weight<m2&&HuffNode[j].parent==-1)
                        {
                                m2=HuffNode[j].weight;
                                x2=j;
                        }
                } //最后m1,m2为最新权重节点的权重,x1,x2为其位置
                HuffNode[x1].parent=n+i;
                HuffNode[x2].parent=n+i;
                HuffNode[n+i].weight=m1+m2;
                HuffNode[n+i].lchild=x1;
                HuffNode[n+i].rchild=x2;
                cout<<"x1.weight and x2.weight in round "<<i+1<<"\t"<<HuffNode[x1].weight<<"\t"<<HuffNode[x2].weight<<endl;
        }
}
void HuffmanCode(HCodeType HuffCode[MAXLEAF],int n) //对生成的树进行编码
{
        HCodeType cd; //临时结构体
        int i,j,c,p;
        for(i=0;i<n;i++)
        {
                cd.start=n-1;
                c=i;
                p=HuffNode[c].parent; //p为遍历过程中每个节点的parent值
                while(p!=-1) //如果未到根节点
                {
                        if(HuffNode[p].lchild==c) //为parent的左节点则在该处编码为0
                                cd.bit[cd.start]=0;
                        else
                                cd.bit[cd.start]=1;
                        cd.start--; //编码长度加1,start位置减1
                        c=p;
                        p=HuffNode[c].parent;
                }
                for(j=cd.start+1;j<n;j++)
                        HuffCode[i].bit[j]=cd.bit[j]; 
                HuffCode[i].start=cd.start; //将临时变量复制到编码结构体
        }
}
int main()
{
        int i,j,n;
        cout<<""<<endl;
        cin>>n;
        HuffmanTree(HuffNode,n);
        HuffmanCode(HuffCode,n);
        for(i=0;i<n;i++)
        {
                cout<<HuffNode[i].value<<" :Huffman code is: ";
                for(j=HuffCode[i].start+1;j<n;j++)
                        cout<<HuffCode[i].bit[j];
                cout<<endl;
        }
        return 0;
}


然后python写起来简单多了.

免费评分

参与人数 3吾爱币 +7 热心值 +3 收起 理由
wikiyc + 1 + 1 谢谢@Thanks!
苏紫方璇 + 5 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!
chenmg + 1 + 1 谢谢@Thanks!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

 楼主| 笙若 发表于 2019-4-23 21:54
Fris 发表于 2019-4-23 17:22
第12行应该是:
self.a = [Node(key, value) for key, value in char_weights.items()]

感谢大佬提醒,不过因为并没有超出dict的作用域,所以像我那么写也是可以正确运行的吧
Fris 发表于 2019-4-24 07:57
笙若 发表于 2019-4-23 21:54
感谢大佬提醒,不过因为并没有超出dict的作用域,所以像我那么写也是可以正确运行的吧

当前例子可以运行,但作为独立模块被其他模块调用就会出问题
wikiyc 发表于 2019-1-15 08:31
chenmg 发表于 2019-1-15 08:42
可以,很强
565266718 发表于 2019-1-15 09:25
可以,很强
rbgaoshou 发表于 2019-1-15 09:43
学些学习是必要的!
观井映天 发表于 2019-1-15 09:44
python写起来简单,但是提高水平的还是c++
 楼主| 笙若 发表于 2019-1-15 09:49
观井映天 发表于 2019-1-15 09:44
python写起来简单,但是提高水平的还是c++

应该说侧重点不同吧,python水平高了也很厉害的
hackysh 发表于 2019-1-15 09:52
越简单的东西,集成的越多,然后运行效率越低,  
快乐就对了呀 发表于 2019-1-15 19:02
学习一哈
hillman323 发表于 2019-1-16 13:52
厉害,学习下
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-16 07:48

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表