@songpfei
2016-02-20T20:16:16.000000Z
字数 8752
阅读 2156
算法导论
/*-----------------------------------------------------------------
* 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 -1
typedef 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;
else
cd.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 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;
}
参考: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<i
most = l;
else
most = i;
if (r<heapsize && (e + r)->freq<(e + most)->freq)//right<most
most = 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;
else
return 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);
}