啊哈,算法自學記——8th

圖:
簡單地說,圖就是由一-些小圓點(稱爲頂點)和連接這些小圓點的直線(稱爲邊)組成的。例如上圖是由五個頂點(編號爲1、2、3、4、5)和5條邊(1-2、1-3、1-5、2-4、3-5)組成。
在這裏插入圖片描述

圖中每個頂點右上方的數就表示這個頂點是第幾個被訪問到的,我們還爲這個數起了很好聽的名字一時間戳

在這裏插入圖片描述

深度優先遍歷的主要思想就是:
首先以一個未被訪問過的頂點作爲起始頂點,沿當前頂點的邊走到未訪問過的頂點:當沒有未訪問過的頂點時,則回到上-一個頂點,繼續試探訪問別的頂點,直到所有的頂點都被訪問過。顯然,深度優先遍歷是沿着圖的某一條 分支遍歷直到末端,然後回溯,再沿着另- -條進行同樣的遍歷,直到所有的頂點都被訪問過爲止。
他訪問的順序依次是1-2-4-3-5

廣度優先遍歷的主要思想就是:
首先以一個未被訪問過的頂點作爲起始頂點,訪問其所有相鄰的頂點,然後對每個相鄰的頂點,再訪問它們相鄰的未被訪問過的頂點,直到所有頂點都被訪問過,遍歷結束。(像剝洋蔥一樣,一層一層遍歷)
它訪問的順序依次是:1-2-3-5-4

圖的存儲:

在這裏插入圖片描述
上圖二維數組中第i行第j列表示的就是頂點i到頂點j是否有邊。1表示有邊,∞表示沒有邊,這裏我們將自己到自己(即i等於j)設爲0。我們將這種存儲圖的方法稱爲圖的鄰接矩陣存儲法

深度優先搜索:

#include <stdio.h>

int book[101],sum,n,e[101][101];

void dfs(int cur)
{
    printf("%d ",cur);
    sum++;
    if(sum==n)return;
    for (int i = 1; i <= n; i++)
    {
        if (e[cur][i]==1 && book[i]==0)
        {
            book[i]=1;
            dfs(i);
        }
    }
    return;
}

int main(int argc, char const *argv[])
{
    int i,j,m,a,b;

    printf("Input the size of the map:\r\n");
    scanf("%d %d",&n,&m);

    for (int i = 1; i <= n; i++)//初始化數組
    {
        for (int j = 1; j <= m; j++)
        {
            if(i==j)
                e[i][j]=0;//自己到自己的設爲0
            else
            {
                e[i][j]=999999;//沒有邊的設爲∞,用999999來代替
            }
            
        }
        
    }

    //讀定點之間的邊
    for (int i = 1; i <= m; i++)    
    {
        printf("Input a line:\r\n");
        scanf("%d %d",&a,&b);
        e[a][b]=1;
        e[b][a]=1;//雙向圖所以e[b][a]=1
    }
    
    book[1]=1;//從一號位出發,標記一號位已經訪問過
    dfs(1);

    return 0;
}

運行結果:
在這裏插入圖片描述

廣度優先搜索:

#include <stdio.h>

int main(int argc, char const *argv[])
{
    int cur,a,b,m,n,e[101][101],book[101]={0};
    int que[10001],head,tail;

    printf("Input the size of the map:\r\n");
    scanf("%d %d",&n,&m);

    for (int i = 1; i <= n; i++)//初始化數組
    {
        for (int j = 1; j <= m; j++)
        {
            if(i==j)
                e[i][j]=0;//自己到自己的設爲0
            else
            {
                e[i][j]=999999;//沒有邊的設爲∞,用999999來代替
            }
            
        }
        
    }

    //讀定點之間的邊
    for (int i = 1; i <= m; i++)    
    {
        printf("Input a line:\r\n");
        scanf("%d %d",&a,&b);
        e[a][b]=1;
        e[b][a]=1;//雙向圖所以e[b][a]=1
    }

    //隊列初始化
    head=1;
    tail=1;

    //從一號位出發
    que[tail]=1;//入隊
    tail++;
    book[1]=1;//標記一號位已經遍歷過

    while (head<tail)//隊列不爲空的時候循環 
    {
        cur=que[head];//當前正在訪問的定點編號
        for (int i = 1; i <= n;  i++)//從1~n依次嘗試
        {
            if (e[cur][i]==1 && book[i]==0)//如果有邊並且沒有遍歷過
            {
                que[tail]=i;//加入隊列
                tail++;
                book[i]=1;//標記
            }
            
            if(tail>n)//說明所有定點都別訪問過了
                break;
        }
        head++;//當一個定點擴展後,head++才能繼續向下擴展
    }
    
    printf("Result:\r\n");
    for (int i = 1; i < tail; i++)
    {
        printf("%d ",que[i]);
    }
    
    return 0;
}

運行結果:
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章