<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
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->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 != ' ') //01編碼字串讀完,解碼結束 { root = T; while(root->lchild != NULL) //找到葉子結點 { if(*code != ' ') { 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的權重是 %dn", l->root->c, l->root->weight); Tree T = creatHuffman(pl); encodeHuffman(T); printf("nn字元編碼結果如下n"); for(int i = 0; i < 7; i++) printf("%c : %sn", i+'a', stack[i]); char code[100]; printf("nn請輸入編碼:n"); scanf("%s", code); printf("解碼結果如下:n"); decodeHuffman(T, code); printf("%sn", decode); printf("nn"); system("date /T"); system("TIME /T"); system("pause"); exit(0); }
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("nn") datetime = datetime.datetime.now() print(datetime.strftime("%Y-%m-%dn%H:%M:%S")) input("Press Enter to exit…")
以上就是利用Python和C語言分別實現哈夫曼編碼的詳細內容,更多關於Python哈夫曼編碼的資料請關注it145.com其它相關文章!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45