数据结构c语言版 哈夫曼树编码系列

版权声明:想不开 想不开 想不开 https://blog.csdn.net/zuoside__lord/article/details/88807598

花2-3小时写完很久以前就想写的东西反倒没有什么想法。似乎大二初学时候也是能写的,区别就在于 现在要考研逼着自己写,当时没有这么强的驱动力逼着自己写。现在心静一点,心静的话什么都可以看懂,脑袋还是一如既往 沙雕。。

下面是数据结构书上的哈夫曼树 编码 解码。

 /*哈夫曼树 小demo 仅仅测试一句话英文, 压缩前 压缩后 还原。
 */
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
typedef struct huff
{
	int parent,lc,rc;
	int wight;
	char s[100];
	int len;
	char code;
}huff,*huffman;
typedef struct wordnum
{
	int num;
	char c;
	int tag;
}wordnum,*word;
void select1(huff *h,int n,int *s1,int *s2);
void huff_code(huff *h,int n)//
{
    int i,j,c,f;
    for(i=0;i<n;i++)
    {
	char t[n];
	int l=0;
	c=i;
	f=h[i].parent;
	while(f!=-1)
	{
		if(h[f].lc==c) 
			t[l]='0';
		else
			t[l]='1';
		c=f;f=h[f].parent;
		l++;
	}
        t[l]='\0';
	for(j=l-1;j>=0;j--)
	{
		h[i].s[h[i].len]=t[j];
		h[i].len++;
	}
	h[i].s[h[i].len]='\0';
    }
    
}


void huff_create(huff *h,int n,wordnum *w)//有n个带权节点需要构成一棵哈夫曼树
{
	int m;
	int x[100];
	int s1,s2;
	m=2*n-1;
	int i,j,t;
	for(i=0;i<m;i++)
	{
		h[i].parent=-1;
		h[i].lc=0;
		h[i].rc=0;
		h[i].len=0;
	}
	for(i=0;i<n;i++)
	{
		h[i].code=w[i].c;
		h[i].wight=w[i].num;
	}
	for(i=n;i<m;++i)
	{
		t=i-1;
		select1(h,t,&s1,&s2);
   	        h[s1].parent=i;
                h[s2].parent=i;

		h[i].wight=h[s1].wight+h[s2].wight;
		h[i].lc=s1;
		h[i].rc=s2;
	}
}
void select1(huff *h,int n,int *s1,int *s2)//
{
	int x=100;
        int min=1000;
	int i;
	int a,b;
        for(i=0;i<=n;i++)
        {
		if(h[i].parent!=-1) continue;
		if(h[i].parent==-1)
		{
                if(h[i].wight<x)
                {
                        min=x;
                        x=h[i].wight;
                }
                else
                {
                        if(h[i].wight<min)
			{
			    	min=h[i].wight;
			}
                }
		}
        }
	for(i=0;i<=n;i++)
	{
		if(h[i].wight==x&&h[i].parent==-1)
		{
			a=i;
			break;
		}
	}
	for(i=0;i<=n;i++)
		if(h[i].wight==min&&h[i].parent==-1&&i!=a)
			b=i;
	
	*s1=a;
	*s2=b;
}
void press(char *origin,huff *h,char *new,int n)//origin为原来的未压缩的,new为压缩的
{
	int i,j;
	int start,end;
	start=0;
	for(i=0;i<strlen(origin);i++)
	{
		for(j=0;j<n;j++)
		{
			if(h[j].code==origin[i])
			{
				int len=strlen(h[j].s);
				memcpy(new+start,h[j].s,len);
				start=start+len;
			}
		}
	}
	new[start]='\0';

}
void unpress(char *new,huff *h,int n,char *o)//
{
	int i,j,f,p,t;
	char x[n];
	int c;
	int m=2*n-1;
	p=0;
	int length=0;
	c=m-1;
	for(i=0;i<strlen(new);i++)
	{
		  t=new[i];
		  if(t=='0')
		  {
		     c=h[c].lc;
		  }
		  else
		  {
			c=h[c].rc;
                  }
		  if(h[c].lc==0&&h[c].rc==0)
		  {
				  o[p++]=h[c].code;
				  c=m-1;
		  }
	}
	o[p]='\0';
	
}
void print(huff *h,int n)
{
	int i;
	for(i=0;i<n;i++)
	{
		printf("id=%d wight=%d c:%c code:%s\n",i,h[i].wight,h[i].code,h[i].s);
	}
}
int count(wordnum *w,char *s,char *old)
{
	int i,j,t;
	t=0;
	j=0;
	for(i=0;i<strlen(s);i++)
	{
		w[i].tag=0;
		w[i].num=1;
		old[i]=s[i];
	}
	old[i]='\0';
	for(i=0;i<strlen(s);i++)
	{
	        if(w[i].tag==0&&s[i]!='0')
		{
			t++;
		for(j=i+1;j<strlen(s);j++)
		{
			if(s[i]==s[j]&&w[i].tag==0)
			{
				w[i].c=s[i];
				w[i].num++;
				s[j]='0';
			}
		}
		w[i].tag=1;
		}
	}
	return t;
}
		
int main()
{
	char sentence[100];
	printf("测试数据:");
	scanf("%s",sentence);
	char old[100];
	char new[100];
	int length,l;
	length=strlen(sentence);
	wordnum w[length];
	l=count(w,sentence,old);
	huff h[l];
	huff_create(h,l,w);
	huff_code(h,l);
	press(old,h,new,l);
	printf("压缩编码:%s\n",new);
	unpress(new,h,l,old);
	printf("解压后原数据:%s\n",old);
}

这个代码很多地方都写得很沙雕 多余 垃圾,但是基本该完成的它还是完成了。不过这个压缩算法似乎有弊端 你们自己去研究。

等我做完项目 再欢迎一起在gay li gay qi github上玩。

猜你喜欢

转载自blog.csdn.net/zuoside__lord/article/details/88807598