PHP前端开发

如何利用Python和C语言分别实现哈夫曼编码

百变鹏仔 2周前 (01-21) #Python
文章标签 语言

1.C语言实现

1.1代码说明

a  创建双向链表:

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

'''C#include <stdlib.h>#include <stdio.h>#include <windows.h>  //哈夫曼树结构体,数据域存储字符及其权重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-&gt;pre = NULL;    temp1-&gt;next = temp2;    temp1-&gt;root = (Tree)malloc(sizeof(Huffman));    temp1-&gt;root-&gt;c = 'a';    temp1-&gt;root-&gt;weight = 22;    temp1-&gt;root-&gt;lchild = NULL;    temp1-&gt;root-&gt;rchild = NULL;         temp2-&gt;pre = temp1;    temp1 = temp2;    temp2 = (pList)malloc(sizeof(List));    temp1-&gt;next = temp2;    temp1-&gt;root = (Tree)malloc(sizeof(Huffman));    temp1-&gt;root-&gt;c = 'b';    temp1-&gt;root-&gt;weight = 5;    temp1-&gt;root-&gt;lchild = NULL;    temp1-&gt;root-&gt;rchild = NULL;         temp2-&gt;pre = temp1;    temp1 = temp2;    temp2 = (pList)malloc(sizeof(List));    temp1-&gt;next = temp2;    temp1-&gt;root = (Tree)malloc(sizeof(Huffman));    temp1-&gt;root-&gt;c = 'c';    temp1-&gt;root-&gt;weight = 38;    temp1-&gt;root-&gt;lchild = NULL;    temp1-&gt;root-&gt;rchild = NULL;     temp2-&gt;pre = temp1;    temp1 = temp2;    temp2 = (pList)malloc(sizeof(List));    temp1-&gt;next = temp2;    temp1-&gt;root = (Tree)malloc(sizeof(Huffman));    temp1-&gt;root-&gt;c = 'd';    temp1-&gt;root-&gt;weight = 9;    temp1-&gt;root-&gt;lchild = NULL;    temp1-&gt;root-&gt;rchild = NULL;     temp2-&gt;pre = temp1;    temp1 = temp2;    temp2 = (pList)malloc(sizeof(List));    temp1-&gt;next = temp2;    temp1-&gt;root = (Tree)malloc(sizeof(Huffman));    temp1-&gt;root-&gt;c = 'e';    temp1-&gt;root-&gt;weight = 44;    temp1-&gt;root-&gt;lchild = NULL;    temp1-&gt;root-&gt;rchild = NULL;     temp2-&gt;pre = temp1;    temp1 = temp2;    temp2 = (pList)malloc(sizeof(List));    temp1-&gt;next = temp2;    temp1-&gt;root = (Tree)malloc(sizeof(Huffman));    temp1-&gt;root-&gt;c = 'f';    temp1-&gt;root-&gt;weight = 12;    temp1-&gt;root-&gt;lchild = NULL;    temp1-&gt;root-&gt;rchild = NULL;     temp2-&gt;pre = temp1;    temp1 = temp2;    temp1-&gt;next = NULL;    temp1-&gt;root = (Tree)malloc(sizeof(Huffman));    temp1-&gt;root-&gt;c = 'g';    temp1-&gt;root-&gt;weight = 65;    temp1-&gt;root-&gt;lchild = NULL;    temp1-&gt;root-&gt;rchild = NULL;     return head;                          }</windows.h></stdio.h></stdlib.h>

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-&gt;top - s-&gt;base &gt;= s-&gt;size)    {        s-&gt;size += STACK_INCREMENT;        s-&gt;base = realloc(s-&gt;base, sizeof(char)*s-&gt;size);    }    *s-&gt;top = e;    s-&gt;top++;} //出栈char charPop(charStack *s){    if(s-&gt;top != s-&gt;base)    {        s-&gt;top--;        return *s-&gt;top;    }    return -1;} //得到栈顶元素,但不出栈char charGetTop(charStack *s){    s-&gt;top--;    char temp = *s-&gt;top;    s-&gt;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-&gt;top - s-&gt;base &gt;= s-&gt;size)    {        s-&gt;size += STACK_INCREMENT;        s-&gt;base = (Huffman *)realloc(s-&gt;base, sizeof(Huffman)*s-&gt;size);    }    *s-&gt;top = e;    s-&gt;top++;} //出栈Huffman pop(BiStack *s){    Huffman temp;    s-&gt;top--;    temp = *s-&gt;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 创建哈夫曼树:

立即学习“Python免费学习笔记(深入)”;

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

d编码:

'''Cchar 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(&amp;bs, root);      //根结点入栈    while(bs.top != bs.base)      //栈空表示遍历结束    {        root = getTop(bs);        temp = root.lchild;       //先访问左孩子        while(temp != NULL)       //左孩子不为空        {            //将结点左孩子设为空,代表已访问其左孩子            root.lchild = NULL;            pop(&amp;bs);                        push(&amp;bs, root);            //左孩子入栈            root = *temp;            temp = root.lchild;            push(&amp;bs, root);            //'0'入字符栈            charPush(&amp;cs, '0');        }        temp = root.rchild;     //后访问右孩子             while(temp == NULL)     //右孩子为空,代表左右孩子均已访问,结点可以出栈         {            //结点出栈            root = pop(&amp;bs);            //寻到叶子结点,可以得到结点中字符的编码            if(root.c != ' ')                traverseStack(cs, root.c);            charPop(&amp;cs);       //字符栈出栈            if(bs.top == bs.base) break;    //根结点出栈,遍历结束            //查看上一级结点是否访问完左右孩子              root = getTop(bs);            temp = root.rchild;                   }        if(bs.top != bs.base)        {            //将结点右孩子设为空,代表已访问其右孩子            root.rchild = NULL;                   pop(&amp;bs);            push(&amp;bs, root);            //右孩子入栈            root = *temp;                  push(&amp;bs, root);            //'1'入字符栈            charPush(&amp;cs, '1');        }        }}

e解码:

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

f主函数:

'''Cvoid main(){    pList pl = creatList();    printf("字符的权重如下");    for(pList l = pl; l-&gt;next != NULL; l = l-&gt;next)        printf("字符%c的权重是 %d", l-&gt;root-&gt;c, l-&gt;root-&gt;weight);    Tree T = creatHuffman(pl);    encodeHuffman(T);    printf("字符编码结果如下");    for(int i = 0; i <h4>1.2运行结果</h4><p><img src="https://img.php.cn/upload/article/000/000/164/168473436956762.png" alt="如何利用Python和C语言分别实现哈夫曼编码"></p><h3>2.Python实现</h3><h4>2.1代码说明</h4><p>a创建哈夫曼树:</p><pre class="brush:py;">#coding=gbk import datetimeimport timefrom 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) &gt; 1:               #列表只剩一个结点时循环结束,此结点即为哈夫曼树的根结点        i = 0        j = 1        k = 2        while k  list[k].weight or list[j].weight &gt; list[k].weight:                if list[i].weight &gt; list[j].weight:                    i = k                else:                    j = k            k += 1               root = Huffman(' ', list[i].weight + list[j].weight) #新结点字符统一设为空格,权重设为list1与list2权重之和           if list[i].weight <p>b编码:</p><pre class="brush:py;">#通过哈夫曼树编码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 <p>d主函数:</p><pre class="brush:py;">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("字符编码结果如下")    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("请输入编码:")    #哈夫曼树在编码时被破坏,必须重建哈夫曼树    list = creatList()    T = creatHuffman(list)    decode = decodeHuffman(T, strCode)    print("解码结果如下:")    for i in range(len(decode)):        print(decode[i], end='')    print("")    datetime = datetime.datetime.now()    print(datetime.strftime("%Y-%m-%d%H:%M:%S"))    input("Press Enter to exit…")

2.2运行结果