当前位置:

首页 > 编程开发 > 如何使用Python和C语言实现哈夫曼编码?

如何使用Python和C语言实现哈夫曼编码?

1.C语言实现1.1代码说明a创建双向链表:在创建哈夫曼树的过程中,需要不断对结点进行更改和删除,所以选用双向链表的结构更容易'''C#include#include#include//哈夫曼树结构体,数据域存储字符及其权重typedefstructnode{charc;intweight;structnode*lchild,*rchild;}Huffman,*Tree;//双向链表结构体,数据域存储哈夫曼树结点typedefstructlist{Treeroot;structli

本文目录

    1.C语言实现

    1.1代码说明

    a  创建双向链表:

    在创建哈夫曼树的过程中,需要不断对结点进行更改和删除,所以选用双向链表的结构更容易

    '''C
    #include 
    #include 
    #include 
     
     
    //哈夫曼树结构体,数据域存储字符及其权重
    typedef struct node
    {
        char c;
        int weight;
        struct node *lchild, *rchild;
    }Huffman, *Tree;
     
     
    //双向链表结构体,数据域存储哈夫曼树结点
    typedef struct list
    {
        Tree root;
        struct list *pre;
        struct list *next;
    }List, *pList;
     
     
    //创建双向链表,返回头结点指针
    pList creatList()
    {
        pList head = (pList)malloc(sizeof(List));
     
        pList temp1 = head;
        pList temp2 = (pList)malloc(sizeof(List));
        temp1->pre = NULL;
        temp1->next = temp2;
        temp1->root = (Tree)malloc(sizeof(Huffman));
        temp1->root->c = 'a';
        temp1->root->weight = 22;
        temp1->root->lchild = NULL;
        temp1->root->rchild = NULL;
        
     
        temp2->pre = temp1;
        temp1 = temp2;
        temp2 = (pList)malloc(sizeof(List));
        temp1->next = temp2;
        temp1->root = (Tree)malloc(sizeof(Huffman));
        temp1->root->c = 'b';
        temp1->root->weight = 5;
        temp1->root->lchild = NULL;
        temp1->root->rchild = NULL;
        
     
        temp2->pre = temp1;
        temp1 = temp2;
        temp2 = (pList)malloc(sizeof(List));
        temp1->next = temp2;
        temp1->root = (Tree)malloc(sizeof(Huffman));
        temp1->root->c = 'c';
        temp1->root->weight = 38;
        temp1->root->lchild = NULL;
        temp1->root->rchild = NULL;
     
        temp2->pre = temp1;
        temp1 = temp2;
        temp2 = (pList)malloc(sizeof(List));
        temp1->next = temp2;
        temp1->root = (Tree)malloc(sizeof(Huffman));
        temp1->root->c = 'd';
        temp1->root->weight = 9;
        temp1->root->lchild = NULL;
        temp1->root->rchild = NULL;
     
        temp2->pre = temp1;
        temp1 = temp2;
        temp2 = (pList)malloc(sizeof(List));
        temp1->next = temp2;
        temp1->root = (Tree)malloc(sizeof(Huffman));
        temp1->root->c = 'e';
        temp1->root->weight = 44;
        temp1->root->lchild = NULL;
        temp1->root->rchild = NULL;
     
        temp2->pre = temp1;
        temp1 = temp2;
        temp2 = (pList)malloc(sizeof(List));
        temp1->next = temp2;
        temp1->root = (Tree)malloc(sizeof(Huffman));
        temp1->root->c = 'f';
        temp1->root->weight = 12;
        temp1->root->lchild = NULL;
        temp1->root->rchild = NULL;
     
        temp2->pre = temp1;
        temp1 = temp2;
        temp1->next = NULL;
        temp1->root = (Tree)malloc(sizeof(Huffman));
        temp1->root->c = 'g';
        temp1->root->weight = 65;
        temp1->root->lchild = NULL;
        temp1->root->rchild = NULL;
     
        return head;                          
    }

    b创建栈结构:

    解码过程需要用到两个栈,一个用来存放树结点,一个用来存放码0和1

    '''C
    #define STACK_INIT_SIZE 100   //栈初始开辟空间大小
    #define STACK_INCREMENT 10    //栈追加空间大小
     
    //字符栈结构体,存放编码'0'和'1'
    typedef struct {
        char *base;
        char *top;
        int size;
    }charStack;
     
     
    //栈初始化
    charStack charStackInit()
    {
        charStack s;
        s.base = (char *)malloc(sizeof(char)*STACK_INIT_SIZE);
        s.top = s.base;
        s.size = STACK_INIT_SIZE;
        return s;
    }
     
    //入栈
    void charPush(charStack *s, char e)
    {
        if(s->top - s->base >= s->size)
        {
            s->size += STACK_INCREMENT;
            s->base = realloc(s->base, sizeof(char)*s->size);
        }
        *s->top = e;
        s->top++;
    }
     
    //出栈
    char charPop(charStack *s)
    {
        if(s->top != s->base)
        {
            s->top--;
            return *s->top;
        }
        return -1;
    }
     
    //得到栈顶元素,但不出栈
    char charGetTop(charStack *s)
    {
        s->top--;
        char temp = *s->top;
        s->top++;
        return temp;
    }
     
    //栈结构体,存放哈夫曼树结点
    typedef struct 
    {
        Huffman *base;
        Huffman *top;
        int size;
    }BiStack;
     
    //栈初始化
    BiStack stackInit()
    {
        BiStack s;
        s.base = (Huffman *)malloc(sizeof(Huffman)*STACK_INIT_SIZE);
        s.top = s.base;
        s.size =STACK_INIT_SIZE;
        return s;
    }
     
    //入栈
    void push(BiStack *s, Huffman e)
    {
        if(s->top - s->base >= s->size)
        {
            s->size += STACK_INCREMENT;
            s->base = (Huffman *)realloc(s->base, sizeof(Huffman)*s->size);
        }
        *s->top = e;
        s->top++;
    }
     
    //出栈
    Huffman pop(BiStack *s)
    {
        Huffman temp;
        s->top--;
        temp = *s->top;
        return temp;
    }
     
    //得到栈顶元素,但不出栈
    Huffman getTop(BiStack s)
    {
        Huffman temp;
        s.top--;
        temp = *s.top;
        return temp;
    }
     
    char stack[7][10];             //记录a~g的编码
    //遍历栈,得到字符c的编码
    void traverseStack(charStack s, char c)
    {
        int index = c - 'a'; 
        int i = 0;
        while(s.base != s.top)
        {
            stack[index][i] = *s.base;
            i++;
            s.base++;
        }
    }

    c 创建哈夫曼树:

    '''C
    //通过双向链表创建哈夫曼树,返回根结点指针
    Tree creatHuffman(pList head)
    {
        pList list1 = NULL;
        pList list2 = NULL;
        pList index = NULL;
        Tree root = NULL;
        while(head->next != NULL)   //链表只剩一个结点时循环结束,此结点数据域即为哈夫曼树的根结点
        {
            list1 = head;
            list2 = head->next;
            index = list2->next;
            root = (Tree)malloc(sizeof(Huffman));
            while(index != NULL)    //找到链表中权重最小的两个结点list1,list2
            {
                if(list1->root->weight > index->root->weight || list2->root->weight > index->root->weight)
                {
                    if(list1->root->weight > list2->root->weight) list1 = index;
                    else list2 = index;
                }
                index = index->next;
            }
            //list1和list2设为新结点的左右孩子
            if(list2->root->weight > list1->root->weight)
            {
                root->lchild = list1->root;
                root->rchild = list2->root;
            }
            else
            {
                root->lchild = list2->root;
                root->rchild = list1->root;
            }
            //新结点字符统一设为空格,权重设为list1与list2权重之和
            root->c = ' ';
            root->weight = list1->root->weight + list2->root->weight;
            //list1数据域替换成新结点,并删除list2
            list1->root = root;
            list2->pre->next = list2->next;
            if(list2->next != NULL)
                list2->next->pre = list2->pre;    
        }
        return head->root;
    }

    d编码:

    '''C
    char stack[7][10];             //记录a~g的编码
    //遍历栈,得到字符c的编码
    void traverseStack(charStack s, char c)
    {
        int index = c - 'a'; 
        int i = 0;
        while(s.base != s.top)
        {
            stack[index][i] = *s.base;
            i++;
            s.base++;
        }
    }
     
     
    //通过哈夫曼树编码
    void encodeHuffman(Tree T)
    {  
        BiStack bs = stackInit();
        charStack cs = charStackInit();
        Huffman root = *T;  
        Tree temp = NULL;
        push(&bs, root);      //根结点入栈
        while(bs.top != bs.base)      //栈空表示遍历结束
        {
            root = getTop(bs);
            temp = root.lchild;       //先访问左孩子
            while(temp != NULL)       //左孩子不为空
            {
                //将结点左孩子设为空,代表已访问其左孩子
                root.lchild = NULL;
                pop(&bs);            
                push(&bs, root);
                //左孩子入栈
                root = *temp;
                temp = root.lchild;
                push(&bs, root);
                //'0'入字符栈
                charPush(&cs, '0');
            }
            temp = root.rchild;     //后访问右孩子     
            while(temp == NULL)     //右孩子为空,代表左右孩子均已访问,结点可以出栈 
            {
                //结点出栈
                root = pop(&bs);
                //寻到叶子结点,可以得到结点中字符的编码
                if(root.c != ' ')
                    traverseStack(cs, root.c);
                charPop(&cs);       //字符栈出栈
                if(bs.top == bs.base) break;    //根结点出栈,遍历结束
                //查看上一级结点是否访问完左右孩子  
                root = getTop(bs);
                temp = root.rchild;           
            }
            if(bs.top != bs.base)
            {
                //将结点右孩子设为空,代表已访问其右孩子
                root.rchild = NULL;       
                pop(&bs);
                push(&bs, root);
                //右孩子入栈
                root = *temp;      
                push(&bs, root);
                //'1'入字符栈
                charPush(&cs, '1');
            }    
        }
    }

    e解码:

    '''C
    char decode[100];   //记录解码得到的字符串
    //通过哈夫曼树解码
    void decodeHuffman(Tree T, char *code)
    {
        int cnt = 0;
        Tree root;
        while(*code != '\0')                  //01编码字符串读完,解码结束
        {
            root = T;
            while(root->lchild != NULL)       //找到叶子结点
            {
                if(*code != '\0')
                {
                    if(*code == '0')
                        root = root->lchild;
                    else
                        root = root->rchild;
                    code++;
                }
                else break;
            }
            decode[cnt] = root->c;             //叶子结点存放的字符即为解码得到的字符
            cnt++;
        }
    }

    f主函数:

    '''C
    void main()
    {
        pList pl = creatList();
        printf("字符的权重如下\n");
        for(pList l = pl; l->next != NULL; l = l->next)
            printf("字符%c的权重是 %d\n", l->root->c, l->root->weight);
        Tree T = creatHuffman(pl);
        encodeHuffman(T);
        printf("\n\n字符编码结果如下\n");
        for(int i = 0; i < 7; i++)
            printf("%c : %s\n", i+'a', stack[i]);
        char code[100];
        printf("\n\n请输入编码:\n");
        scanf("%s", code);
        printf("解码结果如下:\n");
        decodeHuffman(T, code);
        printf("%s\n", decode);
        printf("\n\n");
        system("date /T");
        system("TIME /T");
        system("pause");
        exit(0); 
    }

    1.2运行结果

    如何使用Python和C语言实现哈夫曼编码?

    2.Python实现

    2.1代码说明

    a创建哈夫曼树:

    #coding=gbk
     
    import datetime
    import time
    from pip._vendor.distlib.compat import raw_input
     
    #哈夫曼树结点类
    class Huffman:
        def __init__(self, c, weight):
            self.c = c
            self.weight = weight
            self.lchild = None
            self.rchild = None
        
        #创建结点左右孩子    
        def creat(self, lchild, rchild):
            self.lchild = lchild
            self.rchild = rchild
     
    #创建列表        
    def creatList():
        list = []
        list.append(Huffman('a', 22))
        list.append(Huffman('b', 5))
        list.append(Huffman('c', 38))
        list.append(Huffman('d', 9))
        list.append(Huffman('e', 44))
        list.append(Huffman('f', 12))
        list.append(Huffman('g', 65))
        return list
     
    #通过列表创建哈夫曼树,返回树的根结点
    def creatHuffman(list):
        while len(list) > 1:               #列表只剩一个结点时循环结束,此结点即为哈夫曼树的根结点
            i = 0
            j = 1
            k = 2
            while k < len(list):           #找到列表中权重最小的两个结点list1,list2          
                if list[i].weight > list[k].weight or list[j].weight > list[k].weight:
                    if list[i].weight > list[j].weight:
                        i = k
                    else:
                        j = k
                k += 1       
            root = Huffman(' ', list[i].weight + list[j].weight) #新结点字符统一设为空格,权重设为list1与list2权重之和   
            if list[i].weight < list[j].weight:                  #list1和list2设为新结点的左右孩子
                root.creat(list[i], list[j])
            else:
                root.creat(list[j], list[i])
            #list1数据域替换成新结点,并删除list2
            list[i] = root
            list.remove(list[j])
        return list[0]

    b编码:

    #通过哈夫曼树编码
    def encodeHuffman(T):
        code = [[], [], [], [], [], [], []]
        #列表实现栈结构
        treeStack = []
        codeStack = []
        treeStack.append(T)
        while treeStack != []:        #栈空代表遍历结束
            root = treeStack[-1]
            temp = root.lchild
            while temp != None:
                #将结点左孩子设为空,代表已访问其左孩子
                root.lchild = None        
                #左孩子入栈          
                treeStack.append(temp)         
                root = temp
                temp = root.lchild
                #0入编码栈
                codeStack.append(0)
            temp = root.rchild            #后访问右孩子
            while temp == None:           #右孩子为空,代表左右孩子均已访问,结点可以出栈
                root = treeStack.pop()           #结点出栈
                #寻到叶子结点,可以得到结点中字符的编码
                if root.c != ' ':
                    codeTemp = codeStack.copy()
                    code[ord(root.c) - 97] = codeTemp     
                if treeStack == []:    #根结点出栈,遍历结束
                    break
                codeStack.pop()        #编码栈出栈
                #查看上一级结点是否访问完左右孩子
                root = treeStack[-1]
                temp = root.rchild
            if treeStack != []:
                treeStack.append(temp)     #右孩子入栈
                root.rchild = None         #将结点右孩子设为空,代表已访问其右孩子
                codeStack.append(1)        #1入编码栈
        return code

    c解码:

    #通过哈夫曼树解码
    def decodeHuffman(T, strCode):
        decode = []
        index = 0
        while index < len(strCode):        #01编码字符串读完,解码结束
            root = T
            while root.lchild != None:     #找到叶子结点
                if index < len(strCode):
                    if strCode[index] == '0':
                        root = root.lchild
                    else:
                        root = root.rchild
                    index += 1
                else:
                    break
            decode.append(root.c)           #叶子结点存放的字符即为解码得到的字符
        return decode

    d主函数:

    if __name__ == '__main__':
        list = creatList()
        print("字符的权重如下")
        for i in range(len(list)):
            print("字符{}的权重为: {}".format(chr(i+97), list[i].weight))
        T = creatHuffman(list)
        code = encodeHuffman(T)
        print("\n字符编码结果如下")
        for i in range(len(code)):
            print(chr(i+97), end=' : ')
            for j in range(len(code[i])):
                print(code[i][j], end='')
            print("")
        strCode = input("\n请输入编码:\n")
        #哈夫曼树在编码时被破坏,必须重建哈夫曼树
        list = creatList()
        T = creatHuffman(list)
        decode = decodeHuffman(T, strCode)
        print("解码结果如下:")
        for i in range(len(decode)):
            print(decode[i], end='')
        print("\n\n")
        datetime = datetime.datetime.now()
        print(datetime.strftime("%Y-%m-%d\n%H:%M:%S"))
        input("Press Enter to exit…")

    2.2运行结果

    如何使用Python和C语言实现哈夫曼编码?

    本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系bd@zhengruan.com
    作者最新文章
    编程开发 Python C语言
    相关文章 更多
    python删除一个列表里的重复元素的方法与代码示例
    python删除一个列表里的重复元素的方法与代码示例

    学习如何使用Python高效删除列表中的重复元素。本文提供5种常见方法的代码示例,涵盖保持顺序与不保持顺序的场景,适合初学者和进阶开发者参考。

    Python写接口的步骤及完整代码示例
    Python写接口的步骤及完整代码示例

    详细讲解使用Python编写Web接口的核心步骤与完整代码示例,涵盖环境准备、路由定义、数据校验、服务启动及调试测试方法。

    codex怎么读取word文档及docx文件操作教程
    codex怎么读取word文档及docx文件操作教程

    介绍如何利用编程工具读取和解析Word文档(docx格式),涵盖基础文本提取代码示例、结构化数据处理逻辑,以及处理复杂排版时的技术局限与替代方案。

    怎么在Python中调用C语言代码提升性能
    怎么在Python中调用C语言代码提升性能

    详细讲解在Python中调用C语言代码提升性能的完整实践指南,包含原理分析、编译步骤、ctypes与CFFI具体实现、性能对比及常见陷阱。

    Python与C语言的性能差异及底层原理
    Python与C语言的性能差异及底层原理

    深入解析Python与C语言在执行效率上的数量级差异,从编译机制、变量内存布局、动态类型推断到GIL锁,系统阐明底层核心原理。

    Python和C语言哪个更适合编程入门
    Python和C语言哪个更适合编程入门

    客观对比Python与C语言在心智负担、底层机制与学习反馈上的核心差异,提供清晰有据的选择标准与切实的入门学习路径。

    selenium上传文件教程本地文件路径设置方法
    selenium上传文件教程本地文件路径设置方法

    深入解析Selenium处理文件上传的技术细节,涵盖标准HTML控件的路径直接注入法与非标准控件的系统级模拟方案,提供Windows与Linux环境下的路径设置最佳实践及常见异常排查。

    大数据开发语言选型:Java对比Scala与Python的优缺点及适用场景
    大数据开发语言选型:Java对比Scala与Python的优缺点及适用场景

    针对大数据工程场景,系统对比Java、Scala与Python在执行性能、生态结合、开发效率和维护成本上的核心差异,给出清晰的架构选型依据与落地方案。

    c语言段错误处理方法及排查解决步骤
    c语言段错误处理方法及排查解决步骤

    针对C语言常见的段错误(Segmentation fault)问题,详细剖析内存非法访问根因,提供结合GDB、Core Dump与AddressSanitizer的标准化排查解决步骤与预防方法。

    langgraph python guide中文入门教程详解
    langgraph python guide中文入门教程详解

    本篇LangGraph Python中文入门教程详解,系统梳理StateGraph状态机定义、节点编写、边与条件路由、检查点持久化(MemorySaver)等核心机制,提供从环境安装到完整循环智能体构建的代码示例与实操指导。

    查看更多
    精品专题 更多
    装机必备
    装机必备

    正软商城装机必备专区,精选办公、浏览器、安全防护、影音播放、压缩解压、设计创作和系统工具等电脑常用正版软件,帮助用户快速完成新电脑软件配置。

    Windows
    Windows

    正软商城Windows软件专区,汇集适用于Windows电脑的办公、设计、安全防护、影音播放、开发工具和系统优化软件,提供软件介绍、系统要求、正版授权及购买下载服务。

    PDF教程
    PDF教程

    正软商城PDF教程频道提供PDF编辑、转换、合并、拆分、压缩及格式处理方法,同时介绍常用PDF软件和工具的使用技巧。

    Mac软件 更多
    讯飞智作 网页版
    讯飞智作 网页版
    Windows/ macOS/ Linux

    讯飞智作是一款基于语音合成技术、虚拟人驱动技术与数字人形象声音构建能力的 AI 数字人音视频创作平台。

    火山引擎 网页版
    火山引擎 网页版
    Windows/ macOS/ Linux

    火山引擎是字节跳动旗下企业级云与AI服务平台。聚焦大模型核心能力,依托字节自研豆包多模态大模型,凭借火山方舟一站式平台,提供模型精调、推理部署、智能应用搭建等全链路服务,结合高性能AI算力,助力各行业快速落地大模型数字化与智能化应用。

    Aperty macOS版
    Aperty macOS版
    macOS

    Aperty 是 Skylum 推出的 AI 人像修图软件,支持自然肤质修饰、瑕疵处理、面部与身体调整、预设及批量同步。

    WINDOWS 更多
    讯飞智作 网页版
    讯飞智作 网页版
    Windows/ macOS/ Linux

    讯飞智作是一款基于语音合成技术、虚拟人驱动技术与数字人形象声音构建能力的 AI 数字人音视频创作平台。

    火山引擎 网页版
    火山引擎 网页版
    Windows/ macOS/ Linux

    火山引擎是字节跳动旗下企业级云与AI服务平台。聚焦大模型核心能力,依托字节自研豆包多模态大模型,凭借火山方舟一站式平台,提供模型精调、推理部署、智能应用搭建等全链路服务,结合高性能AI算力,助力各行业快速落地大模型数字化与智能化应用。

    PixTV 网页版
    PixTV 网页版
    Windows

    PixTV 是一款在浏览器中使用的 AI 视觉内容创作平台,提供图片、视频、音频、文字生成、AI 分镜、局部重绘、提示词反推和无限画布等工具,适合短剧、漫剧、广告及社交媒体内容制作。