首页 > 其他分享 >二叉树和哈夫曼树

二叉树和哈夫曼树

时间:2023-12-28 21:00:14浏览次数:28  
标签:遍历 return 哈夫曼 int cin ch 二叉树 节点

Entropy(poj 1521)


题目大意

对字符串分别用ASCII编码(每个字符8b)和哈夫曼编码,输出编码前、后的长度并计算压缩比。
解题思路

本题不要求求出编码,只需计算长度,考虑记录字符出现频次,用优先队列记录最小的两个频次,直接计算长度。

未知的代码
#include<bits/stdc++.h>
using namespace std;
int main(){
	priority_queue<int,vector<int>,greater<int>>q;
	string s;
	while(getline(cin,s)&&s!="END"){
		sort(s.begin(),s.end());
		int cnt=1;
		int len=s.size();
		for(int i=1;i<=len;i++){
			if(s[i]!=s[i-1]){
				q.push(cnt);
				cnt=1;
			}else cnt++;
		}
		int ans=0;
		if(q.size()==1)ans=len;
		while(q.size()>1){
			int a=q.top();
			q.pop();
			int b=q.top();
			q.pop();
			q.push(a+b);
			ans+=(a+b);
		}
		q.pop();
		cout<<len*8<<" "<<ans<<" "<<len*8.0/ans<<endl;
	}
	return 0;
}

Safe Or Unsafe(hdu P2527)


题目大意

对字符串按哈夫曼编码统计总权值即频次,判断是否小于等于给定值。这道题与上一题基本相同。


解题思路

对字符串排序,统计字符串频次,将其作为节点权值,利用优先队列计算总和。

未知的代码
#include<bits/stdc++.h>
using namespace std;
int main(){
	priority_queue<int,vector<int>,greater<int>>q;
	int n,t;
	string s;
	cin>>n;
	while(n--){
		cin>>t>>s;
		sort(s.begin(),s.end());
		int cnt=1;
		int len=s.size();
		for(int i=1;i<=len;i++){
			if(s[i]!=s[i-1]){
				q.push(cnt);
				cnt=1;
			}else cnt++;
		}
		int ans=0;
		if(q.size()==1)ans=len;		//只有一种字符,长度即为频次
		while(q.size()>1){
			int a=q.top();
			q.pop();
			int b=q.top();
			q.pop();
			q.push(a+b);
			ans+=(a+b);
		}
		q.pop();
		if(ans<=t)puts("yes");
		else puts("no");
	}
	return 0;
}

FBI树(洛谷P1087)


题目大意

根据给出的01串建树,输出相应后续遍历字符序列。


解题思路

依据题目意思,采用先序遍历的方式建树,即根左右,对01串的操作类似于二分。递归函数先对左右建树并输出节点字符,最后输出根节点字符,对应后序遍历。

未知的代码
#include<bits/stdc++.h>
using namespace std;
int main(){
	int n;
	cin>>n;
	string s;
	cin>>s;
	function<void(int,int)>build=[&](int l,int r){
		if(l<r){
			int mid=(l+r)>>1;
			build(l,mid);
			build(mid+1,r);
		}
		int a=0,b=0;
		for(int i=l;i<=r;i++){
			if(s[i]=='0')a++;
			else b++;
		}
		if(a&b)cout<<"F";
		else if(a)cout<<"B";
		else cout<<"I";
	};
	build(0,(1<<n)-1);
	return 0;
}

求先序排列(洛谷P1030)


题目大意

根据二叉树的中序与后续排列求前序排列。


解题思路

中序遍历左根右,后序遍历左右根,依据上述特点,先取后序排列最后一个字符即为根且易知为树的整个树的根,然后在中序排列里查找这个根,并将其分为左右两个子树序列,那么对应的后序排列也可分为两个子树序列,重复上述操作输出所有节点即为先序遍历,按照根左右输出。

未知的代码
#include<bits/stdc++.h>
using namespace std;
int main(){
	string instr,poststr;
	cin>>instr>>poststr;
	function<void(string,string)>build=[&](string instr,string poststr){
		if(instr.size()<=0)return;
		cout<<poststr.back();
		int mid=instr.find(poststr.back());
		build(instr.substr(0,mid),poststr.substr(0,mid));
		build(instr.substr(mid+1),poststr.substr(mid,instr.size()-mid-1));  //注意后序排列
	};
	build(instr,poststr);
	return 0;
}

新二叉树(洛谷P1305)


题目大意

输入二叉树每个节点的根左右字符串,求先序序列。


解题思路

解法1:根据条件建树,并递归输出先序序列。
解法2:根据先序序列性质,根据给出的根左右单节点字符序进行拼接,'*'可以不做处理,输出时判断跳过即可。

建树解法
#include<bits/stdc++.h>
using namespace std;
struct BTree{
	char ch;
	BTree*l,*r;
	BTree(){}
	BTree(char ch):ch(ch),l(nullptr),r(nullptr){}
}tree;
BTree*build(char ch){
	if(ch=='*')return nullptr;
	return new BTree(ch);
}
BTree*find_node(char ch,BTree*t){
	if(t->ch==ch)return t;
	BTree*ans=nullptr;
	if(t->l)ans=find_node(ch,t->l);
	if(ans!=nullptr)return ans;
	if(t->r)ans=find_node(ch,t->r);
	return ans;
}
void prevorder(BTree*t){
	cout<<t->ch;
	if(t->l)prevorder(t->l);
	if(t->r)prevorder(t->r);
}
int main(){
	int n;
	cin>>n;
	char root,l,r;
	cin>>root>>l>>r;
	tree.ch=root;
	tree.l=build(l);
	tree.r=build(r);
	for(int i=1;i<n;i++){
		cin>>root>>l>>r;
		BTree*node=find_node(root,&tree);
		node->l=build(l);
		node->r=build(r);
	}
	prevorder(&tree);
	return 0;
}
搜索解法
#include<bits/stdc++.h>
using namespace std;
int main(){
	int n;
	string s;
	cin>>n>>s;
	for(int i=1;i<n;i++){
		string ret;
		cin>>ret;
		int pos=s.find(ret[0]);
		s.erase(pos,1);
		s.insert(pos,ret);	//直接拼接
	}
	for(auto&it:s){
		if(it!='*')cout<<it;
	}
	return 0;
}

遍历问题(洛谷P1229)


题目大意

给定二叉树前序遍历和后序遍历结果,求中序遍历种数。


解题思路

依据题意可知,当节点只存在一个儿子时,它既可以做左子树又可以做右子树,会在已知前、后序的条件下存在不同的中序遍历结果,那么求有多少个节点只有一个儿子,然后依据乘法原理不断乘2即可。如果该节点有一个子节点,那么它在前序遍历序列中的下一个节点一定是它的子节点,同时在后序遍历序列中的位置一定是在它的前一个节点的位置。

未知的代码
#include<bits/stdc++.h>
using namespace std;
int main(){
	int ans=1;
	string s1,s2;
	cin>>s1>>s2;
	int len=s1.size();
	for(int i=0;i<len-1;i++){
		for(int j=1;j<len;j++){
			if(s1[i]==s2[j]&&s1[i+1]==s2[j-1])ans<<=1;
		}
	}
	cout<<ans<<endl;
	return 0;
}

对称二叉树(洛谷P5018)


题目大意

根据给定信息的二叉树,找出最大对称(在结构和权值上均对称)二叉树的节点数。


解题思路

创建递归函数,递归遍历左右子树,判断是否相等。记录节点数最值。

未知的代码
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=1e6+5;
struct node{
	int l,r,v;
}a[N];
bool dfs(int x,int y){
	if(x==-1&&y==-1)return true;
	if(x==-1||y==-1)return false;
	if(a[x].v!=a[y].v)return false;
	return dfs(a[x].l,a[y].r)&&dfs(a[x].r,a[y].l);
}
int count(int x){ //递归求节点数
	return x==-1?0:count(a[x].l)+count(a[x].r)+1;
}
signed main(){
	int n,ans=0;
	cin>>n;
	for(int i=1;i<=n;i++)cin>>a[i].v;
	for(int i=1;i<=n;i++)cin>>a[i].l>>a[i].r;
	for(int i=1;i<=n;i++){
		if(dfs(i,i))ans=max(ans,count(i));
	}
	cout<<ans;
	return 0;
}

复读(洛谷P5597)


题目大意

解题思路


荷马史诗(洛谷P2168)


题目大意

解题思路

标签:遍历,return,哈夫曼,int,cin,ch,二叉树,节点
From: https://www.cnblogs.com/eternal-world/p/17931532.html

相关文章

  • 代码随想录算法训练营第十六天 |104.二叉树的最大深度,559.n叉树的最大深度,111.二叉树
    一、104.二叉树的最大深度题目链接:LeetCode104.二叉树的最大深度学习:思路:分别求左子树和右子树的高度,返回给根结点,加1之后是根结点的深度,这是后序遍历的思路二、559.n叉树的最大深度题目链接:LeetCode559.N叉树的最大深度学习前:思路:后序遍历。分别所有孩子结点的深......
  • 114. 二叉树展开为链表
    给你二叉树的根结点 root ,请你将它展开为一个单链表:展开后的单链表应该同样使用 TreeNode ,其中 right 子指针指向链表中下一个结点,而左子指针始终为 null 。展开后的单链表应该与二叉树 先序遍历 顺序相同。 示例1:输入:root=[1,2,5,3,4,null,6]输出:[1,null,2,null,3,......
  • 代码随想录算法训练营第十五天 | 层序遍历 ,226.翻转二叉树,101.对称二叉树
    一、二叉树层序遍历题目链接:LeetCode102.二叉树的层序遍历LeetCode107.二叉树的层序遍历IILeetCode199.二叉树的右视图LeetCode637.二叉树的层平均值LeetCode429.N叉树的层序遍历LeetCode515.在每个树行中找最大值LeetCode116.填充每个节点的下一个右侧节......
  • [LeetCode Hot 100] LeetCode102. 二叉树的层序遍历
    题目描述思路方法一:递归/***Definitionforabinarytreenode.*publicclassTreeNode{*intval;*TreeNodeleft;*TreeNoderight;*TreeNode(){}*TreeNode(intval){this.val=val;}*TreeNode(intval,TreeNodelef......
  • [LeetCode Hot 100] LeetCode543. 二叉树的直径
    题目描述思路所谓二叉树的直径,就是左右子树的最大深度之和。方法一:/***Definitionforabinarytreenode.*publicclassTreeNode{*intval;*TreeNodeleft;*TreeNoderight;*TreeNode(){}*TreeNode(intval){this.val=va......
  • [LeetCode Hot 100] LeetCode104. 二叉树的最大深度
    题目描述思路熟练掌握二叉树的遍历算法方法一:层序遍历(迭代)+计数/***Definitionforabinarytreenode.*publicclassTreeNode{*intval;*TreeNodeleft;*TreeNoderight;*TreeNode(){}*TreeNode(intval){this.val=val;......
  • [LeetCode Hot 100] LeetCode110. 平衡二叉树
    题目描述思路LeetCode104.二叉树的最大深度变种方法一:后序遍历(递归、dfs)/***Definitionforabinarytreenode.*publicclassTreeNode{*intval;*TreeNodeleft;*TreeNoderight;*TreeNode(){}*TreeNode(intval){this.......
  • [LeetCode Hot 100] LeetCode111. 二叉树的最小深度
    题目描述思路二叉树的最小深度就是第一个叶子节点所在的层数方法一:前序遍历(递归、dfs)/***Definitionforabinarytreenode.*publicclassTreeNode{*intval;*TreeNodeleft;*TreeNoderight;*TreeNode(){}*TreeNode(intva......
  • [LeetCode Hot 100] LeetCode94. 二叉树的中序遍历
    题目描述思路熟练掌握迭代和递归的代码。递归:额外写一个函数voidinOrder(TreeNodenode,Listres)迭代:令cur=root,一直往左子树找,找到最后一个左子节点,当cur为空,就开始处理栈顶元素(将栈顶元素加入结果集),随后将cur设置为右子节点,继续执行以上操作。方法一:递归/***......
  • [LeetCode Hot 100] LeetCode144. 二叉树的前序遍历
    题目描述思路熟练掌握迭代和递归的代码。递归代码:额外写一个函数voidpreOrder(TreeNodenode,Listres)迭代代码:会用到数据结构——栈。先入栈当前节点的右子节点,再入栈左子节点。方法一:递归/***Definitionforabinarytreenode.*publicclassTreeNode{*......