数据结构与算法—复习:最优二叉树 哈夫曼算法
手画很简单,代码则需要多考虑
/**
* 程序说明:复习 最优二叉树(哈夫曼树) 哈夫曼算法
*/
#include <stdio.h>
#include <malloc.h>
/**
* 定义一个非常大的整数
*/
int MAXINT = 999999999;
/**
* 哈夫曼树 结点结构
*/
struct HtNode{
int ww; //该点到带权外部路径长度的值
int parent,llink,rlink; //父结点、左子树、右子树
};
/**
* 哈夫曼树 结构
*/
struct HtTree{
int m; //外部节点个数
int root; //哈夫曼树根在数组中的下标
struct HtNode* ht; //存放 2m - 1个 结点的数组
};
typedef struct HtTree* PHtTree;
PHtTree huffman(int m,int* w){
PHtTree pht = (PHtTree)malloc(sizeof(struct HtTree));
int i, // i,j 为循环所用
j,
x1, // x1 存储 最小权无父结点的结点下标
x2, // x2 存储 次最小权无父结点的结点下标
m1, // m1 存储 最小权无父结点的结点的带权外部路径权值
m2; // m2 存储 次最小权无父结点的结点的带权外部路径权值
if(pht == NULL){
printf("哈夫曼树分配空间超出范围\n");
return pht;
}
pht->ht = (struct HtNode*)malloc(sizeof(struct HtNode) * (2*m - 1));
if(pht->ht == NULL){
printf("哈夫曼树结点分配空间超出范围\n");
return pht;
}
//对整个哈夫曼数组初始化
for (i = 0; i < 2*m - 1; ++i) {
//所给权值都是扩充结点,一开始的左右子树和父结点都是不存在的
pht->ht[i].llink = -1; pht->ht[i].rlink = -1; pht->ht[i].parent = -1;
//当在m个权值结点以内时,此时的权值,就是所给的权值
if(i < m){
pht->ht[i].ww = w[i];
}else{ //在m个结点以外的空间,是还没有生成的父结点,他们的权值不确定,置为空
pht->ht[i].ww = -1;
}
}
//每循环一次,构造一个内部结点
for (i = 0; i < m-1; ++i) {
m1 = m2 = MAXINT;
x1 = -1; x2 = -1;
//找两个最小权的无父结点的结点
for (j = 0; j < m + i; j++){
if(pht->ht[j].ww < m1 && pht->ht[j].parent == -1){
//用x1 存放最小权无父结点的结点下标
//下面的前两句话的作用是,如果发现了更小的结点,则把当前的第一结点记作次小结点
m2 = m1; x2 = x1; m1 = pht->ht[j].ww; x1 = j;
}
else if(pht->ht[j].ww < m2 && pht->ht[j].parent == -1){
//用x2 存放次最小权无父结点的结点下标
m2 = pht->ht[j].ww; x2 = j;
}
//构造内部结点
pht->ht[x1].parent = m + i; pht->ht[x2].parent = m + i;
pht->ht[m+i].ww = m1 + m2; pht->ht[m+i].llink = x1; pht->ht[m+i].rlink = x2;
}
pht->root = 2*m-2;
return pht;
}
}