數據結構無向圖的建立和遍歷(鄰接鏈表)


  數據結構無向圖的鄰接鏈表的存儲方式:頂點用一維數組儲存,每個頂點構成一個線性表,用單鏈表的形式表達

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("請依次將頂點數據輸入進來\n");
    for(i=0;i<G->vexNum;i++)
    {  
        getchar();
        scanf("%c",&G->vexs[i].data);
        G-> vexs[i].firstNode=NULL;//頂點指向的線性表為空 
    }
    
    printf("請依次將邊輸入進來\n");
    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("請依次將頂點數據輸入進來\n");
    for(i=0;i<G->vexNum;i++)
    {  
        getchar();
        scanf("%c",&G->vexs[i].data);
        G-> vexs[i].firstNode=NULL;//頂點指向的線性表為空 
    }
    
    printf("請依次將邊輸入進來\n");
    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("\n");
    } 
}

int main()
{
    Graph *G;  //申明鄰接鏈表的對象
    createGraph(G);  //創建鄰接鏈表
    printfGraph(*G);   //打印該鄰接鏈表 
    
    int visit[G->vexNum]={0};
    printf("圖的鄰接鏈表的深度優先遍歷如下:\n");
    for(int i=0;i<G->vexNum;i++)  //避免出現沒有鄰接點的頂點 
    {
        DFS(G,i,visit);
    }
    printf("\n");
    
    for(int i=0;i<G->vexNum;i++)
    {
        visit[i]=0;
    }
    printf("圖的鄰接鏈表的廣度優先遍歷如下:\n");
    BFS(G,visit); 
    return 0;
}




 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM