代码通过最小堆建立哈夫曼树,例如输入3 A 1 B 1 C 1,3为输入总数,1为权重。运行后发现在main函数的第二个for循环只能运行一次,第2次运行到malloc发生错误
#include <stdio.h>
#include <malloc.h>
//题目要求根据字母的使用频率对字母进行编码,利用二叉树每次选取权重最小的两个节
#define maxsize 50
typedef int Tree
typedef struct HuffmanTree *TreeNode;
//哈夫曼树:叶节点的内容按从小到大的顺序自左向右排列
struct HuffmanTree
{
char Code;//编码内容
Tree Num;//使用频率
TreeNode Left,Right;//该元素节点的左右子树
} ;
//小顶堆(每个父节点都小于其子值)
typedef struct HeapStruct *MinHeap ;
struct HeapStruct
{
TreeNode Element[maxsize];
int Size;//已插入元素个数
int Capacity;//容量
} ;
//初始化最小堆
MinHeap CreatHeap(int MinData)
{
MinHeap t=(MinHeap)malloc( sizeof(struct HeapStruct) );
t->Size=0;
t->Capacity=maxsize;
t->Element[0]=(TreeNode)malloc( sizeof(TreeNode) );//由于数组类型为结构体指针,需要手动分配空间
t->Element[0]->Num=MinData;//为了使第一个插入的元素插入到 Element[1]
return t;
}
//最小堆是否已满
int IsFull(MinHeap t)
{
if(t->Size==t->Capacity) return 1;
else return 0;
}
//向最小堆插入结点
void Insert(MinHeap H,TreeNode t)
{
int i;
if( IsFull(H) )
{
printf("FULL");
return ;//当函数类型的返回值的类型为空时,return不用返回值
}
//新插入的节点和父节点比大小
for(i=++H->Size;H->Element[i/2]->Num>t->Num;i/=2)//向零取整
H->Element[i]=H->Element[i/2];
H->Element[i]=t;
}
//最小堆是否为空
int IsEmpty(MinHeap t)
{
if(t->Size==0) return 1;
else return 0;
}
//元素出堆
TreeNode DeleteMin(MinHeap H)
{
int Parent,Child;
TreeNode MinItem,temp;//取最小堆的最小和最后一个值
if( IsEmpty(H) )
{
printf("Empty");
return NULL;//由于在哈夫曼树的结构中含有多个元素,所以返回值不能为零
}
MinItem=H->Element[1];
temp=H->Element[H->Size--];
//将根节点抽离后,后面的节点选出最小值从上至下逐层上移
for(Parent=1;Parent*2<=H->Size;Parent=Child)
{
Child=Parent*2;
if( (Child!=H->Size)&&( H->Element[Child]->Num > H->Element[Child+1]->Num) )
Child++;//指向每一个节点左右子节点的最小值
if(temp->Num<=H->Element[Child]->Num)
break;//如果最后一个节点的值小于上面的最小值,终止循环,将最后一个节点的值赋给父节点
else
H->Element[Parent]=H->Element[Child];//将上面确定的最小值赋给其父节点
}
H->Element[Parent]=temp;
return MinItem;
}
int main()
{
printf("输入编码个数\n");
int CodeSize;
scanf("%d",&CodeSize);
getchar();//用于接受上条语句的回车,避免下条scanf语句接受不到有效字符
int i;
printf("开始输入字母及其权重\n");
MinHeap H=CreatHeap(0);//建立最小堆
TreeNode t;
for(i=0;i<CodeSize;i++)
{
t=(TreeNode)malloc( sizeof(TreeNode) );
scanf("%c%d",&t->Code,&t->Num);
getchar();//用于接受输入语句的空格,避免下次scanf语句接受不到有效字符
Insert(H,t);//接收的节点插入最小堆
}
for(i=1;i<CodeSize;i++)//创建最小堆
{
t=(TreeNode)malloc( sizeof(TreeNode) );
t->Left=DeleteMin(H);
t->Right=DeleteMin(H);
t->Num= t->Left->Num + t->Right->Num ;//权重最小的两个节点组成一个新的节点
t->Code=' ';
Insert(H,t);//新节点插入最小堆
}
t=DeleteMin(H);//头结点
return 0;
}