C语言:哈夫曼树的编码与译码

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<conio.h>

#define N 100

typedef struct
{
	int weight;
	int parent, lchild, rchild;
}hafuman;

typedef struct
{
	char data[N]; //字符数据

	char copy[N][10*N];//编码
}bianma;

void display();
int input(int w[], bianma *bm);
void creat_hafuman(hafuman ht[], int w[], int n);
void select(hafuman ht[], int m, int *s1,  int *s2);
void encoding(hafuman ht[], bianma *bm, int n);
void coding(bianma *bm, int n);//译码
void coding_2(hafuman ht[], bianma *bm, int n);//译码
void output(bianma *bm, int n);
int i, j, k;

void display()
{
	printf("\n\n\n");
	printf("\t\t\t1.输出编码\n\n");
	printf("\t\t\t2.进行译码\n\n");
	printf("\t\t\t3.退出\n\n");
	printf("\t\t请选择(1~~3):  ");
}

int input(int w[], bianma *bm)
{
	int n=0;

	printf("\n请输入要进行编码的文章或句子(#结束)\n");

	while(1)
	{
		bm->data[n]=getchar();

		if(bm->data[n]=='#')
			break;
		n++;
	}

	for(i=0; i<n; i++)
	{
		w[i]=1;

		for(j=i+1; j<n; )
		{
			if( bm->data[i] == bm->data[j] )
			{
				w[i]++;

				for(k=j; k<n; k++)
				{
					bm->data[k]=bm->data[k+1];
				}
				n--; //覆盖完之后n--;
			}
			else
				j++;
		}

	}

	printf("\n\n");
	printf("不同的字符\n");
	for(i=0; i<n; i++)
	{
		printf("%c", bm->data[i]);
	}

	return n;
}

void creat_hafuman(hafuman ht[], int w[], int n)
{
	int s1, s2;
	int t;

	for(t=1; t<=n; t++)
	{
		ht[t].weight=w[t-1];
		ht[t].parent=0;
		ht[t].lchild=0;
		ht[t].rchild=0;
	}

	for(t=n+1; t<=2*n-1; t++)
	{
		ht[t].weight=0;
		ht[t].parent=0;
		ht[t].lchild=0;
		ht[t].rchild=0;
	}

	for(t=n+1; t<=2*n-1; t++)
	{
		select(ht, t-1, &s1, &s2);//前i-1中选双亲为0, 权值最小

		ht[t].weight=ht[s1].weight + ht[s2].weight;

		ht[t].lchild=s1, ht[t].rchild=s2;

		ht[s1].parent=t, ht[s2].parent=t;

	}
}

void select(hafuman ht[], int m, int *s1,  int *s2)
{
	int min1, min2, a, b;
	i=1;
	while( ht[i].parent != 0)
	{
		i++;
	}
	min1=ht[i].weight;
	a=i;

	for(j=i+1; j<=m; j++)
	{
		if(min1 > ht[j].weight && ht[j].parent==0)
		{
			min1=ht[j].weight;
			a=j;
		}

	}

	i=1;
	while( ht[i].parent != 0 || a==i )
	{
			i++;
	}

	min2=ht[i].weight;
	b=i;

	for(j=i+1; j<=m; j++)
	{
		if(j==a)
			continue;

		if(min2 > ht[j].weight && ht[j].parent==0)
		{
			min2=ht[j].weight;
			b=j;
		}
	}
	*s1=a; *s2=b;

}

void encoding(hafuman ht[], bianma *bm, int n)//编码, *copy[]为复制编码
{
	int start, c, p;
	char *ch;
	ch=(char *)malloc( n*sizeof(char) );
	ch[n-1]='\0';

	for(i=1; i<=n; i++)//n个叶子节点
	{
		start=n-1;
	    c=i, p=ht[i].parent; //p为parent, c为child

		while(p!=0)
		{
			start--;
			if(ht[p].lchild==c)
				ch[start]='0';
			else
				ch[start]='1';

			c=p; p=ht[p].parent;	//printf("\n123\n");
		}

	    strcpy( bm->copy[i-1], &ch[start] );
		//printf("\n%s\n", bm->copy[i-1]);
	}
	free(ch);

}

void coding_2(hafuman ht[], bianma *bm, int n)//译码
{
	char s[10*N];
	int p;

	printf("\n请输入要译码的字符\n");
	fflush(stdin);
	gets(s);

	printf("\n译码\n\n");
	p=2*n-1;
	for(i=0; s[i] != '\0'; i++)
	{	

		if(s[i]=='0')
			p=ht[p].lchild;

		else
			if(s[i]=='1')
			p=ht[p].rchild;	

		if(ht[p].lchild == 0 && ht[p].rchild == 0)
		{
				printf("%c", bm->data[p-1]);//p: 1~~2*n-1, bbm->data[0~~n-1]
				p=2*n-1;
				continue;
		}

	}
	puts("\n\n");
}

void output(bianma *bm, int n)
{
	printf("\n");
	for(i=0; i<n; i++)
	{
		printf("%c\t", bm->data[i] );

		printf("%s\n", bm->copy[i]);
	}
}

void main()
{
	hafuman ht[N];
	bianma *bm;
	int w[N];
	int n, m;

	bm=(bianma *)malloc( sizeof(bianma) );
	n=input(w, bm);

	printf("\n\n不同字符总数: %d\n\n", n);

    creat_hafuman(ht, w, n); 

	encoding(ht, bm, n); 

	getch();
    system("cls");

loop:	display();
	scanf("%d",  &m);
	switch(m)
	{
	case 1:
		output(bm, n);
		printf("\n\n请按任意键继续");
		getch();
		system("cls");
		goto loop;
		break;
	case 2:
		//coding(bm, n);//译码
		coding_2(ht, bm, n);//译码
		printf("\n\n请按任意键继续");
		getch();
		system("cls");
		goto loop;
		break;
	case 3:
		break;
	default:
		system("cls");
		goto loop;
	}
}

时间: 2024-10-29 19:05:51

C语言:哈夫曼树的编码与译码的相关文章

【数据结构】哈夫曼树实现编码译码

根据一段字符串中字符的个数 作为该字符的权值生成哈夫曼树. 然后根据生成的哈夫曼编码,对任意字符串实现编码,对任意二进制串实现译码. 程序运行结果: 1.程序主界面: 2.根据字符串 创建哈夫曼树及编码: 3.生成的编码表如下: 4.根据生成的哈夫曼编码对字符串编码: 5.生成的编码保存在文件中: 6.对二进制串译码: 结果: 代码: 哈夫曼树的生成和编码的常见,以及编码和译码函数 //_HuffmanTree_H #ifndef _HuffmanTree_H #define _HuffmanT

数据结构之---C语言实现哈夫曼树和编码

//哈夫曼树 //杨鑫 #include <stdio.h> #include <stdlib.h> typedef int ElemType; struct BTreeNode { ElemType data; struct BTreeNode* left; struct BTreeNode* right; }; //遍历哈夫曼树 void PrintBTree_int(struct BTreeNode* BT) { if (BT != NULL) { printf("

哈夫曼树及编码

介绍哈夫曼编码之前先介绍一下哈弗曼树: 哈夫曼树:哈夫曼树又称最优二叉树,是一种带权路径长度最短的二叉树.所谓树的带权路径长度,就是树中所有的叶结点的权值乘上其到根结点的路径长度(若根结点为0层,叶结点到根结点的路径长度 为叶结点的层数).树的带权路径长度记为WPL= (W1*L1+W2*L2+W3*L3+...+Wn*Ln) ,N个权值Wi(i=1,2,...n)构成一棵有N个叶结点的二叉树,相应的叶结点的路径长度为Li(i=1,2,...n).可以证明哈夫曼树的WPL是最小的. 哈夫曼树的构

哈夫曼树与编码译码实现

一.哈弗曼树的基本概念. 哈夫曼树,又称最优树,是一类带权路径长度最短的树.下面有几个概念: (1)路径. 树中一个结点到另一个结点之间的分支构成这两个结点之间的路径. (2)路径长度. 路径上的分枝数目. (3)树的路径长度. 从树根到每一个结点的路径长度之和. (4)结点的带权路径长度. 从该结点到树根之间的路径长度与结点上权的乘积. (5)树的带权路径长度. 树中所有叶子节点的带权路径长度之和.通常记作: 带权路径长度WPL最小的二叉树叫做最优二叉树或哈夫曼树. 二.构造哈夫曼树. 采用哈

哈夫曼树的编码实验

Java哈夫曼编码实验--哈夫曼树的建立,编码与解码 建树,造树,编码,解码 一.哈夫曼树编码介绍 1.哈夫曼树: (1)定义:假设有n个权值{w1, w2, ..., wn},试构造一棵含有n个叶子结点的二叉树,每个叶子节点带权威wi,则其中带权路径长度WPL最小的二叉树叫做最优二叉树或者哈夫曼树. (2)特点:哈夫曼树中没有度为1的结点,故由n0 = n2+1以及m= n0+n1+n2,n1=0可推出m=2*n0-1,即一棵有n个叶子节点的哈夫曼树共有2n-1个节点. 2.哈夫曼编码步骤:

5678: 数据结构实验:哈夫曼树和编码

描述 当用 n 个结点(都做叶子结点且都有各自的权值)试图构建一棵树时,如果构建的这棵树的带权路径长度最小,称这棵树为“最优二叉树”,有时也叫“赫夫曼树”或者“哈夫曼树”. 现给定若干权值,请构建一棵哈夫曼树,并输出各个权值对应的哈夫曼编码长度. 哈夫曼树中的结点定义如下: //哈夫曼树结点结构 typedef struct { int weight;//结点权重 int parent, left, right;//父结点.左孩子.右孩子在数组中的位置下标 }HTNode, *HuffmanTr

哈夫曼树的编码可视化演示

哈夫曼树及哈夫曼编码

一,引言 如上图,是一个判断体重在什么范围内的判定树,例如,学校体检的时候,我们反复用这个算法,当你输入一个体重:200斤,然后程序就开始反复判断了,经过三次判断,它发现你过重,然后重启系统了,又来一个人,还是200斤,三次判断之后,又系统重启了-后面的200多个200多斤的盘子判断完了之后,来了个120的,终于是个比较正常的体重了,但是系统一判断完,系统还是重启,反复检查之后,发现你那台8086时代的电脑终于撑不住了~ 于是你改了下算法,换了一棵判定树,这次,先判断这个人是不是个200多斤的胖

数据结构--树(下)--哈夫曼树与哈夫曼编码

什么是哈夫曼树? 编码这个问题,二进制的形式,等长码.出现频率高的 不登场编码,效率能提高. 将百分制的考试成绩转换成五分制的成绩. 判定树 同一件事情,我们用了不通的判定树,就得出了不同的效率 so........如何根据结点不通的查找频率构造更有效地搜索树?这就是哈夫曼舒要解决的问题. 哈夫曼树的定义: 带权路径长度(WPL):设二叉树有n个叶子节点,每个叶子节点带有权重wk,从根节点到叶子节点的长度为lk,则每个叶子节点的带权路径长度之和就是 哈夫曼树又叫最优二叉树. 哈夫曼树就是让WPL