看了算法导论关于霍夫曼编码的内容,然后做了实现,可能并不是很好,写得比较复杂,结合了最小优先级队列。
//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);
}