哈夫曼树的应用就不说了,主要是用于优化算法和文本压缩。
哈夫曼树的实现的原理还算比较简单的,至少我认为比红黑树简单,但是,哈夫曼树的实现的编码是个头疼的问题,它的实现有很多的细节,很难说哪一种实现是最好的,必须依据现实的具体情况进行设计,不过有几个细节还是可以说下的,比如找最小值可以使用小堆用于优化,至于编码是从根开始,还是从叶子开始,看具体情况吧!!!
#include <stdio.h>
#include <assert.h>
#include <string.h>
using namespace std;
struct HufNode {
int key;
HufNode *lChild;
HufNode *rChild;
int nIndex;
char code[BUFSIZ];
};
struct ListHufNode{
HufNode *data;
ListHufNode *next;
ListHufNode *pre;
};
class List_Huf_Node {
public:
List_Huf_Node() {
head = new ListHufNode;
memset(head, 0, sizeof(ListHufNode));
tail = new ListHufNode;
memset(tail , 0, sizeof(ListHufNode));
head->next = tail;
tail->pre = head;
}
~List_Huf_Node() {
delete head;
delete tail;
}
void insert_huf_node(HufNode *huf_node) {
ListHufNode *node = new ListHufNode;
memset(node, 0, sizeof(ListHufNode));
node->data = huf_node;
node->pre = tail->pre;
node->pre->next = node;
node->next = tail;
tail->pre = node;
}
void Get_Min_Min2_Huf_Node(HufNode **min_node, HufNode **min_node2) {
ListHufNode *min, *min2;
ListHufNode *p = head->next;
min = min2 = NULL;
while (p != tail) {
if (min==NULL || p->data->key < min->data->key) {
min2 = min;
min = p;
}
else if (min2==NULL || p->data->key < min2->data->key) {
min2 = p;
}
p = p->next;
}
*min_node = min->data;
*min_node2 = min2->data;
ListHufNode *pre = NULL;
pre = min->pre;
pre->next = min->next;
pre->next->pre = pre;
pre = min2->pre;
pre->next = min2->next;
pre->next->pre = pre;
delete min;
delete min2;
}
void GetFirstElement(HufNode **huf_node) {
*huf_node = head->next->data;
ListHufNode *cur = head->next;
head->next = cur->next;
head->next->pre = head;
delete cur;
}
bool IsHaveMoreThanTwoElement() {
return head->next!=tail && head->next->next!=tail;
}
bool IsEmpty() {
return head->next==tail;
}
private:
ListHufNode *head;
ListHufNode *tail;
};
void HuffmanCode(int a[], char codes[][BUFSIZ], int len) {
assert(len>1);
// 建立结点
HufNode *node = NULL;
HufNode *min_node = NULL;
HufNode *min_node2 = NULL;
List_Huf_Node list_huf_node;
for (int i=0; i<len; ++i) {
node = new HufNode;
memset(node, 0, sizeof(HufNode));
node->key = a[i];
node->nIndex = i;
list_huf_node.insert_huf_node(node);
}
while (list_huf_node.IsHaveMoreThanTwoElement()) {
list_huf_node.Get_Min_Min2_Huf_Node(&min_node, &min_node2);
node = new HufNode;
memset(node, 0, sizeof(HufNode));
node->key = min_node->key + min_node2->key;
node->lChild = min_node;
node->rChild = min_node2;
list_huf_node.insert_huf_node(node);
}
while (list_huf_node.IsEmpty()==false) {
list_huf_node.GetFirstElement(&node);
if (node->lChild != NULL) {
strcat(node->lChild->code, node->code);
strcat(node->lChild->code, "0");
list_huf_node.insert_huf_node(node->lChild);
}
if (node->rChild != NULL) {
strcat(node->rChild->code, node->code);
strcat(node->rChild->code, "1");
list_huf_node.insert_huf_node(node->rChild);
}
if (node->lChild==NULL && node->rChild==NULL) {
strcpy(codes[node->nIndex], node->code);
}
delete node;
}
}
int main() {
const int SIZE = 4;
int a[SIZE] = {20, 40, 25, 15};
char code[SIZE][BUFSIZ] = {0};
HuffmanCode(a, code, SIZE);
for (int i=0; i<SIZE; ++i) {
printf("%d:%s\n", a[i], code[i]);
}
putchar('\n');
return 0;
}