小任的第一篇部落格-哈夫曼樹
哈夫曼樹
主要介紹哈夫曼樹的構建,遍歷(先序遍歷、中序遍歷、後序遍歷)、哈弗曼編碼實現、哈夫曼譯碼實現。
哈夫曼樹功能實現
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
using namespace std;
#define OK 1
#define N 100
typedef struct {
int num;//下標
int weight;
int parent, lchild, rchild;
}HTNode, * HuffmanTree;
typedef char ** HuffmanCode;
//選擇兩個最小的數構建哈夫曼樹
void Select(HuffmanTree& HT, int m, int& s1, int& s2) {
HuffmanTree p, q, pmin1 = NULL, pmin2 = NULL;
p = HT + 1;//p指向下標為1的結點
while (p->parent != 0) p++;
pmin1 = p; pmin2 = p + 1;
while (pmin2->parent != 0) pmin2++;
for (q = pmin2; q <= HT + m; q++) { //遍歷所有結點找到權值最小的兩個結點
if (q->parent == 0 && q->weight < pmin1->weight) {
pmin2 = pmin1; pmin1 = q;
}//if
else if (q->parent == 0 && q->weight < pmin2->weight) {
pmin2 = q;
}
}//for
s1 = pmin1->num;
s2 = pmin2->num;
}
//Visit函式
int PrintHuffman(int weight){
printf("%5d",weight);//輸出權重
return weight;
}
//輸出哈夫曼樹
void PrintHuffmanTree(HuffmanTree& HT, int m) {
int i;
HuffmanTree p = HT + 1;
printf("i\tweight\tparent\tlchild\trchild\n");
for (i = 1; i <= m; i++, p++)
printf("%d\t%d\t%d\t%d\t%d\n", p->num, p->weight, p->parent, p->lchild, p->rchild);
}
//編碼輸出函式
void PrintHuffmanCode(HuffmanTree HT,HuffmanCode HC,int n){
int i;
printf("輸出各權值對應的編碼:\n");
printf("權值\t編碼\n");
for(i=1;i<=n;i++)
printf("%d\t%s\n",HT[i].weight,HC[i]);
}
//構建哈夫曼樹
void HuffmanBuding(HuffmanTree& HT, HuffmanCode& HC, int* w, int n) {
//w存放n個字元的權值(均>0),構造哈夫曼樹HT,並求出n個字元的哈夫曼編碼HC
int s1, s2, f, c, i, m, start;
if (n <= 1) return;
m = 2 * n - 1;
HT = (HuffmanTree)malloc((m + 1) * sizeof(HTNode)); //0號單元未用
for (i = 1; i <= n; ++i, ++w) {
HT[i].num = i;
HT[i].weight = *w;//將下標為i的結點權值放入w中
HT[i].parent = 0; HT[i].lchild = 0; HT[i].rchild = 0;//初始為0
}
for (;i <= m; ++i) { //i=n+1
HT[i].num = i; HT[i].weight = 0; HT[i].parent = 0; HT[i].lchild = 0; HT[i].rchild = 0;
}
printf("輸出HT表的初態:\n");
PrintHuffmanTree(HT, m);
for (i = n + 1; i <= m; ++i) {
//在HT[1..i-1]選擇parent為0且weight最小的兩個結點,其序號分別為s1和s2
Select(HT, i - 1, s1, s2);
HT[s1].parent = i;
HT[s2].parent = i;
HT[i].lchild = s1;
HT[i].rchild = s2;
HT[i].weight = HT[s1].weight + HT[s2].weight;
}
printf("輸出HT表的終態:\n");
PrintHuffmanTree(HT, m);
}
//---從葉子到根逆向求每個字元的哈夫曼編碼---
void HuffmanTreeCoding(HuffmanTree HT,HuffmanCode& HC, int* w, int n){
char* cd;
HC = (HuffmanCode)malloc((n + 1) * sizeof(char*)); //分配n個字元編碼的頭指標向量
cd = (char*)malloc(n * sizeof(char)); //分配求編碼的工作空間
cd[n - 1] = '\0'; //編碼結束符
for (int i = 1; i <= n; ++i) { //逐個字元求哈夫曼編碼
int start = n - 1; //編碼結束符位置
for (int c = i, f = HT[i].parent; f != 0; c = f, f = HT[f].parent) //從葉子到根逆向求編碼,若不是根結點則進行編碼
if (HT[f].lchild == c) cd[--start] = '0';//如果為左孩子,編碼為0
else cd[--start] = '1';//右孩子編碼為1
HC[i] = (char*)malloc((n - start) * sizeof(char)); //為第i個字元編碼分配空間
strcpy(HC[i], &cd[start]); //從cd複製編碼(串)到HC
}
free(cd);
PrintHuffmanCode(HT,HC,n);
}
//對哈夫曼樹進行先序遍歷
void PreOrder(HuffmanTree HT,int x,int(*Visit)(int weight)){
if(x>0){
Visit(HT[x].weight);//輸出下標為x的結點的值
if(HT->lchild) PreOrder(HT,HT[x].lchild,Visit);
if(HT->rchild) PreOrder(HT,HT[x].rchild,Visit);
}}
//哈夫曼樹中序遍歷
void MidOrder(HuffmanTree HT,int x,int(*Visit)(int weight)){
if(x>0){
MidOrder(HT,HT[x].lchild, Visit);//輸出左孩子
Visit(HT[x].weight);
MidOrder(HT,HT[x].rchild, Visit);//輸出右孩子
}}
//後序遞迴遍歷哈夫曼樹
void PostOrder(HuffmanTree HT, int x,int(*Visit)(int weight)) {
if (x>0) {
PostOrder(HT,HT[x].lchild, Visit);
PostOrder(HT,HT[x].rchild, Visit);
Visit(HT[x].weight);
}}
//哈夫曼譯碼
void HuffmanTranslating(HuffmanTree HT,HuffmanCode& HC,int n)
{
int i=0,j,k;
char temp[N];
char a[N];
k = 0;
i = 0;
int*w=NULL;
HuffmanTreeCoding(HT,HC,w,n);
printf("請根據上表,輸入所要譯出的編碼,不得輸入空格\n");
scanf("%s",a);
//遍歷輸入的編碼,從編碼表查詢。
while(a[i]!='\0'){
temp[k] = a[i];//將字元陣列a中的字元附給temp,a繼續接受新的字串
k++;
temp[k] = '\0';
//從編碼表中找出相應的字元
for(j=1;j<=n;j++){
if(!(strcmp(temp,HC[j]))){
k = 0;
printf("%d",HT[j].weight);
break;
}
}
if(k>N)
printf("這串編碼有問題,請重新檢查!!\n"); //判斷k值是否超過陣列長度
i++;
}}
void main()
{
HuffmanTree HT = NULL;
HuffmanCode HC = NULL;
int (*Visit)(int weight);
Visit = PrintHuffman;
int* w, * p;
int enter=1;
int x=0;
int n, i,choice;
while(enter){
printf("\n");
printf("******哈夫曼樹功能選單*******\n");
printf("1、建立一個哈夫曼樹\n");
printf("2、對哈夫曼樹進行遍歷\n");
printf("3、對哈夫曼樹進行編碼\n");
printf("4、對哈夫曼樹進行譯碼\n");
printf("5、退出\n");
printf("請輸入你的選擇:");
scanf("%d",&choice);
switch(choice){
case 1:
printf("請輸入哈夫曼結點個數:");
cin >> n;
x=2*n-1;
printf("請輸入哈夫曼樹各個結點的權值:");
w = (int*)malloc(n * sizeof(int));
for (i = 1, p = w; i <= n; ++i, ++p)
cin >> *p;
HuffmanBuding(HT, HC, w, n);
break;
case 2:
printf("先序遍歷結果為:");
PreOrder(HT,x,Visit);
printf("\n");
printf("中序遍歷結果為:");
MidOrder(HT,x,Visit);
printf("\n");
printf("後序遍歷結果為:");
PostOrder(HT,x,Visit);
break;
case 3:
HuffmanTreeCoding(HT, HC, w, n);
break;
case 4:
HuffmanTranslating(HT,HC,n);
break;
case 5:
enter=0;
exit(0);
default:
printf("輸出有誤,請重新輸入:");
break;
}
system("pause");
}
}
以上為哈夫曼樹功能實現程式碼
輸出
以上為哈夫曼樹各項功能具體實現結果。
感謝閱讀。
相關文章
- 哈夫曼樹
- 哈夫曼樹及其編碼
- Java 樹結構實際應用 二(哈夫曼樹和哈夫曼編碼)Java
- 資料結構與演算法——赫夫曼樹(哈夫曼樹)資料結構演算法
- 哈夫曼樹學習筆記筆記
- 6.6 哈夫曼樹及其應用
- Task A2 哈夫曼樹的應用
- 哈夫曼編碼
- 最優二叉樹(哈夫曼樹)Java實現二叉樹Java
- 資料結構-哈夫曼樹(python實現)資料結構Python
- 重學資料結構之哈夫曼樹資料結構
- 哈夫曼樹及其應用(檔案壓縮)
- 資料結構與演算法:哈夫曼樹資料結構演算法
- 【資料結構X.11】程式碼實現 哈夫曼樹的建立,建立,構造,實現哈夫曼編碼資料結構
- 有趣的赫夫曼樹
- 【資料結構】哈夫曼樹的建立與基礎應用資料結構
- 哈夫曼編碼 —— Lisp 與 Python 實現LispPython
- 高階資料結構---赫(哈)夫曼樹及java程式碼實現資料結構Java
- 一本正經的聊資料結構(6):最優二叉樹 —— 哈夫曼樹資料結構二叉樹
- 曼哈頓距離與切比雪夫距離
- 資料結構之哈弗曼樹資料結構
- 從哈夫曼編碼中我們學到了什麼?
- 曼哈頓距離與切比雪夫距離的互化
- C#資料結構-赫夫曼樹C#資料結構
- 第一篇部落格
- 部落格第一篇
- 我的第一篇部落格
- 哈夫曼實現檔案壓縮解壓縮(c語言)C語言
- 第一篇部落格文章
- 第一篇部落格啊!!!
- 年輕人的第一篇部落格
- 這是我的第一篇部落格
- 我的第一篇部落格出爐~
- 這是自己的第一篇部落格
- 第一篇部落格記錄test
- 小灰灰部落格,社交類新部落格
- 【部落格】替罪羊樹
- 立個flag,部落格任務