05-树9 Huffman Codes

题意:给出字符和频率,检查学生的答案是不是最优解

输入输出:

 主要思路:读入第一行数据,建立哈夫曼树,计算最优编码长度,然后读入学生数据,先计算编码长度,再检查是否符合前缀码。

但在视频中给出的建哈夫曼树的方法(如下)

使用了堆,在前面堆的章节中,元素使用数组存储,但这里函数insert和delete都返回指针,所以建立最小堆要使用结构体指针数组 

堆的插入和删除如下(dt[] 是结构体指针数组,是最小堆)

 然后按照视频的方法建造树

 完整代码:

#include<bits/stdc++.h>
using namespace std;
int n,m,heapsize;
map<char,int>mm;
bool f2;
struct data{
	char a;
	string b;
};
data d1[64];//d1是读入的学生的数据 
typedef struct node* ht;
struct node{
	char s; 
	int w;
	ht l,r;
};
ht dt[64],d2[64];//使用结构体指针数组建造最小堆 ,d2是读入数据,dt是堆 
void insert(ht t,int i){
	for(;i>1&&dt[i/2]->w  > t->w   ;i/=2){
		dt[i] = dt[i/2];
	}
	dt[i] = t;
}
ht d(){ //删除堆元素 ,返回所删除的指针 
	ht t = dt[1],temp = dt[heapsize--];
	int p,c;
	for(p = 1;p*2<=heapsize;p = c){
		c = p*2;
		if((c!=heapsize) && (dt[c]->w >dt[c+1]->w)){
			c++;
		}
		if(temp->w <=dt[c]->w )break;
		else{
			dt[p] = dt[c];
		}
	}
	dt[p] = temp;
	return t;
}
ht h(){//构建哈夫曼树 
	ht T;
	for(int i = 1;i<n;i++){
		T = (ht)malloc( sizeof( struct node ) );
		T->l = d();
		T->r = d();
		T->w = T->l->w +T->r->w ;
		insert(T,++heapsize);
	}
	T = d();
	return T;
}
int getsum(ht H,int i){//i是层数,从0开始 
	if(!H->l &&!H->r ){
		return i*H->w ;
	}else{
		return getsum(H->l ,i+1)+getsum(H->r ,i+1);
	}
}
void check(){//根据视频方法,建树判断 
	ht head,t;
	t = (ht)malloc(sizeof(struct node));
	t->w = 0;
	t->l = t->r  = NULL;
	head = t;//保存树根 
	for(int i = 1;i<=n && f2;i++){
		t = head;//指向树根 
		string s = d1[i].b ;
		for(int j = 0;j<s.size()-1;j++){
			if(t->w ){//非前缀码 
				f2 = false;
				break;
			}
			if(s[j]=='0'){
				if(!t->l ){
					ht tt;
					tt = (ht)malloc(sizeof(struct node));
					tt->l = tt->r = NULL;
					tt->w =0;
					t->l = tt;
				}
				t = t->l ;
			}
			if(s[j]=='1'){
				if(!t->r ){
					ht tt;
					tt = (ht)malloc(sizeof(struct node));
					tt->r = tt->l =NULL;
					tt->w = 0;
					t->r = tt;
				}
				t  = t->r ;
			}
		}//后面进行叶子节点的判断 
		if(s[s.size()-1]=='0'){
			if(t->l ){
				f2 = false;
			}else{
				ht tt;
				tt = (ht)malloc(sizeof(struct node));
				tt->l = tt->r = NULL;
				tt->w = 1;
				t->l = tt;
			}
		}
		if(s[s.size()-1]=='1'){
			if(t->r ){
				f2 = false;
			}else{
				ht tt;
				tt = (ht)malloc(sizeof(struct node));
				tt->l = tt->r = NULL;
				tt->w = 1;
				t->r = tt;
			}
		}
	}
}
int main(){
	cin>>n;
	for(int i = 1;i<=n;i++){
		char k;
		int l;
		cin>>k>>l;
		mm[k] = l;
		d2[i] = (ht)malloc(sizeof(struct node));
		dt[i] = (ht)malloc(sizeof(struct node));
		d2[i]->s  = k;
		d2[i]->w  = l;
		d2[i]->r = d2[i]->l =NULL;
		insert(d2[i],i);
	}
	heapsize = n;
	ht H = h();
	int sum = 0;
	sum = getsum(H,0);//计算最优编码长度 
	cin>>m;
	bool f1 = false;//判断是否输出换行 
	while(m--){
		f2 = true;
		int sumstu = 0;
		for(int i = 1;i<=n;i++){
			char k;
			string l;
			cin>>k>>l;
			d1[i].a = k;
			d1[i].b  = l;
			sumstu+=l.length()*mm[k];
		}
		if(sumstu != sum){
			f2 = false;
		}
		if(f2){1
			check();
		}
		if(f1){
			cout<<endl;
		}else f1 = true;
		if(f2)cout<<"Yes";
		else cout<<"No";
	}
    return 0;
}

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值