大一写的哈夫曼编码程序(今天贴上)

/*
霍夫曼编码
哈夫曼树(Huffman Tree),又叫最优二叉树,指的是对于一组具有确定权值的叶子结点的具有最小带权路径长度的二叉树
1.数据移动时无符号不同于有符号,右移要默认为0
2.文件操作以字节为最小单位。凑足写入,最后多一个字节写上次剩余多少
3.区分叶子节点与内部节点,8个字符的最长路径为7

无符号类型的应用,位操作在有符号时候会带符号操作,当系统使用文本方式打开文件后,会对回车做相应处理。文件读取不正确
移位操作时候注意左右不同。当最后一个单元不能完全保存时,最后用一个来存储最后一次操作的位数
	k<<=32-count;移位至前面,自底向上寻找编码,但从上到下使用

*/#include<stdio.h>
#include<stdlib.h>
#include<conio.h>
#include<string.h>
#define N 511
#define M 256
typedef struct HTree
{
	unsigned char ch;
	int parent,lchild,rchild;
	unsigned int code;
	int codenum;
	double weight;
}Tree;
Tree tree[N]={0};
void encode();
void hufftree();
void getcode();
void crackcode();
void printcode();
void translatecode(unsigned char *rdtemp,int filesize);
int main()
{
	char ch[3];
	while(1)
	{
		system("cls");
		printf("             -----------------------哈夫曼编码解码---------------------\n\n");
		printf(" 						BY:许少岩\n\n\n\n");
		printf(" 				1.哈夫曼编码\n");
		printf(" 				2.哈夫曼解码\n");
		printf(" 				3.打印各个字符的哈夫曼编码\n				0.EXIT\n\n");
		printf("注:编码文件为test.txt,解码文件名为Htest.txt与源程序放在同一目录\n\n\n			");
		gets(ch);
		switch(ch[0])
		{
		case '0': return 0;
		case '1':encode();break;
		case '2':crackcode();break;
		case '3':printcode();break;
		}
	}

	return 0;
}
void encode()
{
	FILE *fp;
	if((fp=fopen("test.txt","rb"))==NULL)
		exit(0);
	int All_char[M]={0};

	int i;
	unsigned char rdtemp[100000];
	i=sizeof(unsigned char);
	long filesize;
	fseek(fp,0,2);
	filesize=ftell(fp);
	rewind(fp);
	fread(rdtemp,filesize,1,fp);
	fclose(fp);							//读入文本
	i=0;
	while(i<filesize)
		All_char[rdtemp[i++]]++;
	for(i=0;i<M;i++)
	{
		tree[i].ch=i;
		tree[i].parent=-1;
		tree[i].weight=All_char[i]/(double)filesize;
	}
	for(i=M;i<N;i++)
		tree[i].parent=-1;												//统计字符
	hufftree();															//create哈夫曼编码
	getcode();
																			//译码写入
	translatecode(rdtemp,filesize);
	printf("\n\n	mission successful! press any key to back...\n");
	_getch();

}
void hufftree()
{
	int i;
	int num1,num2;
	int count;
	double min1,min2;
	int arc;
	arc=M;
	count=0;
	while(arc<N)
	{

		for(i=0,min1=min2=1.0;i<arc;i++)
		{
			if(tree[i].parent != -1)
				continue;
			if(tree[i].weight<min2)
			{
				if(tree[i].weight<min1)
				{
					num2=num1;
					num1=i;
					min2=min1;
					min1=tree[i].weight;
				}
				else
				{
					num2=i;
					min2=tree[i].weight;
				}
			}
		}
		tree[arc].lchild=num1;
		tree[arc].rchild=num2;
		tree[arc].weight=min1+min2;
		tree[num1].parent=arc;
		tree[num2].parent=arc;
		arc++;
	}

}
void getcode()
{
	int i,j;
	int codenum;
	int chcount=0;
	while(chcount<M)
	{
		codenum=0;
		i=chcount;
		while(tree[i].parent != -1)
		{
			tree[chcount].code>>=1;
			codenum++;
			j=tree[i].parent;
			if(tree[j].rchild == i)
				tree[chcount].code |=0x80000000;
			i=j;
		}
		tree[chcount].codenum=codenum;
		chcount++;
	}
/*
	for(i=j=0;i<M;i++)
	{
		j=tree[i].codenum>j?tree[i].codenum:j;
		//printf("%c %d\n",tree[i].ch,tree[i].code);

	}*/

}
void translatecode(unsigned char *rdtemp,int filesize)
{
	FILE *fp;
	int i,j,count;
	unsigned int k,l;
	if((fp=fopen("Htest.txt","wb"))==NULL)
		exit(0);
	fwrite(tree,sizeof(Tree),N,fp);
	for(i=k=count=0;i<filesize;i++)
	{
		l=tree[rdtemp[i]].code;
		for(j=0;j<tree[rdtemp[i]].codenum;j++,count++)
		{
			if(count == 32)
			{
				fwrite(&k,sizeof(int),1,fp);
				count=k=0;
			}
			k<<=1;
			if((l&0x80000000) == 0x80000000)
				k|=1;
			l<<=1;
		}
	}
	k<<=32-count;
	if(count)
		fwrite(&k,sizeof(int),1,fp);
	fwrite(&count,sizeof(int),1,fp);
	fclose(fp);
}
void crackcode()
{
	int i,j,k;
	unsigned int oparrey[500]={0};
	FILE *fp;
	if((fp=fopen("Htest.txt","r+b"))==NULL)
		exit(0);
	ftell(fp);
	fread(tree,sizeof(Tree),N,fp);
	long filesize1,filesize2,filesize;
	filesize1=ftell(fp);
	fseek(fp,0,2);
	filesize2=ftell(fp);
	filesize=filesize2-filesize1;
	filesize/=4;
	fseek(fp,filesize1,0);
	fread(oparrey,sizeof(int),filesize,fp);
	fclose(fp);
	for(i=0,k=N-1;i<filesize-2;i++)
	{
		for(j=0;j<32;j++)
		{
			if((oparrey[i]&0x80000000) == 0x80000000)
				k=tree[k].rchild;
			else
				k=tree[k].lchild;
			if(tree[k].ch)
			{
				putchar(tree[k].ch);
				k=N-1;
			}//字符处理
			oparrey[i]<<=1;
		}
	}
	for(j=0;j<(signed)oparrey[filesize-1];j++)
		{
			if((oparrey[i]&0x80000000) == 0x80000000)
				k=tree[k].rchild;
			else
				k=tree[k].lchild;
			if(tree[k].ch)
			{
				putchar(tree[k].ch);
				k=N-1;
			}//字符处理
			oparrey[i]<<=1;
		}
		printf("\n\n	mission successful! press any key to back...\n");
	_getch();
}
void printcode()
{
	unsigned int k;
	for(int i=0;i<M;i++)
		{
			k=tree[i].code;
			printf("%c\t",tree[i].ch);
			for(int j=0;j<tree[i].codenum;j++)
			{
				if((k&0x80000000) == 0x80000000)
					putchar('1');
				else
					putchar('0');
				k<<=1;
			}
			putchar('\n');
		}
		printf("\n\n	mission successful! press any key to back...\n");
	_getch();
}
时间: 2024-10-17 02:17:58

大一写的哈夫曼编码程序(今天贴上)的相关文章

自写项目——哈夫曼编译码及客户端服务端交互实现

1.项目要求 哈夫曼编译码 题目要求:编写一个用哈夫曼实现的编码压缩器,语言不限! 实现英文字符编译码的功能:实现译码的压缩解压功能:要有较美观的图形用户界面:从客户端发送一段字符给服务器端,服务器端能成功的返回这段字符经过哈夫曼编译码之后的结果! 编写步骤: ①编写较美观的图形用户界面: ②得到客户端所发送的字符信息,并进行统计,每个字符 的频度作为哈夫曼树叶子结点的权值,并构建哈夫曼树: ③进行哈夫曼树的编码和译码: ④自行选取5~7个二进制码来进行压缩: ⑤将压缩好的字符发送到服务器端,并

哈夫曼编码(Huffman coding)的那些事,(编码技术介绍和程序实现)

前言 哈夫曼编码(Huffman coding)是一种可变长的前缀码.哈夫曼编码使用的算法是David A. Huffman还是在MIT的学生时提出的,并且在1952年发表了名为<A Method for the Construction of Minimum-Redundancy Codes>的文章.编码这种编码的过程叫做哈夫曼编码,它是一种普遍的熵编码技术,包括用于无损数据压缩领域.由于哈夫曼编码的运用广泛,本文将简要介绍: 哈夫曼编码的编码(不包含解码)原理 代码(java)实现过程 一

基于哈夫曼编码的文件压缩(c++版)

本博客由Rcchio原创 我了解到很多压缩文件的程序是基于哈夫曼编码来实现的,所以产生了自己用哈夫曼编码写一个压缩软件的想法,经过查阅资料和自己的思考,我用c++语言写出了该程序,并通过这篇文章来记录一下自己写该程序学到的东西.因为本人写的程序在压缩率上,还有提升的空间,所以本文将不定期更新,但程序整体的思路不会有较大的改动. 一.基于哈夫曼编码可实现压缩文件的原理分析 在计算机中,数据的存储都是二进制的,并且以字节作为基本的存储单位,像英文字母在文本中占一个字节,汉字占两个字节,我们把这种每一

哈夫曼树的建立

闲暇的夜晚, 写个哈夫曼树练练笔. #include<iostream>#include<cstring>#include<cstdlib>#include<algorithm>typedef struct{ char data; int w,parent, lchild, rchild; int use;}HFNode,*HuffmanTree;char N[100];    //用以保存结点的dataint w[100];     //权值typedef

哈夫曼树学习笔记

既然我们要学习赫夫曼树,那么我们首先就要知道什么叫赫夫曼树. 那么什么叫赫夫曼树呢? 一.什么叫赫夫曼树? 书上说:“赫夫曼(Huffman)树又称最优树,是一类带权路径长度最短的树,但是我们仅学习最优二叉树.” 看到这个还是不明白什么意思,因此在学习之前我们要结合这个图了解几个基本概念. 路    径:由一结点到另一结点间的分支所构成.如:a->b a->b->e 路径长度:路径上的分支数目,如:a→e的路径长度=2  a->c的路径长度=1 树的路径长度:从树根到每一结点的路径

赫夫曼树编码的表示与实现--自己写数据结构

头文件huffman.h #ifndef _HUFFMAN_H_ #define _HUFFMAN_H_ #define MAX_WEIGHT 10000 typedef struct _HTNode { int weight; int parent,lchild,rchild; char data; }HTNode,*pHTNode; typedef char** huffmancode; void select_min_weight(HTNode* btree,int mn,int* s1,

一步一步写算法(之哈夫曼树 下)

原文:一步一步写算法(之哈夫曼树 下) [ 声明:版权所有,欢迎转载,请勿用于商业用途.  联系信箱:feixiaoxing @163.com] 前面说到了哈夫曼树的创建,那下面一个重要的环节就是哈夫曼树的排序问题.但是由于排序的内容是数据结构,因此形式上说,我们需要采用通用数据排序算法,这在我之前的博客里面已经涉及到了(通用算法设计).所以,我们所要做的就是编写compare和swap两个函数.通用冒泡代码如下所示, void bubble_sort(void* array[], int le

一步一步写算法(之哈夫曼树 上)

原文:一步一步写算法(之哈夫曼树 上) [ 声明:版权所有,欢迎转载,请勿用于商业用途.  联系信箱:feixiaoxing @163.com] 在数据传输的过程当中,我们总是希望用尽可能少的带宽传输更多的数据,哈夫曼就是其中的一种较少带宽传输的方法.哈夫曼的基本思想不复杂,那就是对于出现频率高的数据用短字节表示,对于频率比较低得数据用长字节表示. 比如说,现在有4个数据需要传输,分别为A.B.C.D,所以一般来说,如果此时没有考虑四个数据出现的概率,那么我们完全可以这么分配,平均长度为2, /

看数据结构写代码(32) 赫夫曼树编码以及译码

杂谈:最近有点慵懒,不好不好.好几天都没写代码,原本准备上星期完结 树 这一章节的.现在 又耽误了.哎.要抓紧时间啊. 下面直接上代码: 可以到我的网盘下载源代码,或者 直接拷贝下面的源代码 运行 网盘地址:点击打开链接 // HuffmanTree.cpp : 定义控制台应用程序的入口点. //哈弗曼编码,译码 #include "stdafx.h" #include <stdlib.h> #include <cstring> enum E_State { E