哈夫曼樹是一棵怎樣的樹呢,假如我們給出一堆數據"1,2,3,4,5"(數據對應的數字還代表這個數字出現的次數)來構建一顆二叉樹,怎樣一顆二叉樹才能使我們的查找效率率最高呢,那就是哈夫曼樹了,在前面的“1,2,3,4,5”中,我們先選出兩個最小的,那就是“1,2”,然后1和2構建一個結點。該結點為3,左右子樹為“1,2”,把該結點3放進去后,現在的數據就是“3,3,4,5”,然后我們再從這里面選出兩個最小的--"3,3",加起來就是6,放進去后就是“6,4,5”,依次循環。
我們可以利用堆來實現,我們先把數據放入一個最小堆,然后建立一顆樹結點,該樹的左子樹對於第一個出堆的結點數據,右子樹等於第二個出堆的,該結點的值就為左右子樹的值加起來,然后再放進堆,然后又從堆里面選出兩個最小的值的結點為左右子樹,依次這樣,直到最后一個結點放進去,然后出堆。這樣一顆哈夫曼樹就構建成功了,為了方便我們看清楚它的樣子,也為了方便我加強前面隊列的印象,我就用了層次遍歷把這個哈夫曼樹遍歷了一遍,層次遍歷會運用到隊列的思想,先將第根結點進隊,然后輸出,再將他的左右子樹進隊,然后出隊,(反正就是每出一次隊,我們就要將這個結點的左右子樹存入進去)。這樣直到隊列為空。
#include <stdio.h>
#include <stdlib.h>
typedef struct huf {
int weight;
struct huf *left,*right;
}Huf,*HufTree;//哈夫曼樹的結構體。
typedef struct Heap {
Huf *data;
int size;
int maxsize;
}Heap,*HNode;//堆的結構體。
typedef struct Queue {
Huf *data;
int front;
int rear;
int maxsize;
}Queue,*QNode;//隊列的結構體。
void InitHeap (HNode *H);//初始化堆。
void InsertToHeap (HNode H,Huf *T);//插入堆。
HufTree DeleteHeap (HNode H);//出堆。
int IsFullHeap (HNode H);//判斷堆是否為滿。
int IsEmptyHeap (HNode H);//判斷堆是否為空。
HufTree CreateHufTree (int n);//創建一個n個數據的一個哈夫曼樹。
void InitQueue (QNode *Q);//初始化隊列。
void InsertQueue (QNode Q,Huf *T);//進隊。
HufTree DeleteQueue (QNode Q);//出隊。
int IsFullQueue (QNode Q);//判斷隊是否為滿。
int IsEmptyQueue (QNode Q);//判斷隊是否為空。
void LevelTree (HufTree T);//層次遍歷樹。
int main ()
{
int n;
scanf("%d",&n);
HufTree T = CreateHufTree (n);//創建一顆樹。
LevelTree(T);//層次遍歷該樹。
return 0;
}
void LevelTree (HufTree T)
{
QNode Q;
InitQueue (&Q);
InsertQueue(Q,T);
while (!IsEmptyQueue(Q)) {
HufTree temp;
temp = DeleteQueue(Q);
printf("%d ",temp->weight);
if(temp->left) InsertQueue(Q,temp->left);
if(temp->right) InsertQueue(Q,temp->right);
}
}
void InitQueue (QNode *Q)
{
*Q = malloc(sizeof(Queue));
(*Q)->maxsize = 10;
(*Q)->data = (Huf*)malloc(sizeof(Huf)*(*Q)->maxsize);
(*Q)->front= (*Q)->rear = 0;
}
int IsFullQueue (QNode Q)
{
return (Q-> rear + 1) % (Q->maxsize) == Q->front;
}
int IsEmptyQueue (QNode Q)
{
return Q->rear == Q->front;
}
void InsertQueue (QNode Q,Huf *T)
{
if(IsFullQueue (Q)) {
printf("The queue is full!\n");
return;
}
Q->data[Q->rear] = *T;
Q->rear = (Q->rear + 1) % (Q->maxsize);
}
HufTree DeleteQueue (QNode Q)
{
if (IsEmptyQueue(Q)) {
printf("The queue is empty!\n");
return NULL;
}
Huf *temp;
temp = malloc(sizeof(Huf));
*temp = Q->data[Q->front];
Q->front = (Q->front+1) % (Q->maxsize);
return temp;
}
HufTree CreateHufTree (int n)
{
HNode H;
InitHeap(&H);
int x;
for(int i = 1; i <= n;i++) {
printf("x is :");
scanf("%d",&x);
Huf *temp = malloc(sizeof(Huf));
temp->weight = x;
temp->left = temp->right = NULL;
InsertToHeap(H,temp);
}
HufTree Tree;
for(int i = 1; i < n;i++) {
Tree = malloc(sizeof(Huf));
Tree->left = DeleteHeap(H);
Tree->right = DeleteHeap(H);
Tree->weight = Tree->left->weight + Tree->right->weight;
InsertToHeap(H,Tree);
}
Tree = DeleteHeap(H);
return Tree;
}
void InitHeap (HNode *H)
{
(*H) = (HNode) malloc (sizeof(Heap));
(*H)->data = (Huf*)malloc(sizeof(Huf)*10);
(*H)->size = 0;
(*H)->maxsize = 10;
(*H)->data[0].weight = -1;
}
int IsFullHeap (HNode H)
{
return (H->size == H->maxsize - 1);
}
int IsEmptyHeap (HNode H)
{
return (H->size == 0);
}
void InsertToHeap (HNode H, Huf *T)
{
if (IsFullHeap(H)) {
printf("The heap is full!\n");
return ;
}
H->size++;
int i = H->size;
while (H->data[i/2].weight > T->weight) {
H->data[i] = H->data[i/2];
i = i /2;
}
H->data[i] = *T;
}
HufTree DeleteHeap (HNode H)
{
if (IsEmptyHeap(H)) {
printf("The heap is empty!\n");
return NULL;
}
Huf *Min;
Min = malloc(sizeof(Huf));
*Min = H->data[1];
Huf *temp;
temp = malloc(sizeof(Huf));
*temp = H->data[H->size];
H->size--;
int parent,child;
for(parent = 1;parent * 2 <= H->size;parent = child) {
child = parent * 2;
if (child != H->size && H->data[child].weight > H->data[child+1].weight) {
child++;
}
if (temp->weight <= H->data[child].weight) break;
else H->data[parent] = H->data[child];
}
H->data[parent] = *temp;
return Min;
}
代碼就如上,若讀者有任何不懂,可以留言,期待下一次!