基础实验4-2.7 修理牧场

题目

农夫要修理牧场的一段栅栏,他测量了栅栏,发现需要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);
}
  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值