Huffman樹與編碼

2022-08-28 19:45:09 字數 3688 閱讀 7875

帶權路徑最小的二叉樹稱為最優二叉樹或huffman(哈夫曼樹)。

b = malloc(n*sizeof(btreenode));

for (i = 0; i < n; i++)

陣列b中的指標可以理解為二叉樹的根指標。

選擇b中根節點權值最小的兩棵二叉樹作為左右子樹組成新的二叉樹,新二叉樹的根節點權值為兩顆二叉樹根節點權值的和。

將新二叉樹新增到b中,並從b中刪除原來的兩棵二叉樹。當b中只有一棵樹時終止迴圈。

int k1 = -1, k2;

for (j = 0; j < n; j++)

//讓k1初始指向森林中第一棵樹,k2指向第二棵

if (b[j] != null)

}for (j = k2; j < n; j++)

//從當前森林中求出最小權值樹和次最小權值樹

else if (b[j]->data < b[k2]->data)

k2 = j;

}}//由最小權值樹和次最小權值樹建立一棵新樹,q指向樹根結點

q = malloc(sizeof(btreenode));

q->data = b[k1]->data + b[k2]->data;

q->left = b[k1];

q->right = b[k2];

b[k1] = q;//將指向新樹的指標賦給b指標陣列中k1位置

b[k2] = null;//k2位置為空

首先給出求帶權路徑的遞迴實現:

double weightpathlength(btreenode* fbt, int len) 

else

}

上述演算法實際上通過雙遞迴遍歷了huffman樹。

改進上述演算法得到求哈夫曼編碼的實現:

static int index = 0;

char *c;

void huffmancoding(file *fp, btreenode* fbt, int len)//len初始值為0

else//訪問到非葉子結點時分別向左右子樹遞迴呼叫,並把分支上的0、1編碼儲存到陣列a

}}

節點的huffman編碼由它在huffman樹中的位置決定。從根節點到任意節點有且僅有一條路徑,且路徑可以唯一確定節點。因此規定從左子結點經過編碼為0,從右子結點經過編碼為1,路徑序列作為編碼。

由huffman樹和huffman編碼的性質可知,huffman編碼是一種不等長編碼。在構造過程中,兩個權值較小的節點生成一棵新的二叉樹,根節點的權值為左右子節點的和,並不實際代表字元。也就是說,較短的編碼不可能是較長編碼的字首。

huffman樹從葉子到根構造,靠近根的字元節點權值與幾個靠近葉子的節點權值和相近,故而靠近根的字元節點權值較高即編碼較短。

解碼過程可以由字串匹配來完成:

//decoding

for(i = 0; code[i]; i++)

}if (t == 1)

}}printf("%s\n",out);

#include#include#includetypedef struct

btreenode;

#define m 32

char coding[m][m];

btreenode* createhuffman(int a, int n)

for (i = 1; i < n; i++)//進行 n-1 次迴圈建立哈夫曼樹

if (b[j] != null)

}for (j = k2; j < n; j++)//從當前森林中求出最小權值樹和次最小

else if (b[j]->data < b[k2]->data)

k2 = j;}}

q = malloc(sizeof(btreenode));

q->data = b[k1]->data + b[k2]->data;

q->left = b[k1];

q->right = b[k2];

b[k1] = q;

b[k2] = null;

}free(b);

return q;

}double weightpathlength(btreenode* fbt, int len)//len初始為0

else

else

}}static int index = 0;

char *c;

void huffmancoding(file *fp, btreenode* fbt, int len)//len初始值為0

else

}} int i;

for (i = 0; str[i];i++);

str[i] = ch;

str[i+1] = '\0';

}int main()

, code[m*m] = , out[m] = ;

btreenode* fbt;

file *fp;

//input

freopen("test.in","r",stdin);

scanf("%d", &n);

arr = (int *)malloc(n * sizeof(int));

c = (char *)malloc(n * sizeof(char));

arr[0] = 186;

c[0] = ' ';

//原諒樓主這裡偷懶,空格字元的輸入有點麻煩所以直接寫入了

for (i = 1; i < n; i++)

//huffman coding

fbt = createhuffman(arr, n);

fp = fopen("code.txt","w");

huffmancoding(fp, fbt, 0);

fflush(fp);

//encoding

fp = fopen("code.txt","r");

for (i = 0; i < n; i++)

fp = fopen("src.in","r");

fscanf(fp, "%s", in);

for (i = 0; in[i]; i++) }}

printf("%s\n",code);

//decoding

for(i = 0; code[i]; i++)

}if (t == 1) }}

printf("%s\n",out);

return 0;

}

測試資料:

test.in:

27

a 4b 13

c 22

d 32

e 103

f 21

g 15

h 47

i 57

j 1

k 5

l 32

m 20

n 57

o 63

p 15

q 1

r 48

s 51

t 80

u 23

v 8

w 18

x 1

y 16

z 1

Huffman樹與Huffman編碼

一.哈夫曼樹概念 路徑 祖先到節點之間的分支構成一條通往節點的路徑 路徑長度 路徑上分支的數目稱為路徑長度 節點的權 給樹中節點所設的物理意義的值 節點帶權路徑長度 從根到該點路徑長度與該點權值的乘機 huffman樹就是所有樹中每點帶權路徑加和最短的樹。二.huffman樹構造步驟 1.根據每個點...

Huffman樹與Huffman編碼

huffman tree簡介 赫夫曼樹 huffman tree 又稱最優二叉樹,是一類帶權路徑長度最短的樹。假設有n個權值,如果構造一棵有n個葉子節點的二叉樹,而這n個葉子節點的權值是,則所構造出的帶權路徑長度最小的二叉樹就被稱為赫夫曼樹。這裡補充下樹的帶權路徑長度的概念。樹的帶權路徑長度指樹中所...

huffman樹和huffman編碼

huffman樹和huffman編碼 include include include include define overflow 1 typedef struct htnode,huffmantree typedef char huffmancode void select huffmantre...