⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 huffman.c

📁 一个哈夫曼编码,我是新手,随便做个玩,请大家别笑话我.
💻 C
字号:
/*
 * Definition for Huffman coding 
 *
 * vim: ts=4 sw=4 cindent nowrap
 */
#include <stdlib.h>
#include <stdio.h>
#include "bitio.h"

typedef struct{
	unsigned long count;
	int parent, lchild, rchild;
} HNODE;
HNODE hTree[512];
typedef struct{
	unsigned long code;
	int codelength;
} HCODE;
HCODE hCode[256];
unsigned long counts[256];

void BuildCounts( FILE *fp);
int BuildTree( void);
void BuildCode( void);
void HuffmanEncode( FILE *fp, BITFILE *bf);
void HuffmanDecode( BITFILE *bf, FILE *fp);

void BuildCounts( FILE *fp){
	int c;
	for( c=0; c<256; c++) counts[c] = 0;
	while( EOF!=(c=fgetc(fp))) counts[c]++;
}

int BuildTree( void){
	int i;
	int min1, min2, nextfree;
	for( i=0; i<256; i++){
		hTree[i].count = counts[i];
		hTree[i].parent = 0;
		hTree[i].lchild = 0;
		hTree[i].rchild = 0;
	}
	for( i=256; i<512; i++){
		hTree[i].count = 0;
		hTree[i].parent = 0;
		hTree[i].lchild = 0;
		hTree[i].rchild = 0;
	}
	hTree[511].count = 0xFFFFFFFFL;
	nextfree = 256;
	for( ;;nextfree++){
		min1=min2=511;
		for( i=0; i<nextfree; i++){
			if( 0<hTree[i].count && 0==hTree[i].parent){ // free node
				// update min1,min2, for min1, min2 and i
				if( hTree[i].count < hTree[min1].count){
					min2=min1;
					min1=i;
				}else if( hTree[i].count < hTree[min2].count){
					min2=i;
				}
			}
		}
		if( 511==min2)  break;  //done if only one node left( the root)
		// now min1,min2 are the least weighted nodes before nextfree
		// update nextfree as parents of min1,min2
		hTree[nextfree].count = hTree[min1].count + hTree[min2].count;
		hTree[nextfree].lchild = min1;
		hTree[nextfree].rchild = min2;
		// min1 and min2 need to be updated too
		hTree[min1].parent = nextfree;
		hTree[min2].parent = nextfree;
	}
	nextfree --;
	return nextfree;
}

void BuildCode( void){
	unsigned long code;
	unsigned long mask;
	int n, codelength;
	int currentNode, parentNode;
	for( n=0; n<256; n++){
		codelength = 0;
		code = 0;
		mask = 1;
		for( currentNode=n, parentNode=hTree[currentNode].parent; 
				0!=parentNode; 
				currentNode=parentNode, parentNode=hTree[parentNode].parent){
			if( currentNode == hTree[parentNode].rchild)
				code |= mask;
			mask <<= 1;
			codelength++;
		}
		hCode[n].code = code;
		hCode[n].codelength = codelength;
	}
}

void HuffmanEncode( FILE *fp, BITFILE *bf){
	unsigned long filelength;
	int i;
	BuildCounts( fp);
	fseek( fp, 0, SEEK_END);
	filelength = ftell( fp);
	BitsOutput( bf, filelength, 4*8);
	for( i=0; i<256; i++) BitsOutput( bf, counts[i], 4*8);
	BuildTree( );
	BuildCode( );
	fseek( fp, 0, SEEK_SET);
	while( EOF!=(i=fgetc(fp))){
		BitsOutput( bf, hCode[i].code, hCode[i].codelength);
	}
}

void HuffmanDecode( BITFILE *bf, FILE *fp){
	unsigned long filelength;
	int i;
	int rootNode;
	int node;

	filelength = BitsInput( bf, 4*8);
	if( -1 == filelength) filelength = 0;
	// reading the counts
	for( i=0; i<256; i++) counts[i] = BitsInput( bf, 4*8);
	rootNode = BuildTree( );
	while( 0<filelength){
		node = rootNode;
		do{
			if( 0 == BitInput( bf)) node = hTree[node].lchild;
			else node = hTree[node].rchild;
		}while( 255<node);
		fputc( node, fp);
		filelength --;
	}
}

int main( int argc, char **argv){
	FILE *fp;
	BITFILE *bf;

	if( 4>argc){
		fprintf( stdout, "usage: %s <o> <ifile> <ofile>\n", argv[0]);
		fprintf( stdout, "\t<o>: E or D reffers encode or decode\n");
		fprintf( stdout, "\t<ifile>: input file name\n");
		fprintf( stdout, "\t<ofile>: output file name\n");
		return -1;
	}
	if( 'E' == argv[1][0]){ // do encoding
		fp = fopen( argv[2], "rb");
		bf = OpenBitFileOutput( argv[3]);
		if( NULL!=fp && NULL!=bf){
			HuffmanEncode( fp, bf);
			fclose( fp);
			CloseBitFileOutput( bf);
			fprintf( stdout, "encoding done\n");
		}
	}else if( 'D' == argv[1][0]){	// do decoding
		bf = OpenBitFileInput( argv[2]);
		fp = fopen( argv[3], "wb");
		if( NULL!=fp && NULL!=bf){
			HuffmanDecode( bf, fp);
			fclose( fp);
			CloseBitFileInput( bf);
			fprintf( stdout, "decoding done\n");
		}
	}else{	// otherwise
		fprintf( stderr, "not supported operation\n");
	}
	return 0;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -