zoukankan      html  css  js  c++  java
  • 数据结构无向图的建立和遍历(邻接链表)

      数据结构无向图的邻接链表的存储方式:顶点用一维数组储存,每个顶点构成一个线性表,用单链表的形式表达

    1.结构体的创建

    #define MAX 20
    
    //线性表中的结点 
    typedef struct ENode{
        int index;  //该数据的下标 
        struct ENode *next;//下一个结构体 
    }ENode;
    
    //顶点信息
    typedef struct Node{
        char data;
        struct ENode *firstNode;  //指向节点的指针 
    }Node; 
    
    //链接表的信息
    typedef struct Graph{
        int vexNum;  //顶点数量
        int arcNum;  //边的数量
        Node vexs[MAX];   //顶点数组  用.的方式访问 
    }Graph,*myGraph;

    2.无向图的邻接链表的创建

    void createGraph(myGraph &G)
    {
        G=(Graph*)malloc(sizeof(Graph));  //结构体的指针要初始化
         
        int i,j,k;
        char v1,v2;    //边的两个顶点 
        printf("请输入顶点的数量:");
        scanf("%d",&G->vexNum);
        printf("请输入边的数量:");
        scanf("%d",&G->arcNum);
        
        printf("请依次将顶点数据输入进来
    ");
        for(i=0;i<G->vexNum;i++)
        {  
            getchar();
            scanf("%c",&G->vexs[i].data);
            G-> vexs[i].firstNode=NULL;//顶点指向的线性表为空 
        }
        
        printf("请依次将边输入进来
    ");
        for(int i=0;i<G->arcNum;i++)
        {
            getchar();
            scanf("%c%c",&v1,&v2);
            j=getLocate(G,v1);  //获取下标
            k=getLocate(G,v2);  //获取下标
            
            //v1v2边   jk
            ENode *currentNode1=(ENode*)malloc(sizeof(Node));//生成临时结点
            currentNode1->index=k; //储存的下标
            currentNode1->next=NULL; //指针指向的节点为空 
            
            if(G->vexs[j].firstNode==NULL)//当该顶点没有邻接点时 
            {
                G->vexs[j].firstNode=currentNode1; //指向这个结点
            } 
            else  //该顶点有邻接点时 
            {
                ENode *p=G->vexs[j].firstNode;  //避免 G->vexs[j].firstNode 会发生改变 
                while(p->next!=NULL)  //指向该顶点线性表中的最后一个节点 
                {
                    p=p->next;
                }
                p->next=currentNode1; //指向这个结点 
            }
            
            //v2v1边   kj
            ENode *currentNode2=(ENode*)malloc(sizeof(Node));//生成临时结点
            currentNode2->index=j; //储存的下标
            currentNode2->next=NULL; //指针指向的节点为空 
                
            if(G->vexs[k].firstNode==NULL)//当该顶点没有邻接点时 
            {
                G->vexs[k].firstNode=currentNode2; //指向这个结点 
            } 
            else  //该顶点有邻接点时 
            {
                ENode *q=G->vexs[k].firstNode;   //避免 G->vexs[j].firstNode 会发生改变 
                while(q->next!=NULL)  //指向该顶点线性表中的最后一个节点 
                {
                    q=q->next;
                }
                q->next=currentNode2; //指向这个结点 
            }
        }  
    }

    3.邻接链表的深度优先遍历

    void DFS(myGraph G,int i,int *visit)
    {
        if(!visit[i])//如果没有访问过 
        {
            ENode *node;//临时结点 
            visit[i]=1;
            printf("%c ",G->vexs[i].data); //输出该顶点信息
            node=G->vexs[i].firstNode;   //避免破坏  G->vexs[i].firstNode
            
            while(node!=NULL)//该邻接点不为空
            {
                if(!visit[node->index]) //如果该邻接点没有被访问过 
                {
                    DFS(G,node->index,visit);
                }
                node=node->next;
            } 
        }
    }

    4.邻接链表的广度优先遍历

    void BFS(myGraph G,int *visit)  //队列满足先进先出的规律 
    {
        int front=0;
        int rear=0;
        int Queue[G->vexNum]; 
        int i,j;
        ENode *node;
        
        for(i=0;i<G->vexNum;i++)//避免出现没有邻接点的顶点 
        {
            if(!visit[i]) //如果没有访问过 
            {
                visit[i]=1; //该顶点被访问过
                printf("%c ",G->vexs[i].data);
                Queue[rear++]=i;   //入队列 
            }
            
            while(front!=rear)
            {
                j=Queue[front++];  //出队列 
                node=G->vexs[j].firstNode;
                while(node!=NULL)
                {
                    if(!visit[node->index])
                    {
                        visit[node->index]=1;
                        printf("%c ",G->vexs[node->index].data);
                        Queue[rear++]=node->index;   //入队列 
                    }
                    node=node->next;
                }
            }
        }
    } 

    所有的代码如下:

    #include<stdio.h>
    #include<stdlib.h> 
    
    #define MAX 20
    
    //线性表中的结点 
    typedef struct ENode{
        int index;  //该数据的下标 
        struct ENode *next;//下一个结构体 
    }ENode;
    
    //顶点信息
    typedef struct Node{
        char data;
        struct ENode *firstNode;  //指向节点的指针 
    }Node; 
    
    //链接表的信息
    typedef struct Graph{
        int vexNum;  //顶点数量
        int arcNum;  //边的数量
        Node vexs[MAX];   //顶点数组  用.的方式访问 
    }Graph,*myGraph;
    
    //获取顶点的下标
    int getLocate(myGraph G,char v)
    {
        int i;
        for(i=0;i<G->vexNum;i++)
        {
            if(v==G->vexs[i].data)
            {
                return i;
            }
        }
        return -1;
    }
    
    //创建链表
    void createGraph(myGraph &G)
    {
        G=(Graph*)malloc(sizeof(Graph));  //结构体的指针要初始化
         
        int i,j,k;
        char v1,v2;    //边的两个顶点 
        printf("请输入顶点的数量:");
        scanf("%d",&G->vexNum);
        printf("请输入边的数量:");
        scanf("%d",&G->arcNum);
        
        printf("请依次将顶点数据输入进来
    ");
        for(i=0;i<G->vexNum;i++)
        {  
            getchar();
            scanf("%c",&G->vexs[i].data);
            G-> vexs[i].firstNode=NULL;//顶点指向的线性表为空 
        }
        
        printf("请依次将边输入进来
    ");
        for(int i=0;i<G->arcNum;i++)
        {
            getchar();
            scanf("%c%c",&v1,&v2);
            j=getLocate(G,v1);  //获取下标
            k=getLocate(G,v2);  //获取下标
            
            //v1v2边   jk
            ENode *currentNode1=(ENode*)malloc(sizeof(Node));//生成临时结点
            currentNode1->index=k; //储存的下标
            currentNode1->next=NULL; //指针指向的节点为空 
            
            if(G->vexs[j].firstNode==NULL)//当该顶点没有邻接点时 
            {
                G->vexs[j].firstNode=currentNode1; //指向这个结点
            } 
            else  //该顶点有邻接点时 
            {
                ENode *p=G->vexs[j].firstNode;  //避免 G->vexs[j].firstNode 会发生改变 
                while(p->next!=NULL)  //指向该顶点线性表中的最后一个节点 
                {
                    p=p->next;
                }
                p->next=currentNode1; //指向这个结点 
            }
            
            //v2v1边   kj
            ENode *currentNode2=(ENode*)malloc(sizeof(Node));//生成临时结点
            currentNode2->index=j; //储存的下标
            currentNode2->next=NULL; //指针指向的节点为空 
                
            if(G->vexs[k].firstNode==NULL)//当该顶点没有邻接点时 
            {
                G->vexs[k].firstNode=currentNode2; //指向这个结点 
            } 
            else  //该顶点有邻接点时 
            {
                ENode *q=G->vexs[k].firstNode;   //避免 G->vexs[j].firstNode 会发生改变 
                while(q->next!=NULL)  //指向该顶点线性表中的最后一个节点 
                {
                    q=q->next;
                }
                q->next=currentNode2; //指向这个结点 
            }
        }  
    }
    
    
    //邻接链表的深度优先遍历
    void DFS(myGraph G,int i,int *visit)
    {
        if(!visit[i])//如果没有访问过 
        {
            ENode *node;//临时结点 
            visit[i]=1;
            printf("%c ",G->vexs[i].data); //输出该顶点信息
            node=G->vexs[i].firstNode;   //避免破坏  G->vexs[i].firstNode
            
            while(node!=NULL)//该邻接点不为空
            {
                if(!visit[node->index]) //如果该邻接点没有被访问过 
                {
                    DFS(G,node->index,visit);
                }
                node=node->next;
            } 
        }
    }
    
    //邻接链表的广度优先遍历
    void BFS(myGraph G,int *visit)  //队列满足先进先出的规律 
    {
        int front=0;
        int rear=0;
        int Queue[G->vexNum]; 
        int i,j;
        ENode *node;
        
        for(i=0;i<G->vexNum;i++)//避免出现没有邻接点的顶点 
        {
            if(!visit[i]) //如果没有访问过 
            {
                visit[i]=1; //该顶点被访问过
                printf("%c ",G->vexs[i].data);
                Queue[rear++]=i;   //入队列 
            }
            
            while(front!=rear)
            {
                j=Queue[front++];  //出队列 
                node=G->vexs[j].firstNode;
                while(node!=NULL)
                {
                    if(!visit[node->index])
                    {
                        visit[node->index]=1;
                        printf("%c ",G->vexs[node->index].data);
                        Queue[rear++]=node->index;   //入队列 
                    }
                    node=node->next;
                }
            }
        }
    } 
    
    //打印该邻接表
    void printfGraph(Graph G)  //打印表不要用指针,这样可能会改变图的结构 
    {
        for(int i=0;i<G.vexNum;i++)
        {
            printf("%c ",G.vexs[i].data);
            while(G.vexs[i].firstNode!=NULL)
            {
                printf("%d ",G.vexs[i].firstNode->index);
                G.vexs[i].firstNode=G.vexs[i].firstNode->next;
            }
            printf("
    ");
        } 
    }
    
    int main()
    {
        Graph *G;  //申明邻接链表的对象
        createGraph(G);  //创建邻接链表
        printfGraph(*G);   //打印该邻接链表 
        
        int visit[G->vexNum]={0};
        printf("图的邻接链表的深度优先遍历如下:
    ");
        for(int i=0;i<G->vexNum;i++)  //避免出现没有邻接点的顶点 
        {
            DFS(G,i,visit);
        }
        printf("
    ");
        
        for(int i=0;i<G->vexNum;i++)
        {
            visit[i]=0;
        }
        printf("图的邻接链表的广度优先遍历如下:
    ");
        BFS(G,visit); 
        return 0;
    }
    
    
    
    
     
  • 相关阅读:
    2017干货分享丨全球100款大数据工具汇总(附图)
    Hbase与Oracle比较(列式数据库与行式数据库)
    HBase底层存储原理
    关系数据库_关系代数的并行计算_数据库分类
    HBase与列存储
    ZooKeeper分布式过程协同技术详解2——了解ZooKeeper
    ZooKeeper分布式过程协同技术详解1——ZooKeeper的概念和基础
    facebook api之基本概念(中文)
    facebook api之Access Tokens之Business Manager System User
    facebook api之Access Tokens
  • 原文地址:https://www.cnblogs.com/qian-yi/p/12774948.html
Copyright © 2011-2022 走看看