天天看点

数据结构-图结构转化为二叉树

  • 不多bb先上代码

首先声明这个图不是连通图,存在3个连通分支

数据结构-图结构转化为二叉树
#include<iostream>
using namespace std;
struct TreeNode{
    int data;
    struct TreeNode* f;
    struct TreeNode* s;
};
char name[13]={'a','b','c','d','e','f','g','h','i','j','k','l','m'};//data[a],a号点的名字
struct G{
    int n;
    int weight[20][20];
};
struct G* creat(){
    struct G* G=new struct G;
    cin>>G->n;
    for(int a=0;a<G->n;a++){
        for(int b=0;b<G->n;b++){
            cin>>G->weight[a][b];
        }
    }
    return G;
};
struct TreeNode* creatNode(int data ){
    struct TreeNode* head=new struct TreeNode;
    head->data=data;
    head->s=NULL;
    head->f=NULL;
    return head;
};
void fun1(struct G *G,struct TreeNode ** head,int *flag,int dian){
    int f=1;//g==1 访问了第一个孩子 g==0 没有访问第一个;
    flag[dian]=1;
    struct TreeNode *pr=NULL;
    for(int a=0;a<G->n;a++){
        if(G->weight[dian][a]==1&&flag[a]!=1){
            struct TreeNode* p=creatNode(a);
            if(f==1){
                (*head)->f=p;
                f=0;
            }else{
                pr->s=p;
            }
            pr=p;
            fun1(G,&p,flag,a);
        }
    }
}
void fun(struct G* G ,struct TreeNode**head,int *flag){
    struct TreeNode* pr=NULL;
    for(int a=0;a<G->n;a++){
        if(flag[a]!=1){
            struct TreeNode*p=creatNode(a);
            if(*head==NULL)*head=p;
            else {
                pr->s=p;
            }
            pr=p;
            fun1(G,&p,flag,a);
        }
    }
}
void xian(struct TreeNode* head){
    if(head==NULL)return ;
    cout<<name[head->data]<<' ';
    xian(head->f);
    xian(head->s);
}
void hou(struct TreeNode *head){
    if(head==NULL)return ;
    hou(head->f);
    cout<<name[head->data]<<' ';
    hou(head->s);
}
main(){
    struct G* G=creat();
    int *flag= new int[G->n];
    for(int a=0;a<G->n;a++){
        flag[a]=0;
    }
    struct TreeNode* head=NULL;
    fun(G,&head,flag);
    xian(head);
    cout<<endl;
    hou(head);
}
/*
    13
    0 1 1 0 0 1 0 0 0 0 0 1 0
    1 0 0 0 0 0 0 0 0 0 0 0 1
    1 0 0 0 0 0 0 0 0 0 0 0 0
    0 0 0 0 1 0 0 0 0 0 0 0 0
    0 0 0 1 0 0 0 0 0 0 0 0 0
    1 0 0 0 0 0 0 0 0 0 0 0 0
    0 0 0 0 0 0 0 1 1 0 1 0 0
    0 0 0 0 0 0 1 0 0 0 1 0 0
    0 0 0 0 0 0 1 0 0 0 0 0 0
    0 0 0 0 0 0 0 0 0 0 0 1 1
    0 0 0 0 0 0 1 1 0 0 0 0 0
    1 0 0 0 0 0 0 0 0 1 0 0 1
    0 1 0 0 0 0 0 0 0 1 0 1 0


0 1 12 9 11 2 5 3 4 6 7 10 8
xian:
a b m j l c f d e g h k i
zhong:
l j m b c f a e d k h i g
*/

           

这个算法真的花费了我好多脑力,注意事项:

思路

  • 如果这个图不是连通图需要一个函数把每个连通分量都“合在”一个二叉树中(这是fun()的功能)
  • 创建一个图 这个很简单你们都会
  • fun()将遍历图的每一个连通分支同时以一个连通分支的其中一个点作为根节点调用fun1()函数来遍历这个连通分支中的所有点
  • fun1()函数是个深度优先的遍历 但要值得注意的是first这个变量代表的意思:时候遍历了这个点的下一个点(赋给左孩子)否则(给右孩子)而且永远有一个单独的指针指向我们新创建的节点!!这是是最关键的!(反正我在这弄了好久)

注意事项

  • 简单说一下fun()函数 的最关键的部分:创建一个节点存储第一个点(一定是第一个点)如果head没有东西,那就给head 因为这是我们在外界函数的头!如果*head有东西 那就给 当前活跃的节点()的右孩子 这是因为我们是兄弟啊 不管怎么说我都会以这个新创的节点为活跃节点
  • fun1()函数 最关键的部分:我们的父亲(头结点已经知道了)来了,我们要接到父亲的身上。(记住:递归函数调用的时候有可能回来的)要记录是否访问了第一个孩子将其赋给左孩子 否则赋给活跃节点的右兄弟!

赶紧写代码吧

继续阅读