数据结构代码小总:动态数组引论 哈夫曼

动态数组引论:



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

//1MB = 1024*1024
typedef struct {
	char name[995];
	int id;
}node;

typedef struct Vectorst {
	int size;
	int maxSize;
	node* data;
}* Vector;

Vector VectorNew(void);
void VectorPushBack(Vector v, node e);
node VectorPopBack(Vector v);
node VectorGet(Vector v, int index);
int VectorSize(Vector v);
int VectorMaxSize(Vector v);
void VectorRm(Vector v, int index);
void VectorDelete(Vector v);

Vector VectorNew(void) {
	Vector v = (Vector)malloc(sizeof(struct Vectorst));
	assert(v != NULL);
	v->size = 0;
	v->maxSize = 32;
	v->data = (node*)malloc(sizeof(node)*v->maxSize);
	assert(v->data != NULL);
	return v;
}

void VectorPushBack(Vector v, node e) {
	assert(v != NULL);
	if (v->size >= v->maxSize) {
		v->maxSize *= 2;
		v->data = (node*)realloc(v->data, v->maxSize * sizeof(node));
		assert(v->data != NULL);
	}
	v->data[v->size++] = e;
}

node VectorPopBack(Vector v) {
	assert(v != NULL && v->size > 0);
	return v->data[--v->size];
}

node VectorGet(Vector v, int index) {
	assert(v != NULL && index >= 0 && index < v->size);
	return v->data[index];
}
int VectorSize(Vector v) {
	assert(v != NULL);
	return v->size;
}
int VectorMaxSize(Vector v) {
	assert(v != NULL);
	return v->maxSize;
}
void VectorRm(Vector v, int index) {
	assert(v != NULL || index <= v->size - 1);
	int i;
	if (index < v->size - 1) {
		for (i = index;i < v->size - 1;i++) {
			v->data[i] = v->data[i + 1];
		}
		v->size--;
	}
	else {
		v->size--;
	}
}
void VectorDelete(Vector v) {
	assert(v != NULL && v->data != NULL);
	free(v->data);
	free(v);
}
int main(void) {
	//node MyArr[1024*2];

	/*node e;
	e.id = 1;
	strcpy(e.name, "laoxia");
	node e1;
	e1.id = 2;
	strcpy(e1.name, "laoding");
	printf("id=%d,name=%s\n", e.id, e.name);
	printf("id=%d,name=%s\n", e1.id, e1.name);*/

	/*MyArr[0].id = 1000;
	strcpy(MyArr[0].name, "C++");
	printf("id=%d,name=%s\n", MyArr[0].id, MyArr[0].name);*/
	Vector v = VectorNew();
	node e;
	for (int i = 0;i < 1024 * 2;i++) {
		e.id = i;
		VectorPushBack(v, e);
	}
	printf("size of Vector=%d\n", VectorSize(v));

	for (int i = 0;i < 1024 * 2;i++) {
		printf("%d,", VectorGet(v, i).id);
	}
	system("pause");
	return 0;
}

综合 哈夫曼



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


//以字节形式读入目标文件,统计字符频度作为临时节点
typedef struct {
	unsigned char uch;//以8位为单元作为无符号的字符
	unsigned long weight;//每一个以二进制进行区分的字符出现的频度

}TmpNode;

//Huffman树的节点
typedef struct {
	unsigned char uch;//无符号字符
	unsigned long weight;
	char* code;//字符对应的huffman编码(动态分配存储空间)
	int parent, lchild, rchild;
}HufNode,*HufTree;

//建立Huffman树
void select(HufNode* huf_tree, unsigned int n, int *s1, int *s2) {
	//找最小
	unsigned int i;
	unsigned long min = ULONG_MAX;
	for (i = 0;i < n;i++) {
		if (huf_tree[i].parent == 0 && huf_tree[i].weight < min) {
			min = huf_tree[i].weight;
			*s1 = i;
		}
	}
	huf_tree[*s1].parent = 1;//此节点已经选中

	//找次小
	min = ULLONG_MAX;
	for (i = 0;i < n;i++) {
		if (huf_tree[i].parent == 0 && huf_tree[i].weight < min) {
			min = huf_tree[i].weight;
			*s2 = i;
		}
	}
}

//建立huffman树
void CreateTree(HufNode *huf_tree, unsigned int char_kinds, unsigned int node_num) {
	unsigned int i;
	int s1, s2;
	for (i = char_kinds;i < node_num;i++) {
		select(huf_tree, i, &s1, &s2);
		huf_tree[s1].parent = huf_tree[s2].parent = i;
		huf_tree[i].lchild = s1;
		huf_tree[i].rchild = s2;
		huf_tree[i].weight = huf_tree[s1].weight + huf_tree[s2].weight;
	}
}

//生成huffman编码
void HufCode(HufNode* huf_tree, unsigned char_kinds) {
	unsigned int i;
	int cur, next, index;
	char* code_tmp = (char*)malloc(256 * sizeof(char));//暂存编码,最多256个叶子,编码不超过255
	code_tmp[255] = '\0';
	for (i = 0;i < char_kinds;i++) {
		//从叶子向根反向遍历求解
		index = 255;//索引
		for (cur = i, next = huf_tree[i].parent;next != 0;cur = next, next = huf_tree[next].parent) {
			if (huf_tree[next].lchild == cur)
				code_tmp[--index] = '0';//左0
			else
				code_tmp[--index] = '1';
		}
		//为第i个字符编码动态分配空间
		huf_tree[i].code = (char*)malloc((256 - index) * sizeof(char));
		strcpy(huf_tree[i].code, &code_tmp[index]);//正向保存编码到树节点响应的域
	}
	free(code_tmp);
}

//compress

int compress(char* ifname,char* ofname){
	unsigned int i, j;
	unsigned int char_kinds;//字符的种类
	unsigned char char_temp;//暂存8位的字符

	unsigned long file_len = 0;

	FILE* infile, *outfile;
	TmpNode node_temp;
	unsigned int node_num;
	HufTree huf_Tree;
	char code_buf[256] = { '\0' };//待存编码缓冲区
	unsigned int code_len;

	//动态分配256个节点,暂存字符频度
	//统计并拷贝到树节点后立即释放
	
	TmpNode* tmp_nodes = (TmpNode*)malloc(256 * sizeof(TmpNode));
	//初始化暂存节点
	for (i = 0;i < 256;i++) {
		tmp_nodes[i].weight = 0;
		tmp_nodes[i].uch = (unsigned char)i;//数组的256个角标与256种字符对应
	}

	//遍历文件获取字符频度
	infile = fopen(ifname, "rb");
	if (infile == NULL)
		return -1;
	fread((char*)&char_temp, sizeof(unsigned char), 1, infile);//读入一个字符

	while(!feof(infile)){
		//统计下标对应的字符权重
		++tmp_nodes[char_temp].weight;
		++file_len;
		fread((char*)&char_temp, sizeof(unsigned char), 1, infile);
	}
	fclose(infile);

	//排序,将频度为0的放到最后,剔除
	for (i = 0;i < 255;i++) {
		for (j = i + 1;j < 256;j++) {
			if (tmp_nodes[i].weight < tmp_nodes[j].weight) {
				node_temp = tmp_nodes[i];
				tmp_nodes[i] = tmp_nodes[j];
				tmp_nodes[j] = node_temp;
			}
		}
	}

	//统计实际的字符种类
	for (i = 0;i < 256;i++) {
		if (tmp_nodes[i].weight == 0)
			break;
	}
	char_kinds = i;

	if (char_kinds == 1) {
		outfile = fopen(ofname, "wb");
		fwrite((char*)&char_kinds, sizeof(unsigned int), 1, outfile);
		fwrite((char*)&tmp_nodes[0].uch, sizeof(unsigned char), 1, outfile);
		fwrite((char*)&tmp_nodes[0].weight, sizeof(unsigned long), 1, outfile);
		free(tmp_nodes);
		fclose(outfile);
	}
	else {
		//根据字符种类数,计算建立Huffman树所有需要的节点
		node_num = 2 * char_kinds - 1;
		huf_Tree = (HufNode*)malloc(node_num * sizeof(HufNode));

		//初始化前char_kinds的节点
		for (i = 0;i < char_kinds;i++) {
			huf_Tree[i].uch = tmp_nodes[i].uch;
			huf_Tree[i].weight = tmp_nodes[i].weight;
			huf_Tree[i].parent = 0;
		}
		free(tmp_nodes);

		//初始化后面的node_num-char_kinds
		for (;i < node_num;i++)
			huf_Tree[i].parent = 0;

		//建树
		CreateTree(huf_Tree, char_kinds, node_num);
		//生Huffman
		HufCode(huf_Tree, char_kinds);
		//写入字符和相应的权重,以便解压的时候,我们重建huffman树
		outfile = fopen(ofname, "wb");
		fwrite((char*)&char_kinds, sizeof(unsigned int), 1, outfile);
		for (i = 0;i < char_kinds;i++) {
			fwrite((char*)&huf_Tree[i].uch, sizeof(unsigned char), 1, outfile);
			fwrite((char*)&huf_Tree[i].weight, sizeof(unsigned long), 1, outfile);
		}

		//接下来,将字符和权重信息后面写入文件长度和字符编码
		fwrite((char*)&file_len, sizeof(unsigned long), 1, outfile);
		infile = fopen(ifname, "rb");
		fread((char*)&char_temp, sizeof(unsigned char), 1, infile);
		while (!feof(infile)) {
			//匹配字符对应编码
			for (i = 0;i < char_kinds;i++)
				if (char_temp == huf_Tree[i].uch)
					strcat(code_buf, huf_Tree[i].code);
			//以8位为一个处理单元
			while (strlen(code_buf) >= 8) {
				char_temp = '\0';
				for (i = 0;i < 8;i++) {
					char_temp <<= 1;
					if (code_buf[i] == '1') {
						char_temp |= 1;
					}
				}
				fwrite((char*)&char_temp, sizeof(unsigned char), 1, outfile);
				strcpy(code_buf, code_buf + 8);
			}
			fread((char*)&char_temp, sizeof(unsigned char), 1, infile);
		}

		//处理一下不足8位
		code_len = strlen(code_buf);
		if (code_len > 0) {
			char_temp = '\0';
			for (i = 0;i < code_len;i++) {
				char_temp <<= 1;
				if (code_buf[i] == '1')
					char_temp != 1;
			}
			char_temp <<= 8 - code_len;
			fwrite((char*)&char_temp, sizeof(unsigned char), 1, outfile);
		}
		fclose(infile);
		fclose(outfile);
		
		for (i = 0;i < char_kinds;i++)
			free(huf_Tree[i].code);
		free(huf_Tree);
		
	}

}


int extract(char* ifname, char* ofname)
{
	unsigned int i;
	unsigned long file_len;
	unsigned long writen_len = 0;//控制文件的写入长度
	FILE* infile, *outfile;
	unsigned int char_kinds;//存储字符种类
	unsigned int node_num;
	HufTree huf_tree;
	unsigned char code_temp;//暂存8位的编码
	//构建huffman树,因此,定义根节点的索引
	unsigned int root;

	infile = fopen(ifname, "rb");
	if (infile == NULL)
		return -1;

	//重建haffman树
	fread((char*)&char_kinds, sizeof(unsigned int), 1, infile);
	if (char_kinds == 1) {
		fread((char*)&code_temp, sizeof(unsigned char), 1, infile);
		fread((char*)&file_len, sizeof(unsigned long), 1, infile);
		outfile = fopen(ofname, "wb");//打开压缩后的文件
		while (file_len--)
			fwrite((char*)&code_temp, sizeof(unsigned char), 1, outfile);
		fclose(infile);
		fclose(outfile);

	}
	else {
		node_num = 2 * char_kinds - 1;//左孩子,和右孩子重建huffman树
		huf_tree = (HufNode*)malloc(node_num * sizeof(HufNode));
		//读取字符以及对应的权重
		for (i = 0;i < char_kinds;i++) {
			fread((char*)&huf_tree[i].uch, sizeof(unsigned char), 1, infile);
			fread((char*)&huf_tree[i].weight, sizeof(unsigned long), 1, infile);
			huf_tree[i].parent = 0;
		}

		//初始化后面的每一个节点的parent
		for (;i < node_num;i++) {
			huf_tree[i].parent = 0;
		}

		CreateTree(huf_tree, char_kinds, node_num);

		//读完了字符和权重的信息,再读取文件长度和编码,开始解压缩
		fread((char*)&file_len, sizeof(unsigned long), 1, infile);
		outfile = fopen(ofname, "wb");
		root = node_num - 1;

		while (1) {
			fread((char*)&code_temp, sizeof(unsigned char), 1, infile);
			for (i = 0;i < 8;i++) {
				//从root开始到叶子节点进行恢复
				if (code_temp & 128)
					root = huf_tree[root].rchild;
				else
					root = huf_tree[root].lchild;
				if (root < char_kinds) {
					fwrite((char*)&huf_tree[root].uch, sizeof(unsigned char), 1, outfile);
					++writen_len;
					if (writen_len == file_len)
						break;
					root = node_num - 1;//复位根索引,匹配下一个字符
				}
				code_temp <<= 1;//将编码缓存的下一个移动到最高位,供匹配
			}
			if (writen_len == file_len)
				break;
		}
		fclose(infile);
		fclose(outfile);
		free(huf_tree);
	}
}


int main(void) {
	//compress("d://dingst.bmp", "d://dingst.bmp.hfm");
	//extract("d://dingst.bmp.hfm","d://laoxia.bmp");
	{
	FILE* fpSrc = fopen("d://dingst.bmp", "r");
	fseek(fpSrc, 0L, SEEK_END);
	printf("dinst BMP size=%d\n", ftell(fpSrc));
	fclose(fpSrc);
	}
	///////////////////////HFM
	{
		FILE* fpSrc = fopen("d://dingst.bmp.hfm", "r");
		fseek(fpSrc, 0L, SEEK_END);
		printf("huffman压缩的 size=%d\n", ftell(fpSrc));
		fclose(fpSrc);
	}
	/////////////////////end HFM
	///////////////////////解压还原的
	{
		FILE* fpSrc = fopen("d://laoxia.bmp", "r");
		fseek(fpSrc, 0L, SEEK_END);
		printf("huffman还原的 size=%d\n", ftell(fpSrc));
		fclose(fpSrc);
	}
	/////////////////////end 还原

	system("pause");
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_41543888/article/details/97055162
今日推荐