霍夫曼编码

看了算法导论关于霍夫曼编码的内容,然后做了实现,可能并不是很好,写得比较复杂,结合了最小优先级队列。

//heap.h

#ifndef HEAP_H
#define HEAP_H

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

typedef struct _letter
{
	int freq;
	char alpha;
	char *code;
}stLetter;


typedef struct _heapNode
{
	stLetter *let;	
}stHeapNode;

typedef struct _heap
{
	stHeapNode *nodeAry;
	int nLen;
}stHeap;


void print(stHeap *heap);
void swap(stLetter *firstLet, stLetter *lastLet);
void minHeap(stHeap *heap, int i);
void buildHeap(stHeap *heap);
void heapInsert(stHeap *src, stLetter *lett);
stLetter * minExtract(stHeap *heap);
int lettFreq(stHeap *heap, int i);
stHeapNode *heapNode(stHeap *heap, int i);
stLetter *nodeLetter(stHeap *heap, int i);

#endif

//heap.c

#include "heap.h"

int lettFreq(stHeap *heap, int i)
{
	stLetter *lett = nodeLetter(heap, i);
	return lett->freq;
}

stHeapNode *heapNode(stHeap *heap, int i)
{
	return &heap->nodeAry[i];
}

stLetter *nodeLetter(stHeap *heap, int i)
{
	return heap->nodeAry[i].let;
}

void print(stHeap *heap)
{
	int i = 0;
	for(i = 0; i < heap->nLen; i++)
	{
		printf("%c %d %s", nodeLetter(heap, i)->alpha, 
						   nodeLetter(heap, i)->freq,
						   nodeLetter(heap, i)->code);
	}
	printf("\n");
}

void swap(stHeapNode *firstNode, stHeapNode *lastNode)
{
	stLetter *lett = firstNode->let;
	firstNode->let = lastNode->let;
	lastNode->let = lett;
}

void minHeap(stHeap *heap, int i)
{
	int min = i;
	if ((2 * i + 1 < heap->nLen) && (lettFreq(heap, 2 * i + 1) < lettFreq(heap, i)))
	{
		min = 2 * i + 1;
	}
	if ((2 * i + 2 < heap->nLen) && (lettFreq(heap, 2 * i + 2) < lettFreq(heap, min)))
	{
		min = 2 * i + 2;
	}
	if(min != i)
	{
		stHeapNode *iNode = heapNode(heap, i);
		stHeapNode *minNode = heapNode(heap, min);
		swap(iNode, minNode);
		minHeap(heap, min);
	}
}

void buildHeap(stHeap *heap)
{
	int i = 0;
	for(i = heap->nLen  / 2 + 1; i >= 0; i--)
	{
		minHeap(heap, i);
	}
}

void heapInsert(stHeap *heap, stLetter *lett)
{	
	stHeapNode *temp = (stHeapNode *)malloc((heap->nLen + 1) * sizeof(stHeapNode));
	int i = 0; 
	for(i = 0; i < heap->nLen; i++)
	{
		temp[i].let = nodeLetter(heap, i);
	}
	temp[i].let = lett;
	heap->nLen++;
	free(heap->nodeAry);
	heap->nodeAry = temp;
	buildHeap(heap); 
}

stLetter *minExtract(stHeap *heap)
{
	stLetter *lett = nodeLetter(heap, 0);
	heapNode(heap, 0)->let = nodeLetter(heap, --heap->nLen);		
	stHeapNode *temp = (stHeapNode *)malloc(heap->nLen * sizeof(stHeapNode));
	memset(temp, 0, sizeof(temp));
   	memcpy(temp, heap->nodeAry, sizeof(stHeapNode) * heap->nLen);	
	free(heap->nodeAry);
	heap->nodeAry = temp;
	buildHeap(heap);
	return lett;
}

//huffman.h

#ifndef HUFFMAN_H
#define HUFFMAN_H
#include "heap.h"


typedef struct _huffNode
{
	stLetter *let;
	_huffNode *left;
	_huffNode *right;
}stHuffNode;

typedef struct _huffMan
{
	stHuffNode *root;
}stHuffman;


stHuffNode *createHuffNode(stLetter *lett);
stHuffNode *mergeNode(stLetter *left, stLetter *right);
stLetter *findMinFreq(stHeap *heap);
void insertNode(stHeap* heap, stLetter *lett);
stHuffNode *find2Merge(stHeap *heap);
stHuffman *huffmanCode(stHeap *heap);
void print(stHuffman *huffman);
void printNode(stHuffNode *node, char *code);
stHuffNode *findHuffNode(stLetter *lett);

#endif

//huffman.c

#include "huffman.h"
#include <malloc.h>

stHuffNode **huffNodeAry;
int g_num = 0;
stHuffNode *createHuffNode(stLetter *lett)
{
	stHuffNode *node = (stHuffNode *)malloc(sizeof(stHuffNode));
	node->let = (stLetter *)malloc(sizeof(stLetter));
	lett->code = (char *)malloc(sizeof(100));
	node->left = NULL;
	node->right = NULL;
	node->let = lett;
	return node;
}

stHuffNode *mergeNode(stLetter *left, stLetter *right)
{
	stHuffNode *node = (stHuffNode *)malloc(sizeof(stHuffNode));
	node->let = (stLetter *)malloc(sizeof(stLetter));
	node->let->code = (char *)malloc(sizeof(100));
	stHuffNode *leftNode;
	stHuffNode *rightNode;
	if(left->alpha != '#')
	{
		leftNode = createHuffNode(left);
	}
	else
	{
		leftNode = findHuffNode(left);
	}
	if(right->alpha != '#')
	{
		rightNode = createHuffNode(right);
	}
	else
	{
		rightNode = findHuffNode(right);
	}
	node->let->freq = left->freq + right->freq;
	node->let->alpha = '#';
	strcpy(leftNode->let->code, "0");
	node->left = leftNode;
	strcpy(rightNode->let->code, "1");
	node->right = rightNode;
	return node;
}

stLetter *findMinFreq(stHeap *heap)
{
	stLetter *lett = minExtract(heap);
	return lett;
}

void insertNode(stHeap* heap, stLetter *lett)
{
	heapInsert(heap, lett);
}

stHuffNode *find2Merge(stHeap *heap)
{
	stLetter *left = findMinFreq(heap);
	stLetter *right = findMinFreq(heap);
	stHuffNode *huffNode = mergeNode(left, right);
	insertNode(heap, huffNode->let);
	return huffNode;
}

stHuffNode *findHuffNode(stLetter *lett)
{
	int i = 0;
	for(i = 0; i < g_num; i++)
	{
		if(huffNodeAry[i]->let == lett)
		{
			return huffNodeAry[i];
		}
	}
}
stHuffman *huffmanCode(stHeap *heap)
{
	stHuffman *huffman = (stHuffman *)malloc(sizeof(stHuffman));
	stHuffNode *huffNode;
	huffNodeAry = (stHuffNode **)malloc(sizeof(stHuffNode*) * heap->nLen);
	int i = 0;
	while(heap->nLen != 1)
	{
		huffNode = find2Merge(heap);
		huffNodeAry[i] = huffNode;
		i++;
		g_num++;
	}
	huffman->root = huffNode;
	return huffman;
}

void print(stHuffman *huffman)
{
	char *code = (char *)malloc(100);
	memset(code, 0, sizeof(code));
	printNode(huffman->root, code);	
}

void printNode(stHuffNode *node, char *code)
{
	char *tCode = (char *)malloc(100);
	tCode = strcpy(tCode, code);
	tCode = strncat(tCode, node->let->code, sizeof(node->let->code));
	if(node->left == NULL && node->right == NULL)
	{
	
		printf("%d %c %s\n", node->let->freq, node->let->alpha, tCode);
		return;
	}
	else
	{
		if(node->left != NULL)
		{
			printNode(node->left, tCode);
		}
		if(node->right != NULL)
		{
			printNode(node->right, tCode);
		}
	}
}

//main.c

#include "huffman.h"

#define NUM 6

int main()
{
	stHeap *minHeap = (stHeap *)malloc(sizeof(stHeap));
	minHeap->nodeAry = (stHeapNode *)malloc(sizeof(stHeapNode) * NUM);
	minHeap->nLen = NUM;
	int i = 0;
	for(i = 0; i < NUM; i++)
	{
		minHeap->nodeAry[i].let = (stLetter *)malloc(sizeof(stLetter));
	}
	minHeap->nodeAry[0].let->alpha = 'c';
	minHeap->nodeAry[0].let->freq = 12;
	minHeap->nodeAry[1].let->alpha = 'b';
	minHeap->nodeAry[1].let->freq = 13;
	minHeap->nodeAry[2].let->alpha = 'f';
	minHeap->nodeAry[2].let->freq = 5;
	minHeap->nodeAry[3].let->alpha = 'e';
	minHeap->nodeAry[3].let->freq = 9;
	minHeap->nodeAry[4].let->alpha = 'd';
	minHeap->nodeAry[4].let->freq = 16;
	minHeap->nodeAry[5].let->alpha = 'a';
	minHeap->nodeAry[5].let->freq = 45;
	buildHeap(minHeap);
	print(minHeap);
	stHuffman *huffman = huffmanCode(minHeap);
	print(huffman);
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值