@songpfei
2016-02-20T12:16:16.000000Z
字数 8752
阅读 2382
算法导论
/*-----------------------------------------------------------------* Name: 哈夫曼编码源代码。* Date: 2011.04.16* Author: Jeffrey Hill* 在 Win-TC 下测试通过* 实现过程:着先通过 HuffmanTree() 函数构造哈夫曼树,然后在主函数 main()中* 自底向上开始(也就是从数组序号为零的结点开始)向上层层判断,若在* 父结点左侧,则置码为 0,若在右侧,则置码为 1。最后输出生成的编码。*----------------------------------------------------------------*/#include <stdio.h>#include<conio.h>#define MAXBIT 100#define MAXVALUE 10000#define MAXLEAF 30#define MAXNODE MAXLEAF*2 -1typedef struct{int bit[MAXBIT];int start;} HCodeType; /* 编码结构体 */typedef struct{int weight;int parent;int lchild;int rchild;} HNodeType; /* 结点结构体 *//* 构造一颗哈夫曼树 */void HuffmanTree(HNodeType HuffNode[MAXNODE], int n){/* i、j: 循环变量,m1、m2:构造哈夫曼树不同过程中两个最小权值结点的权值,x1、x2:构造哈夫曼树不同过程中两个最小权值结点在数组中的序号。*/int i, j, m1, m2, x1, x2;/* 初始化存放哈夫曼树数组 HuffNode[] 中的结点 */for (i = 0; i<2 * n - 1; i++){HuffNode[i].weight = 0;HuffNode[i].parent = -1;HuffNode[i].lchild = -1;HuffNode[i].lchild = -1;} /* end for *//* 输入 n 个叶子结点的权值 */for (i = 0; i<n; i++){printf("Please input weight of leaf node %d: \n", i);scanf("%d", &HuffNode[i].weight);} /* end for *//* 循环构造 Huffman 树 */for (i = 0; i<n - 1; i++){m1 = m2 = MAXVALUE; /* m1、m2中存放两个无父结点且结点权值最小的两个结点 */x1 = x2 = 0;/* 找出所有结点中权值最小、无父结点的两个结点,并合并之为一颗二叉树 */for (j = 0; j<n + i; j++){if (HuffNode[j].weight < m1 && HuffNode[j].parent == -1){m2 = m1;x2 = x1;m1 = HuffNode[j].weight;x1 = j;}else if (HuffNode[j].weight < m2 && HuffNode[j].parent == -1){m2 = HuffNode[j].weight;x2 = j;}} /* end for *//* 设置找到的两个子结点 x1、x2 的父结点信息 */HuffNode[x1].parent = n + i;HuffNode[x2].parent = n + i;HuffNode[n + i].weight = HuffNode[x1].weight + HuffNode[x2].weight;HuffNode[n + i].lchild = x1;HuffNode[n + i].rchild = x2;printf("x1.weight and x2.weight in round %d: %d, %d\n", i + 1, HuffNode[x1].weight, HuffNode[x2].weight); /* 用于测试 */printf("\n");} /* end for */} /* end HuffmanTree */int main(void){HNodeType HuffNode[MAXNODE]; /* 定义一个结点结构体数组 */HCodeType HuffCode[MAXLEAF], cd; /* 定义一个编码结构体数组, 同时定义一个临时变量来存放求解编码时的信息 */int i, j, c, p, n;printf("Please input n:\n");scanf("%d", &n);HuffmanTree(HuffNode, n);for (i = 0; i < n; i++){cd.start = n - 1;c = i;p = HuffNode[c].parent;while (p != -1) /* 父结点存在 */{if (HuffNode[p].lchild == c)cd.bit[cd.start] = 0;elsecd.bit[cd.start] = 1;cd.start--; /* 求编码的低一位 */c = p;p = HuffNode[c].parent; /* 设置下一循环条件 */} /* end while *//* 保存求出的每个叶结点的哈夫曼编码和编码的起始位 */for (j = cd.start + 1; j<n; j++){HuffCode[i].bit[j] = cd.bit[j];}HuffCode[i].start = cd.start;} /* end for *//* 输出已保存好的所有存在编码的哈夫曼编码 */for (i = 0; i<n; i++){printf("%d 's Huffman code is: ", i);for (j = HuffCode[i].start + 1; j < n; j++){printf("%d", HuffCode[i].bit[j]);}printf("\n");}_getch();return 0;}
参考:http://www.cnblogs.com/syblogs/articles/2020145.html
#include <stdio.h>#include <stdlib.h>#include <string.h>//哈夫曼树结点typedef struct HuffNode{int weight;char ch;char code[20];struct HuffNode *rchild;struct HuffNode *lchild;}HuffMan;//队列设计typedef struct _node_{HuffMan *data;struct _node_ *next;}ListNode;typedef struct{ListNode *front;ListNode *rear;}Queue;//create empty queueQueue *create_empty_queue(){ListNode *HList;Queue *Hqueue;HList = (ListNode *)malloc(sizeof(ListNode));HList->next = NULL;Hqueue = (Queue *)malloc(sizeof(Queue));Hqueue->front = Hqueue->rear = HList;return Hqueue;}//入队int EnterQueue(Queue *head,HuffMan *data){ListNode *temp;temp = (ListNode *)malloc(sizeof(ListNode));temp->data = data;temp->next = NULL;head->rear->next = temp;head->rear = temp;return 0;}//有序插入结点int OrderEnterQueue(Queue *head,HuffMan *p){ListNode *m = head->front->next;ListNode *n = head->front;ListNode *temp;while(m){if(m->data->weight < p->weight){m = m->next;n = n->next;}else{break;}}//插到最后一个结点if(m == NULL){temp = (ListNode *)malloc(sizeof(ListNode));temp->data = p;temp->next = NULL;n->next = temp;head->rear = temp;return 0;}//插入中间结点temp = (ListNode *)malloc(sizeof(ListNode));temp->data = p;n->next = temp;temp->next = m;return 0;}//判断队列是否为空(注意,我们认为队列含有一个结点为空,想想为什么//这样做?int _is_empty_queue(Queue *head){if(head->front->next->next == NULL){printf("is_empty_queue\n");return 1;}return 0;}//判断队列是否为空int is_empty_queue(Queue *head){if(head->front == head->rear)return 1;elsereturn 0;}//出队HuffMan *DeleteQueue(Queue * head){ListNode *temp;temp = head->front;head->front = temp->next;free(temp);temp = NULL;return head->front->data;}//创建哈夫曼树HuffMan *create_huffman_tree(Queue *head){HuffMan *right,*left,*current;//循环结束时,队列只含有一个结点while(!_is_empty_queue(head)){left = DeleteQueue(head);right = DeleteQueue(head);current = (HuffMan *)malloc(sizeof(HuffMan));current->weight = left->weight + right->weight;current->rchild = right;current->lchild = left;OrderEnterQueue(head,current);}return head->front->next->data;}//哈夫曼编码int HuffmanCode(HuffMan *root){HuffMan *current = NULL;Queue *queue = NULL;queue = create_empty_queue();EnterQueue(queue, root);while(!is_empty_queue(queue)){current = DeleteQueue(queue);if(current->rchild == NULL && current->lchild == NULL){printf("%c:%d %s\n",current->ch,current->weight,current->code);}if(current->lchild){strcpy(current->lchild->code,current->code);strcat(current->lchild->code,"0");EnterQueue(queue, current->lchild);}if(current->rchild){strcpy(current->rchild->code,current->code);strcat(current->rchild->code,"1");EnterQueue(queue, current->rchild);}}return 0;}
参考:http://blog.chinaunix.net/uid-26833883-id-3160434.html
#include<stdlib.h>#include<stdio.h>#include<string.h>struct BinaryTree{int freq;//字符频率char c;//字符BinaryTree* lchild;BinaryTree* rchild;};typedef struct BinaryTree HuffumanTreeNode;HuffumanTreeNode* BuildTreeNode(int freq, char c, HuffumanTreeNode* lchild, HuffumanTreeNode* rchild){HuffumanTreeNode* node = (HuffumanTreeNode*)malloc(sizeof(HuffumanTreeNode));if (node != NULL){node->freq = freq;node->c = c;node->lchild = lchild;node->rchild = rchild;}return node;}void ClearTree(HuffumanTreeNode *root){if (root == NULL)return;if (root->lchild == NULL&&root->rchild == NULL)return;if (root->lchild != NULL){ClearTree(root->lchild);free(root->lchild);root->lchild = NULL;}if (root->rchild != NULL){ClearTree(root->rchild);free(root->rchild);root->rchild = NULL;}}typedef struct tagQueen{int length;//队列容量int heapsize;//队列中当前所有元素的个数HuffumanTreeNode* heap;}PriorityQueen;//定义一个二叉堆实现的优先队列结构PriorityQueen* AllocHeap(int n){PriorityQueen *q= (PriorityQueen*)malloc(sizeof(PriorityQueen));if (q == NULL)return NULL;q->length = n;q->heapsize = 0;q->heap = (HuffumanTreeNode*)malloc(n*sizeof(HuffumanTreeNode));if (q->heap == NULL){free(q);q = NULL;}return q;}int parent(int i)//父节点下标{return (i - 1) / 2;}int left(int i)//左孩子下标{return 2 * i + 1;}int right(int i)//右孩子下标{return 2 * i + 2;}void swap(HuffumanTreeNode* x, HuffumanTreeNode* y){HuffumanTreeNode temp = *y;*y = *x;*x = temp;}/*--------------------------------------------最小堆性质维护i:待维护节点heapsize:堆元素个数----------------------------------------------*/void heapify(HuffumanTreeNode* e,int i,int heapsize){int l, r, most;l = left(i);r = right(i);if (l<heapsize && (e + l)->freq<(e + i)->freq)//left<imost = l;elsemost = i;if (r<heapsize && (e + r)->freq<(e + most)->freq)//right<mostmost = r;if (most != i)//i不是最小结点,交换元素位置,使其满足最小堆的性质{swap(e + i, e + most);heapify(e, most, heapsize);//递归检测}}/*----------------------------------------------------入队操作,按最小堆实现------------------------------------------------------*/void enQueen(PriorityQueen *q,HuffumanTreeNode* e){if (q == NULL || e == NULL)return;if (q->length == q->heapsize)//队列已满return;int i = q->heapsize++;//堆扩大后最后元素的下标*(q->heap + i) = *e;//复制树节点到队列中while (i > 0 && (q->heap + i)->freq <(q->heap + parent(i))->freq)//heap[i]<parent(i),其小于父节点{swap((q->heap + i), (q->heap + parent(i)));//交换元素,维护堆的性质i = parent(i);}}/*----------------------------------------------------出队操作------------------------------------------------------*/HuffumanTreeNode* deQueen(PriorityQueen* q){if (q == NULL || q->heapsize == 0)//队列不存在或为空return NULL;HuffumanTreeNode* top_node = (HuffumanTreeNode*)malloc(sizeof(HuffumanTreeNode));*top_node = *(q->heap);q->heapsize--;//删除堆中一个元素*(q->heap) = *(q->heap + q->heapsize);//heap[0]=heap[heapsize]heapify(q->heap,0,q->heapsize);//堆性质维护return top_node;}bool isQueenEmpty(PriorityQueen* q){if (q == NULL)return 1;elsereturn q->heapsize < 1;}void PriorityQueenClear(PriorityQueen* q){if (q == NULL)return;free(q->heap);q->heap = NULL;q->length = q->heapsize = 0;}HuffumanTreeNode* huffuman(int*f, char*d, int n){HuffumanTreeNode* min1, *min2, *e;PriorityQueen* q = AllocHeap(n);//创建队列for (int i = 0; i < n; i++){e = BuildTreeNode(f[i], d[i], NULL, NULL);enQueen(q, e);}for (int i = 0; i < n - 1;i++){min1 = deQueen(q);min2 = deQueen(q);e = BuildTreeNode(min1->freq + min2->freq, '*', min1, min2);enQueen(q, e);}e = deQueen(q);//返回huffumanTree根结点PriorityQueenClear(q);return e;}void PrintHuffumanCode(HuffumanTreeNode* root,char* c){if (root == NULL || c == NULL)return;int l = strlen(c);char* c1 = (char*)malloc((l + 2)*sizeof(char));if (root->lchild != NULL)//向左搜索{strcpy_s(c1, sizeof(c1), c);strcat_s(c1, strlen(c1) + 2, "0");PrintHuffumanCode(root->lchild, c1);}if (root->rchild != NULL){strcpy_s(c1, sizeof(c1), c);strcat_s(c1, strlen(c1) + 2, "1");PrintHuffumanCode(root->rchild, c1);}if (root->lchild == NULL&&root->rchild == NULL)//打印叶子节点printf("character:%c frequency: %d code: %s\n", root->c, root->freq, c);}int main(int argc, char** argv){int f[] = { 45, 13, 12, 16, 9, 5 };char d[] = { 'a', 'b', 'c', 'd', 'e', 'f' };BinaryTree* h = huffuman(f, d, 6);PrintHuffumanCode(h, "");ClearTree(h);h = NULL;system("pause");return (EXIT_SUCCESS);}