题目
农夫要修理牧场的一段栅栏,他测量了栅栏,发现需要N块木头,每块木头长度为整数L i
个长度单位,于是他购买了一条很长的、能锯成N块的木头,即该木头的长度是L i的总和。但是农夫自己没有锯子,请人锯木的酬金跟这段木头的长度成正比。为简单起见,不妨就设酬金等于所锯木头的长度。例如,要将长度为20的木头锯成长度为8、7和5的三段,第一次锯木头花费20,将木头锯成12和8;第二次锯木头花费12,将长度为12的木头锯成7和5,总花费为32。如果第一次将木头锯成15和5,则第二次锯木头花费15,总花费为35(大于32)。
请编写程序帮助农夫计算将木头锯成N块的最少花费
分析
*通过读题可知,此题大意就是要创建一个Huffman树,然后求它的最短带权路径长度(WPL)。
思路
本题实验思路其实很简单,就是循环找数组中两个最小的点创建树,取到最小节点后要将其置空(就是以后不再扫描此节点,表示数组此处已经为空),节点数组处是否为空我用了一个flag[ ]数组进行标记,如果为1则表示节点数组处此值可用,反之则已经为空。
代码
#include<stdio.h>
#include<stdlib.h>
#define N 100
#define Max 51
typedef struct Tree{
int data;
struct Tree *lchild,*rchild;
}*BiTree,tree;
BiTree CreatHuffman();
int findMin();
void PreSearch(BiTree TT,int level);
BiTree T[N],root;
int n,flag[N],count=0;
void main(){
int i;
BiTree s;
scanf("%d",&n);
for(i=0;i<n;i++){
s=(BiTree)malloc(sizeof(tree));
scanf("%d",& s->data);
s->lchild=NULL;
s->rchild=NULL;
T[i]=s;
flag[i]=1;
}
root=CreatHuffman();
printf("HuffmanTree PreSearch\n");
PreSearch(root,0);
printf("\n");
printf("总花费=%d ",count);
system("pause");
}
BiTree CreatHuffman(){//创建一棵Huffman树
int min1,min2,i;
BiTree TT;
while(1){//循环找到数组中最小的两个点
min1=findMin();
min2=findMin();
if(min2==-1){//用于判断数组中是不是只剩余一个节点可用,若是则此节点就是根节点
return T[min1];
}
TT=(BiTree)malloc(sizeof(tree)); //以最小两节点为叶子节点共同构建一个父节点,创建一棵树
TT->data=T[min1]->data+T[min2]->data;
TT->lchild=T[min1];
TT->rchild=T[min2];
T[min1]=TT;
flag[min1]=1;//插入一个数后,此处别忘了置1,代表新加入节点参与最小值的检索
}
return NULL;
}
int findMin(){
int i,min=Max,index=-1;
for(i=0;i<n;i++){
if(flag[i]==1 && T[i]->data<min){
min=T[i]->data;
index=i;
}
}
if(index != -1){
flag[index]=0;
return index;
}else
return -1;
}
void PreSearch(BiTree TT,int level){
if(!TT)
return;
printf("%d ",TT->data);
if(!TT->lchild && !TT->rchild)
count+=TT->data * level;
PreSearch(TT->lchild,level+1);
PreSearch(TT->rchild,level+1);
}