树和图的基础知识(洛谷)

目录

[模板] 树的深度1

[模板] 树的深度2

【深基16.例3】二叉树深度

新二叉树

[模板] 二叉树的先序遍历

 [模板] 二叉树的中序遍历

[模板] 二叉树的后序遍历

[NOIP2001 普及组] 求先序排列

美国血统 American Heritage

 [NOIP2004 普及组] FBI 树

图的遍历


关于树的基本知识:(331条消息) 数据结构:树(Tree)【详解】_UniqueUnit的博客-CSDN博客_数据结构 树

[模板] 树的深度1

邻接表存树,然后dfs或bfs遍历。(链表

代码1:dfs

#include<bits/stdc++.h>
using namespace std;
const int N = 5010;
int n;
int h[N], e[N], ne[N], idx;
int d[N],q[N];

void add(int a, int b)
{
    e[idx] = b, ne[idx] = h[a], h[a] = idx ++ ;
}

int dfs(int t,int u)
{
    d[t] = u;
    for(int i = h[t]; i != -1; i = ne[i])
        dfs(e[i],u + 1);
}

int main()
{
    cin>>n;
    memset(h, -1, sizeof h);

    for (int i = 2; i <=n; i ++ )
    {
        int a;
        cin>>a;
        add(a, i);
    }
    dfs(1,1);
    for(int i=1;i<=n;i++)
    {
        cout<<d[i]<<' ';
    }

    return 0;
}

代码2:bfs(和搜索与图论的图中点的层次

#include<bits/stdc++.h>
using namespace std;
const int N = 5010;
int n;
int h[N], e[N], ne[N], idx;
int d[N],q[N];

void add(int a, int b)
{
    e[idx] = b, ne[idx] = h[a], h[a] = idx ++ ;
}

int bfs(int x)
{
    int hh=0,tt=0;
    q[0]=1;
    memset(d, 0, sizeof d);
    d[1] = 1;

    while (hh<=tt)
    {
        int t = q[hh++];
        for (int i = h[t]; i != -1; i = ne[i])
        {
            int j = e[i];
            if (d[j]==0)
            {
                d[j] = d[t] + 1;
                q[++tt]=j;
            }
        }
    }
    return d[x];
}

int main()
{
    cin>>n;
    memset(h, -1, sizeof h);

    for (int i = 2; i <=n; i ++ )
    {
        int a;
        cin>>a;
        add(a, i);
    }
    for(int i=1;i<=n;i++)
    {
        cout<<bfs(i)<<' ';
    }

    return 0;
}

[模板] 树的深度2

链式前向星存树

代码:

#include<bits/stdc++.h>
using namespace std;
const int N=5010;
int n;
int d[N];
int head[N],cnt=0;
struct node{
    int to,next;
}edge[N*2];

inline void add(int x,int y){
    edge[cnt].to=y;
    edge[cnt].next=head[x];
    head[x]=cnt++;
}

void dfs(int u,int t){
     d[u]=t;
    for(int i=head[u];~i;i=edge[i].next){
        int cld=edge[i].to;
        dfs(cld,t+1);

    }
}
int main(){
    cin>>n;
    memset(head,-1,4*N);

    for(int i=0;i<n-1;i++)
    {
        int x,y;
        cin>>x>>y;
        add(y,x);
    }
    dfs(1,1);
    for(int i=1;i<=n;i++)
    {
        cout<<d[i]<<' ';
    }

    return 0;
}

【深基16.例3】二叉树深度

用结构体存储左右儿子,dfs深度搜索遍历

代码:

#include<bits/stdc++.h>
using namespace std;
int res,n;
struct node
{
	int l,r;
}a[1001000];//记录每个节点的左右节点

void dfs(int root,int step)
{
    //cout<<"root="<<root<<' '<<"step="<<step<<' '<<"a[root].l="<<a[root].l<<' '<<endl;//测试
	if(root==0) return;//如果该节点为0(即它的爸爸没有这个儿子),返回
	res=max(res,step);//记录最大值
	dfs(a[root].l,step+1);//搜索它的左儿子
	dfs(a[root].r,step+1);//搜索它的右儿子
}
int main()
{
	cin>>n;
	for(int i=1;i<=n;i++)
		cin>>a[i].l>>a[i].r;//输入该节点的左节点和右节点

	dfs(1,1);//从1号节点,深度为1开始搜索
	cout<<res;//输出最大值
	return 0;
}

新二叉树

输出前序遍历

代码1:和上一题做法一样

#include<bits/stdc++.h>
using namespace std;
char root,ch;
struct nade
{
	char l,r;
}a[130];

void dfs(char x)
{
	if(x=='*') return;
	cout<<x;
	dfs(a[x].l);//找到他的左孩子,继续往下探(如果左孩子是*的话,会返回的)
	dfs(a[x].r);
}
int main()
{
	int n;
	cin>>n;
	cin>>root>>a[root].l>>a[root].r;//输入第一个字母,第一个字母比较特殊,所以单独输入
	for(int i=2;i<=n;i++) cin>>ch>>a[ch].l>>a[ch].r;
	dfs(root);
	return 0;
}

代码2:利用ASCII进行存储

#include<bits/stdc++.h>
using namespace std;
int n;
struct node//定义二叉树结构体
{
	string data;//自身
	int l,r;//左孩子和右孩子的数组下表。

}t[1010];

void dfs(int k)//先序遍历
{
	cout<<t[k].data;//遍历根节点
	if(t[k].l!=0)//如果有左孩子的话,遍历左孩子(未赋值默认为0)
		dfs(t[k].l);

	if(t[k].r!=0)//如果有右孩子的话,遍历右孩子
		dfs(t[k].r);
}
int main()
{
	cin>>n;
	int root;//根节点的下标
	for(int i=1;i<=n;i++)
	{
		char a,b,c;
		cin>>a>>b>>c;
		if(i==1)//第一个输入的是根节点,储存其下标,为其在26个字母中的位置
			root=a-'a'+1;
		t[a-'a'+1].data=a;//储存
		//下面为确定父子关系
        if(b!='*')//如果有左儿子
		{
			t[b-'a'+1].data=b;//存储左儿子
			t[a-'a'+1].l=b-'a'+1;//记录左儿子的下标
		}
		if(c!='*')//同上,记录右儿子
		{
			t[c-'a'+1].data=c;
			t[a-'a'+1].r=c-'a'+1;
		}
	}
	dfs(root);//从根节点开始先序遍历
	return 0;
}

代码3:纯dfs(用二维数组进行存储)

#include<bits/stdc++.h>
using namespace std;
int n;
char a[30][3];
void f(char x)
{
    if(x=='*') return ;
    cout<<x;
    for(int i=1;i<=n;i++)
        if(a[i][0]==x)
        {
            f(a[i][1]);
            f(a[i][2]);
        }
}
int main()
{
    cin>>n;
    for(int i=1;i<=n;i++)
        cin>>a[i][0]>>a[i][1]>>a[i][2];
    f(a[1][0]);
    return 0;
}

[模板] 二叉树的先序遍历

代码:和上一题的代码1一样

#include<bits/stdc++.h>
using namespace std;
int root,m;
struct node
{
	int l,r;
}a[5010];

void dfs(int x)
{
	if(x==0) return;
	cout<<x<<' ';
	dfs(a[x].l);
	dfs(a[x].r);

}
int main()
{
	int n,p;
	cin>>n>>p;

	for(int i=1;i<=n;i++)
    {
        cin>>m>>a[m].l>>a[m].r;
    }
	dfs(p);
	return 0;
}

 [模板] 二叉树的中序遍历

代码:和上一题的代码1一样

#include<bits/stdc++.h>
using namespace std;
int root,m;
struct node
{
	int l,r;
}a[5010];

void dfs(int x)
{
	if(x==0) return;
	//cout<<x<<' ';
	dfs(a[x].l);
	cout<<x<<' ';
	dfs(a[x].r);

}
int main()
{
	int n,p;
	cin>>n>>p;
    int root;
	for(int i=1;i<=n;i++)
    {
        cin>>m>>a[m].l>>a[m].r;
    }
	dfs(p);
	return 0;
}

[模板] 二叉树的后序遍历

代码:和上一题的代码1一样

#include<bits/stdc++.h>
using namespace std;
int root,m;
struct node
{
	int l,r;
}a[5010];

void dfs(int x)
{
	if(x==0) return;
	//cout<<x<<' ';
	dfs(a[x].l);
	dfs(a[x].r);
    cout<<x<<' ';
}
int main()
{
	int n,p;
	cin>>n>>p;
    int root;
	for(int i=1;i<=n;i++)
    {
        cin>>m>>a[m].l>>a[m].r;
    }
	dfs(p);
	return 0;
}

[NOIP2001 普及组] 求先序排列

题解:看博客题解 P1030 【求先序排列】 - sunyufei 的博客 - 洛谷博客 (luogu.com.cn)

代码:

#include<bits/stdc++.h>
using namespace std;
void beford(string in,string after)
{
    if (in.size())
    {
        char root=after[after.size()-1];
        cout<<root;//找根输出
        int k=in.find(root);
        beford(in.substr(0,k),after.substr(0,k));
        beford(in.substr(k+1),after.substr(k,in.size()-k-1));//递归左右子树;
    }
}
int main()
{
    string inord,aftord;
    cin>>inord>>aftord;//读入
    beford(inord,aftord);
    return 0;
}

美国血统 American Heritage

代码:同上

#include<bits/stdc++.h>
using namespace std;
void beford(string in,string pre)
{
    if (pre.size())
    {
        char root=pre[0];
        int k=in.find(root);
        pre.erase(pre.begin());
        beford(in.substr(0,k),pre.substr(0,k));
        beford(in.substr(k+1),pre.substr(k));
        cout<<root;
    }
}
int main()
{
    string preord,inord;
    cin>>inord>>preord;
    beford(inord,preord);
    return 0;
}

 [NOIP2004 普及组] FBI 树

主要是二分递归处理

代码1:string()函数强大的用法

#include<bits/stdc++.h>
using namespace std;

char FBI(string t)
{
	if (t.size()>1)
	{
		cout<<FBI(t.substr(0,t.size()/2));
		cout << FBI(t.substr(t.size()/2,t.size()/2));
	}
	if (t==string(t.size(),'0')) return 'B';  //string函数初始化的用法
	if (t==string(t.size(),'1')) return 'I';
	return 'F';
}

int main()
{
	int n;
	cin>>n;
	string s;
	cin >> s;
	cout << FBI(s);
	return 0;
}

代码2:纯二分

#include<bits/stdc++.h>
using namespace std;
char s[1025]; //2^10=1024
void work(int l, int r)
{
    int mid=l+r>>1;
    if(l!=r)
    {
        work(l,mid);
        work(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";
}
int main()
{
    int n;
    cin>>n>>s;  //scanf("&s",s+1)下标从s+1开始
    work(0,pow(2,n)-1);
    return 0;
}

图的遍历

代码:

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
int n,m,a[N];
vector<int> q[N];
void dfs(int x,int d)
{
    if(!a[x])
    {
        a[x]=d;
        for(int i=0;i<q[x].size();i++)dfs(q[x][i],d);
    }
}
int main()
{
    int u,v;
    cin>>n>>m;
    for(int i=1;i<=m;i++)
    {
        cin>>u>>v;
        q[v].push_back(u);
    }
    for(int i=n;i>0;i--)dfs(i,i);
    for(int i=1;i<=n;i++)cout<<a[i]<<' ';
    return 0;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值