圖的基本操作和實現

進階的萌新發表於2018-04-15

圖的基本操作與實現

1)自選儲存結構,輸入含n個頂點(用字元表示頂點)和e條邊的圖G

(2)求每個頂點的度,輸出結果;

3)  指定任意頂點x為初始頂點,對圖GDFS遍歷,輸出DFS頂點序列(提示:使用一個棧實現DFS)

  (4)  指定任意頂點x為初始頂點,對圖GBFS遍歷,輸出BFS頂點序列(提示:使用一個佇列實現BFS)

  (5)  輸入頂點x,查詢圖G:若存在含x的頂點,則刪除該結點及與之相關連的邊,並作DFS遍歷(執行操作3);否則輸出資訊“無x”

  (6)  判斷圖G是否是連通圖,輸出資訊“YES/NO”;

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#define maxSize 100
using namespace std;

int Count=0;
const int Max=50;
typedef char type;
bool visited[100] = { false };

typedef struct                         ///定義資料結構:棧
{
    int *top;
    int *base;
    int Size;
}Stack;

typedef struct                        ///定義資料結構:佇列
{
    int *Front;
    int *Rear;
    int Size;
} Queue;

typedef struct                       ///定義資料結構:圖
{
    type vexs[Max];
    bool arcs[Max][Max];
    int vexnum,arcnum;
} graph;

void InitStack(Stack &s)             ///對棧進行初始化
{
    if(!(s.top=s.base=(int *)malloc(maxSize*sizeof(int))))
        return ;
    s.Size=maxSize;
}

void push(Stack &s,int e)            ///入棧:將元素e壓入棧
{
    *s.top=e;
    s.top++;
}

void pop(Stack &s)                  ///出棧:棧頂指標減一
{
    if(s.base==s.top)
        return ;
    s.top--;
}

int top(Stack s)                    ///返回棧頂元素
{
    s.top--;
    return *s.top;
}

void InitQueue(Queue &q)            ///初始化佇列
{
    if(!(q.Front=q.Rear=(int *)malloc(maxSize*sizeof(int))))
        return ;
    q.Size=maxSize;
}

void Q_push(Queue &q,int e)         ///入佇列:將元素e入佇列
{
    *q.Rear=e;
    q.Rear++;
}

int Q_pop(Queue &q)                 ///出佇列:返回隊頭元素,隊頭指標加一
{
    int e;
    if(q.Front==q.Rear)
        return 0;
    e=*q.Front;
    q.Front++;
    return e;
}

void Create(graph *g)               ///建立鄰接矩陣並輸出
{
    int i,j;
    memset(g->arcs,0,sizeof(g->arcs));
    for(i=0; i<g->arcnum; ++i)
    {
        int x,y;
        cin>>x>>y;
        g->arcs[x][y]=1;
        g->arcs[y][x]=1;
    }
    cout<<"無向鄰接表矩陣為:"<<endl;
    for(i=0; i<g->vexnum; i++)
    {
        for(j=0; j<g->vexnum; j++)
            cout<<g->arcs[i][j]<<" ";
        cout<<endl;
    }
}

void Du(graph *g)                    ///統計每個頂點的度
{
    int i,j;
    for(i=0; i<g->vexnum; i++)
    {
        int amount=0;
        for(j=0; j<g->vexnum; ++j)
            if(g->arcs[i][j])
                ++amount;
        cout<<"頂點"<<g->vexs[i]<<"的度為"<<amount<<endl;
    }
}

void DFS(graph *g,int k)            ///DFS深度優先搜尋
{
    int t,i;
    Stack s;
    InitStack(s);
    cout<<g->vexs[k]<<" ";
    visited[k]=true;
    push(s,k);
    while(s.base!=s.top)
    {
        t=top(s);
        if(i==g->vexnum)                              ///如果內層迴圈未找到沒被訪問的元素,則出棧
            pop(s);
        for(i=0; i<g->vexnum; i++)
        {
            if(g->arcs[t][i]==1&&visited[i]==false)   ///找出鄰接矩陣第t+1行中第一個未被訪問的元素
            {
                visited[i]=true;                      ///找到後標誌為1,並輸出,入棧
                cout<<g->vexs[i]<<" ";
                push(s,i);
                break;                                ///找到之後跳出內層迴圈,返回外層迴圈起始處,重複之前操作
            }
        }
    }
}

void BFS(graph *g, int k)            ///BFS廣度優先搜尋
{
    Queue q;
    InitQueue(q);
    visited[k]=true;
    cout<<g->vexs[k]<<" ";
    Q_push(q,k);
    while(q.Front!=q.Rear)
    {
        int t=Q_pop(q);
        for(int w=0; w<g->vexnum; w++)
        {
            if (g->arcs[t][w]!=0&&visited[w]==false)   ///找出鄰接矩陣中t+1行所有未被訪問的元素
            {
                visited[w]=true;                       ///每找到一個標誌為1併入佇列
                cout<<g->vexs[w]<<" ";
                Q_push(q,w);
            }
        }
    }
}

void Is_in_graph(graph *g,char ch)      ///查詢圖中是否存在頂點ch
{
    int i,j,k;
    for(i=0; i<g->vexnum; i++)          ///遍歷頂點陣列
        if(ch==g->vexs[i])
            break;
    if(i==g->vexnum)                    ///如果迴圈正常結束則i=g->vexnum,此時說明不存在該頂點
    {
        printf("無%c",ch);
        return ;
    }
    else
    {
        for(j=0; j<g->vexnum; j++)     ///如果存在,則將與頂點相關的邊覆蓋
            for(k=0; k<g->vexnum; k++)
            {
                if(j>=i&&k>=i)
                    g->arcs[j][k]=g->arcs[j+1][k+1];
                if(j>=i&&k<i)
                    g->arcs[j][k]=g->arcs[j+1][k];
                if(j<i&&k>=i)
                    g->arcs[j][k]=g->arcs[j][k+1];
            }
    }
    for(j=0; j<g->vexnum; j++)         ///覆蓋該頂點
        if(j>=i)
            g->vexs[j]=g->vexs[j+1];
    g->vexnum--;
    cout<<"刪除該頂點後剩餘頂點為:\n";
    for(j=0; j<g->vexnum; j++)
        cout<<g->vexs[j]<<" ";
    cout<<endl;
    cout<<"刪除後鄰接矩陣為:\n";
    for(j=0; j<g->vexnum; j++)
    {
        for(k=0; k<g->vexnum; k++)
            cout<<g->arcs[j][k]<<" ";
        cout<<endl;
    }
    cout<<"從第一個頂點開始的DFS遍歷為:\n";
    DFS(g,0);
}


void Is_connect(graph *g,int k)        ///利用DFS搜尋的思想遍歷圖,每遍歷一個頂點計數加一
{
    visited[k]=true;
    Count++;
    for(int i=0; i<g->vexnum; i++)
        if(g->arcs[k][i]==1&&visited[i]==false)
        {
            Is_connect(g,i);
        }
}

void main_menu()                      ///主選單
{
    cout<<"-----------------------------------\n";
    cout<<"---------程式主選單----------------\n";
    cout<<"-----------------------------------\n";
    cout<<"---------1圖的創立及鄰接矩陣-------\n";
    cout<<"---------2查詢圖中各頂點的度-------\n";
    cout<<"---------3DFS遍歷圖----------------\n";
    cout<<"---------4BFS遍歷圖----------------\n";
    cout<<"---------5查詢頂點是否在圖中-------\n";
    cout<<"---------6判斷是否為連通圖---------\n";
    cout<<"---------7退出---------------------\n";
    cout<<"---------Enter鍵返回選單------------\n";
    cout<<"-----------------------------------\n";
    cout<<"---------請選擇:(1-7)--------------\n";
}

int main()
{
    int i,num;
    char ch;
    graph g;
    while(1)
    {
        system("cls");
        main_menu();
        scanf("%d",&num);
        system("cls");
        switch(num)                                   ///通過輸入1-7呼叫不同的功能
        {
        case 1:
            printf("1圖的創立及鄰接矩陣\n\n");
            printf("請輸入頂點的個數:");
            cin>>g.vexnum;
            cout<<endl;
            printf("請輸入邊的條數:");
            cin>>g.arcnum;
            printf("請輸入各頂點:");
            for(i=0; i<g.vexnum; ++i)
                cin>>g.vexs[i];
            cout<<endl;
            printf("請輸入各條邊i-j:\n");
            Create(&g);
            printf("輸入任意鍵返回主選單:");
            system("pause");
            break;
        case 2:
            printf("2查詢圖中各頂點的度\n\n");
            Du(&g);
            printf("輸入任意鍵返回主選單:");
            system("pause");
            break;
        case 3:
            printf("3DFS遍歷圖\n\n");
            printf("請輸入開始的頂點:");
            cin>>ch;
            cout<<endl;
            for(i=0;i<g.vexnum;i++)
                if(ch==g.vexs[i])
                    break;
            if(i>=g.vexnum)
            {
                printf("輸入數字有誤!");
                printf("輸入任意鍵返回主選單:");
                system("pause");
                break;
            }
            printf("從該點開始DFS搜尋為:");
            DFS(&g,i);
            cout<<endl;
            memset(visited,0,sizeof(visited));           ///將訪問標誌陣列初始化為0
            printf("輸入任意鍵返回主選單:");
            system("pause");
            break;
        case 4:
            printf("4BFS遍歷圖\n\n");
            printf("請輸入開始的頂點:");
            cin>>ch;
            cout<<endl;
            for(i=0;i<g.vexnum;i++)
                if(ch==g.vexs[i])
                    break;
            if(i>=g.vexnum)
            {
                printf("輸入數字有誤!");
                printf("輸入任意鍵返回主選單:");
                system("pause");
                break;
            }
            printf("從該點開始BFS搜尋為:");
            BFS(&g,i);
            cout<<endl;
            memset(visited,0,sizeof(visited));         ///將訪問標誌陣列初始化為0
            printf("輸入任意鍵返回主選單:");
            system("pause");
            break;
        case 5:
            printf("5查詢頂點是否在圖中\n\n");
            printf("請輸入要查詢的頂點:");
            cin>>ch;
            cout<<endl;
            Is_in_graph(&g,ch);
            cout<<endl;
            memset(visited,0,sizeof(visited));        ///將訪問標誌陣列初始化為0
            printf("輸入任意鍵返回主選單:");
            system("pause");
            break;
        case 6:
            printf("6判斷是否為連通圖\n\n");
            Is_connect(&g,0);
            if(Count==g.vexnum)
                printf("YES!");
            else
                printf("NO!");
            cout<<endl;
            Count=0;
            memset(visited,0,sizeof(visited));         ///將訪問標誌陣列初始化為0
            printf("輸入任意鍵返回主選單:");
            system("pause");
            break;
        case 7:
            printf("退出成功");
            return 0;
        }
    }
}




相關文章