哈夫曼树的构建及遍历

哈夫曼树是一棵怎样的树呢,假如我们给出一堆数据"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;
}

代码就如上,若读者有任何不懂,可以留言,期待下一次!

posted @ 2020-10-28 19:26  lookfd  阅读(311)  评论(0编辑  收藏