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


    目录

    [模板] 树的深度1

    [模板] 树的深度2

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

    新二叉树

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

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

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

    [NOIP2001 普及组] 求先序排列

    美国血统 American Heritage

     [NOIP2004 普及组] FBI 树

    图的遍历


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

    [模板] 树的深度1

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

    代码1:dfs

    1. #include
    2. using namespace std;
    3. const int N = 5010;
    4. int n;
    5. int h[N], e[N], ne[N], idx;
    6. int d[N],q[N];
    7. void add(int a, int b)
    8. {
    9. e[idx] = b, ne[idx] = h[a], h[a] = idx ++ ;
    10. }
    11. int dfs(int t,int u)
    12. {
    13. d[t] = u;
    14. for(int i = h[t]; i != -1; i = ne[i])
    15. dfs(e[i],u + 1);
    16. }
    17. int main()
    18. {
    19. cin>>n;
    20. memset(h, -1, sizeof h);
    21. for (int i = 2; i <=n; i ++ )
    22. {
    23. int a;
    24. cin>>a;
    25. add(a, i);
    26. }
    27. dfs(1,1);
    28. for(int i=1;i<=n;i++)
    29. {
    30. cout<' ';
    31. }
    32. return 0;
    33. }

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

    1. #include
    2. using namespace std;
    3. const int N = 5010;
    4. int n;
    5. int h[N], e[N], ne[N], idx;
    6. int d[N],q[N];
    7. void add(int a, int b)
    8. {
    9. e[idx] = b, ne[idx] = h[a], h[a] = idx ++ ;
    10. }
    11. int bfs(int x)
    12. {
    13. int hh=0,tt=0;
    14. q[0]=1;
    15. memset(d, 0, sizeof d);
    16. d[1] = 1;
    17. while (hh<=tt)
    18. {
    19. int t = q[hh++];
    20. for (int i = h[t]; i != -1; i = ne[i])
    21. {
    22. int j = e[i];
    23. if (d[j]==0)
    24. {
    25. d[j] = d[t] + 1;
    26. q[++tt]=j;
    27. }
    28. }
    29. }
    30. return d[x];
    31. }
    32. int main()
    33. {
    34. cin>>n;
    35. memset(h, -1, sizeof h);
    36. for (int i = 2; i <=n; i ++ )
    37. {
    38. int a;
    39. cin>>a;
    40. add(a, i);
    41. }
    42. for(int i=1;i<=n;i++)
    43. {
    44. cout<<bfs(i)<<' ';
    45. }
    46. return 0;
    47. }

    [模板] 树的深度2

    链式前向星存树

    代码:

    1. #include
    2. using namespace std;
    3. const int N=5010;
    4. int n;
    5. int d[N];
    6. int head[N],cnt=0;
    7. struct node{
    8. int to,next;
    9. }edge[N*2];
    10. inline void add(int x,int y){
    11. edge[cnt].to=y;
    12. edge[cnt].next=head[x];
    13. head[x]=cnt++;
    14. }
    15. void dfs(int u,int t){
    16. d[u]=t;
    17. for(int i=head[u];~i;i=edge[i].next){
    18. int cld=edge[i].to;
    19. dfs(cld,t+1);
    20. }
    21. }
    22. int main(){
    23. cin>>n;
    24. memset(head,-1,4*N);
    25. for(int i=0;i-1;i++)
    26. {
    27. int x,y;
    28. cin>>x>>y;
    29. add(y,x);
    30. }
    31. dfs(1,1);
    32. for(int i=1;i<=n;i++)
    33. {
    34. cout<' ';
    35. }
    36. return 0;
    37. }

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

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

    代码:

    1. #include
    2. using namespace std;
    3. int res,n;
    4. struct node
    5. {
    6. int l,r;
    7. }a[1001000];//记录每个节点的左右节点
    8. void dfs(int root,int step)
    9. {
    10. //cout<<"root="<
      if(root==0) return;//如果该节点为0(即它的爸爸没有这个儿子),返回
    11. res=max(res,step);//记录最大值
    12. dfs(a[root].l,step+1);//搜索它的左儿子
    13. dfs(a[root].r,step+1);//搜索它的右儿子
    14. }
    15. int main()
    16. {
    17. cin>>n;
    18. for(int i=1;i<=n;i++)
    19. cin>>a[i].l>>a[i].r;//输入该节点的左节点和右节点
    20. dfs(1,1);//从1号节点,深度为1开始搜索
    21. cout<//输出最大值
    22. return 0;
    23. }

    新二叉树

    输出前序遍历

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

    1. #include
    2. using namespace std;
    3. char root,ch;
    4. struct nade
    5. {
    6. char l,r;
    7. }a[130];
    8. void dfs(char x)
    9. {
    10. if(x=='*') return;
    11. cout<
    12. dfs(a[x].l);//找到他的左孩子,继续往下探(如果左孩子是*的话,会返回的)
    13. dfs(a[x].r);
    14. }
    15. int main()
    16. {
    17. int n;
    18. cin>>n;
    19. cin>>root>>a[root].l>>a[root].r;//输入第一个字母,第一个字母比较特殊,所以单独输入
    20. for(int i=2;i<=n;i++) cin>>ch>>a[ch].l>>a[ch].r;
    21. dfs(root);
    22. return 0;
    23. }

    代码2:利用ASCII进行存储

    1. #include
    2. using namespace std;
    3. int n;
    4. struct node//定义二叉树结构体
    5. {
    6. string data;//自身
    7. int l,r;//左孩子和右孩子的数组下表。
    8. }t[1010];
    9. void dfs(int k)//先序遍历
    10. {
    11. cout<//遍历根节点
    12. if(t[k].l!=0)//如果有左孩子的话,遍历左孩子(未赋值默认为0)
    13. dfs(t[k].l);
    14. if(t[k].r!=0)//如果有右孩子的话,遍历右孩子
    15. dfs(t[k].r);
    16. }
    17. int main()
    18. {
    19. cin>>n;
    20. int root;//根节点的下标
    21. for(int i=1;i<=n;i++)
    22. {
    23. char a,b,c;
    24. cin>>a>>b>>c;
    25. if(i==1)//第一个输入的是根节点,储存其下标,为其在26个字母中的位置
    26. root=a-'a'+1;
    27. t[a-'a'+1].data=a;//储存
    28. //下面为确定父子关系
    29. if(b!='*')//如果有左儿子
    30. {
    31. t[b-'a'+1].data=b;//存储左儿子
    32. t[a-'a'+1].l=b-'a'+1;//记录左儿子的下标
    33. }
    34. if(c!='*')//同上,记录右儿子
    35. {
    36. t[c-'a'+1].data=c;
    37. t[a-'a'+1].r=c-'a'+1;
    38. }
    39. }
    40. dfs(root);//从根节点开始先序遍历
    41. return 0;
    42. }

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

    1. #include
    2. using namespace std;
    3. int n;
    4. char a[30][3];
    5. void f(char x)
    6. {
    7. if(x=='*') return ;
    8. cout<
    9. for(int i=1;i<=n;i++)
    10. if(a[i][0]==x)
    11. {
    12. f(a[i][1]);
    13. f(a[i][2]);
    14. }
    15. }
    16. int main()
    17. {
    18. cin>>n;
    19. for(int i=1;i<=n;i++)
    20. cin>>a[i][0]>>a[i][1]>>a[i][2];
    21. f(a[1][0]);
    22. return 0;
    23. }

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

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

    1. #include
    2. using namespace std;
    3. int root,m;
    4. struct node
    5. {
    6. int l,r;
    7. }a[5010];
    8. void dfs(int x)
    9. {
    10. if(x==0) return;
    11. cout<' ';
    12. dfs(a[x].l);
    13. dfs(a[x].r);
    14. }
    15. int main()
    16. {
    17. int n,p;
    18. cin>>n>>p;
    19. for(int i=1;i<=n;i++)
    20. {
    21. cin>>m>>a[m].l>>a[m].r;
    22. }
    23. dfs(p);
    24. return 0;
    25. }

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

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

    1. #include
    2. using namespace std;
    3. int root,m;
    4. struct node
    5. {
    6. int l,r;
    7. }a[5010];
    8. void dfs(int x)
    9. {
    10. if(x==0) return;
    11. //cout<
    12. dfs(a[x].l);
    13. cout<' ';
    14. dfs(a[x].r);
    15. }
    16. int main()
    17. {
    18. int n,p;
    19. cin>>n>>p;
    20. int root;
    21. for(int i=1;i<=n;i++)
    22. {
    23. cin>>m>>a[m].l>>a[m].r;
    24. }
    25. dfs(p);
    26. return 0;
    27. }

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

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

    1. #include
    2. using namespace std;
    3. int root,m;
    4. struct node
    5. {
    6. int l,r;
    7. }a[5010];
    8. void dfs(int x)
    9. {
    10. if(x==0) return;
    11. //cout<
    12. dfs(a[x].l);
    13. dfs(a[x].r);
    14. cout<' ';
    15. }
    16. int main()
    17. {
    18. int n,p;
    19. cin>>n>>p;
    20. int root;
    21. for(int i=1;i<=n;i++)
    22. {
    23. cin>>m>>a[m].l>>a[m].r;
    24. }
    25. dfs(p);
    26. return 0;
    27. }

    [NOIP2001 普及组] 求先序排列

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

    代码:

    1. #include
    2. using namespace std;
    3. void beford(string in,string after)
    4. {
    5. if (in.size())
    6. {
    7. char root=after[after.size()-1];
    8. cout<//找根输出
    9. int k=in.find(root);
    10. beford(in.substr(0,k),after.substr(0,k));
    11. beford(in.substr(k+1),after.substr(k,in.size()-k-1));//递归左右子树;
    12. }
    13. }
    14. int main()
    15. {
    16. string inord,aftord;
    17. cin>>inord>>aftord;//读入
    18. beford(inord,aftord);
    19. return 0;
    20. }

    美国血统 American Heritage

    代码:同上

    1. #include
    2. using namespace std;
    3. void beford(string in,string pre)
    4. {
    5. if (pre.size())
    6. {
    7. char root=pre[0];
    8. int k=in.find(root);
    9. pre.erase(pre.begin());
    10. beford(in.substr(0,k),pre.substr(0,k));
    11. beford(in.substr(k+1),pre.substr(k));
    12. cout<
    13. }
    14. }
    15. int main()
    16. {
    17. string preord,inord;
    18. cin>>inord>>preord;
    19. beford(inord,preord);
    20. return 0;
    21. }

     [NOIP2004 普及组] FBI 树

    主要是二分递归处理

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

    1. #include
    2. using namespace std;
    3. char FBI(string t)
    4. {
    5. if (t.size()>1)
    6. {
    7. cout<<FBI(t.substr(0,t.size()/2));
    8. cout << FBI(t.substr(t.size()/2,t.size()/2));
    9. }
    10. if (t==string(t.size(),'0')) return 'B'; //string函数初始化的用法
    11. if (t==string(t.size(),'1')) return 'I';
    12. return 'F';
    13. }
    14. int main()
    15. {
    16. int n;
    17. cin>>n;
    18. string s;
    19. cin >> s;
    20. cout << FBI(s);
    21. return 0;
    22. }

    代码2:纯二分

    1. #include
    2. using namespace std;
    3. char s[1025]; //2^10=1024
    4. void work(int l, int r)
    5. {
    6. int mid=l+r>>1;
    7. if(l!=r)
    8. {
    9. work(l,mid);
    10. work(mid+1,r);
    11. }
    12. int a=0,b=0;
    13. for (int i=l;i<=r;i++)
    14. if (s[i]=='0') a++;
    15. else b++;
    16. if(a&&b) cout<<"F";
    17. else if (a) cout<<"B";
    18. else cout<<"I";
    19. }
    20. int main()
    21. {
    22. int n;
    23. cin>>n>>s; //scanf("&s",s+1)下标从s+1开始
    24. work(0,pow(2,n)-1);
    25. return 0;
    26. }

    图的遍历

    代码:

    1. #include
    2. using namespace std;
    3. const int N=1e5+10;
    4. int n,m,a[N];
    5. vector<int> q[N];
    6. void dfs(int x,int d)
    7. {
    8. if(!a[x])
    9. {
    10. a[x]=d;
    11. for(int i=0;isize();i++)dfs(q[x][i],d);
    12. }
    13. }
    14. int main()
    15. {
    16. int u,v;
    17. cin>>n>>m;
    18. for(int i=1;i<=m;i++)
    19. {
    20. cin>>u>>v;
    21. q[v].push_back(u);
    22. }
    23. for(int i=n;i>0;i--)dfs(i,i);
    24. for(int i=1;i<=n;i++)cout<' ';
    25. return 0;
    26. }

  • 相关阅读:
    关于2022年深圳市福田区支持高端服务业发展项目的申报通知
    spring-boot-starter和spring-boot-starter-web的关联
    异常处理(try,catch,finally)
    HC32L110(四) HC32L110的startup启动文件和ld连接脚本
    IP地址,子网,掩码的计算
    Python学习 day02(注意事项)
    宝安水环境管控平台(Ionic/Angular 移动端) 问题记录
    【蓝桥每日一题]-动态规划 (保姆级教程 篇12)#照相排列
    MW600GQ——5G模块使用、调试记录
    基于Java的汽车维修预约管理系统设计与实现(源码+lw+部署文档+讲解等)
  • 原文地址:https://blog.csdn.net/m0_62593364/article/details/126285373