树与森林数据结构及赫夫曼树

 头文件: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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值