头文件:Tree.h
//树的双亲表示法及并查集
typedef struct PTNode
{
TElemType data;
int parent;
}PTNode;
typedef struct
{
PTNode nodes[MAX_TREE_SIZE];
int root, amount;
}PTree;
typedef PTree MFSet;
int Find_MFSet(MFSet S, int i)
{
if (i<1 || i>S.amount) return -1;
int j = i;
while (S.nodes[j].parent > 0)
j = S.nodes[j].parent;
return j;
}
Status Merge_MFSet(MFSet* S, int i, int j)
{
if (i<1 || j<1 || i>S->amount || j>S->amount)
return ERROR;
S->nodes[i].parent = j;
return OK;
}
Status Mix_MFSet(MFSet* S, int i, int j)
{
if (i<1 || i>S->amount || j<1 || j>S->amount)
return ERROR;
if (S->nodes[i].parent < S->nodes[j].parent)
{
S->nodes[i].parent += S->nodes[j].parent;
S->nodes[j].parent = i;
}
else
{
S->nodes[j].parent += S->nodes[i].parent;
S->nodes[i].parent = j;
}
return OK;
}
int Fix_MFSet(MFSet* S, int i) //确定序号为i的节点所在子集,并将路径上的所有节点都放到第二梯队
{
int j = i;
while (S->nodes[j].parent > 0)
j = S->nodes[j].parent;
int k = i;
while (S->nodes[k].parent > 0)
{
int t = S->nodes[k].parent;
S->nodes[k].parent = j;
k = t;
}
return j;
}
//孩子表示法(用链表方式将根的孩子节点全部连接在链表上)
typedef struct CTNode
{
int child;
struct CTNode* next;
}*Ptr;
typedef struct
{
TElemType data;
Ptr firstchild;
}CTBox;
typedef struct
{
CTBox node[MAX_TREE_SIZE];
int root, amount;
}CTree;
//孩子兄弟表示法
typedef struct CSNode
{
TElemType data;
struct CSNode* firstchild, * nextsibling;
}CSNode, * CSTree;
//赫夫曼树
typedef struct
{
unsigned int weight;
unsigned int parent, lchild, rchild;
}HTNode, * HuffmanTree;
typedef char** HuffmanCode;
void Select(HuffmanTree T, int bound, int* min1, int* min2)
{
int p = 0, q = 0;
for (int i = 1; i <= bound && (!p || !q); i++)
{
if (T[i].parent == 0)
{
if (!p)
p = i;
else
q = i;
}
}
for (int i = 2; i <= bound; i++)
if (T[i].parent == 0)
{
if (T[i].weight < T[p].weight)
{
q = p;
p = i;
}
else
{
if (T[i].weight < T[q].weight && i != p)
q = i;
}
}
*min1 = p;
*min2 = q;
}
Status HuffmanCoding(HuffmanTree T, HuffmanCode HC, int* w, int n)
{
if (n <= 1)
return ERROR;
int m = 2 * n - 1;
for (int i = 1; i <= m; i++)
{
T[i].lchild = 0;
T[i].rchild = 0;
T[i].parent = 0;
if (i <= n)
T[i].weight = w[i];
else
T[i].weight = 0;
}
for (int i = n + 1; i <= m; i++)
{
int min1, min2;
Select(T, i - 1, &min1, &min2);
T[min1].parent = i;
T[min2].parent = i;
T[i].lchild = min1;
T[i].rchild = min2;
T[i].weight = T[min1].weight + T[min2].weight;
}
/*char* code = (char*)malloc(sizeof(char) * n);
if (!code) exit(OVERFLOW);
code[n - 1] = '\0';
int start;
for (int i = 1; i <= n; i++)
{
start = n - 1;
int p = T[i].parent, q = i;
while (p)
{
if (T[p].lchild == q)
code[--start] = '0';
else
code[--start] = '1';
q = p;
p = T[p].parent;
}
HC[i] = (char*)malloc(sizeof(char) * (n - start));
if (!HC[i]) exit(OVERFLOW);
strcpy(HC[i], &(code[start]));
}
free(code);*/
//赫夫曼树的另一种写法,自上而下由根结点出发
int p = m;
for (int i = 1; i <= m; i++)
T[i].weight = 0;
int cdlen = 0;
int count = 1;
char* buf;
buf = (char*)malloc(sizeof(char) * n);
if (!buf) exit(OVERFLOW);
while (p)
{
if (T[p].weight == 0)
{
T[p].weight = 1;
if (T[p].lchild != 0)
{
p = T[p].lchild;
buf[cdlen++] = '0';
}
else
{
HC[count] = (char*)malloc(sizeof(char) * (cdlen + 1));
if (!HC[count]) exit(OVERFLOW);
buf[cdlen] = '\0';
strcpy(HC[count], buf);
count++;
}
}
else
{
if (T[p].weight == 1)
{
T[p].weight = 2;
if (T[p].rchild != 0)
{
p = T[p].rchild;
buf[cdlen++] = '1';
}
}
else
{
p = T[p].parent;
cdlen--;
}
}
}
return OK;
}
c文件:(赫夫曼树)
#include "Tree.h"
//赫夫曼编码主函数
int main()
{
HuffmanCode T;
HuffmanCode HC;
int n = 26;
HC = (char**)malloc(sizeof(char*) * (n + 1));
if (!HC) exit(OVERFLOW);
T = (HuffmanTree)malloc(sizeof(HTNode) * (2 * n));
if (!T) exit(OVERFLOW);
int w[27] = { 0,819,147,383,391,1225,226,171,457,710,14,41,377,334,706,726,289,9,685,636,941,258,109,159,21,158,8};
char c[26] = { 'a','b','c','d','e','f','g','h','i','g','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'};
HuffmanCoding(T, HC, w, n);
for (int i = 1; i <= n; i++)
{
printf("%c字符的编码为:", c[i - 1]);
puts(HC[i]);
printf("\n");
}
return OK;
}
结果:(按照单词字母使用频率编码)
a字符的编码为:0000000
b字符的编码为:00000010
c字符的编码为:000000110
d字符的编码为:0000001110
e字符的编码为:0000001111
f字符的编码为:000001
g字符的编码为:00001
h字符的编码为:0001
i字符的编码为:001
g字符的编码为:01000
k字符的编码为:01001
l字符的编码为:010100
m字符的编码为:010101
n字符的编码为:010110
o字符的编码为:010111
p字符的编码为:011
q字符的编码为:1000
r字符的编码为:1001
s字符的编码为:1010
t字符的编码为:1011
u字符的编码为:11000
v字符的编码为:11001
w字符的编码为:1101
x字符的编码为:11100
y字符的编码为:11101
z字符的编码为:1111