帶權路徑最小的二叉樹稱為最優二叉樹或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...