队列实现霍夫曼树
前面一节我们知道了,怎样去创建一个哈夫曼树,这一节我们来看看哈夫曼编码。
思想:得到哈夫曼树后,自顶向下按路径编号,指向左节点的边编号0,指向右节点的边编号1,从根到叶节点的所有边上的0和1连接起来,就是叶子节点中字符的哈夫曼编码。
下图体现了哈夫曼编码的过程:
- #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 queue
- Queue *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;
- else
- return 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;
- }
运行结果: