數據結構(五)圖---圖的兩種遍歷(深度優先和廣度優先)


從圖的某一頂點出發訪遍其余頂點,且使每一個頂點僅被訪問一次,這一過程就叫做圖的遍歷

一:深度優先遍歷(鄰接矩陣實現)

(一)定義

假設給定圖G的初態是所有頂點均未曾訪問過。在G中任選一頂點v為初始出發點(源點),則深度優先遍歷可定義如下:首先訪問出發點v,並將其標記為已訪問過;然后依次從v出發搜索v的每個鄰接點w。若w未曾訪問過,則以w為新的出發點繼續進行深度優先遍歷,直至圖中所有和源點v有路徑相通的頂點(亦稱為從源點可達的頂點)均已被訪問為止。若此時圖中仍有未訪問的頂點(未連通),則另選一個尚未訪問的頂點作為新的源點重復上述過程,直至圖中所有頂點均已被訪問為止。
圖的深度優先遍歷類似於樹的前序遍歷。采用的搜索方法的特點是盡可能先對縱深方向進行搜索。這種搜索方法稱為深度優先搜索(Depth-First Search)。相應地,用此方法遍歷圖就很自然地稱之為圖的深度優先遍歷

(二)實現思路

1)訪問頂點v;
(2)從v的未被訪問的鄰接點中選取一個頂點w,從w出發進行深度優先遍歷;
(3)重復上述兩步,直至圖中所有和v有路徑相通的頂點都被訪問到。

(三)遞歸實現偽代碼

1)訪問頂點v;visited[v]=1//算法執行前visited[n]=02)w=頂點v的第一個鄰接點;
(3while(w存在)  
           if(w未被訪問)
                   從頂點w出發遞歸執行該算法; 
           w=頂點v的下一個鄰接點;

(四)非遞歸實現偽代碼

1)棧S初始化;visited[n]=0;
(2)訪問頂點v;visited[v]=1;頂點v入棧S
(3while(棧S非空)
            x=棧S的頂元素(不出棧);
            if(存在並找到未被訪問的x的鄰接點w)
                    訪問w;visited[w]=1;
                    w進棧;
            else
                     x出棧;

(五)代碼實現(遞歸+非遞歸)

頭文件

#pragma once
#ifndef _STACK_H
#define _STACK_H
#include <stdio.h>
#include <stdlib.h>

#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0

#define MAXSIZE 100

typedef int ElemType;
typedef int Status;

typedef struct  
{
    ElemType data[MAXSIZE];
    int top;
}Stack;

Status InitStack(Stack* S);
Status Push(Stack* S, ElemType e);
Status Pop(Stack* S, ElemType* e);
Status EmptyStack(Stack S);
ElemType getTop(Stack S);

#endif
stack.h
#pragma once
#ifndef _SEARCH_H
#define _SEARCH_H

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>

#define MAXVEX 100    //最大頂點數
#define INFINITY 0    //用0表示∞

typedef char VertexType;    //頂點類型,字符型A,B,C,D...
typedef int EdgeType;    //邊上權值類型10,15,...

typedef struct
{
    VertexType vers[MAXVEX];    //頂點表
    EdgeType arc[MAXVEX][MAXVEX];    //鄰接矩陣,可看作邊表
    int numVertexes, numEdges;    //圖中當前的頂點數和邊數
}MGraph;

#endif
01search.h

源文件

#include "stack.h"

Status InitStack(Stack* S)
{
    if (!S)
        return ERROR;
    S->top = -1;
    return OK;
}

Status Push(Stack* S, ElemType e)
{
    if (!S)
        return ERROR;
    S->data[++S->top] = e;
    return OK;
}

Status Pop(Stack* S, ElemType* e)
{
    if (!S || !e)
        return ERROR;
    *e = S->data[S->top--];
    return OK;
}

Status EmptyStack(Stack S)
{
    if (S.top != -1)
        return FALSE;
    return TRUE;
}

ElemType getTop(Stack S)
{
    if (S.top == -1)
        return NULL;
    return S.data[S.top];
}
stack.c
#include "01search.h"
#include "stack.h"


bool visited[MAXVEX];    //訪問標志的數組

void CreateMGraph(MGraph* G);  //創建鄰接矩陣

void DFSTraverse(MGraph M);  //深度優先遍歷前會進行初始化
void DFS(MGraph M, int i);    //鄰接矩陣深度優先算法
void DFSInter(MGraph M, int i);    //鄰接矩陣深度非遞歸優先算法
void showGraph(MGraph G);  //顯示矩陣
void CreateMGraph(MGraph* G)
{
    int i, j, k, w;
    //     printf("please input number of vertex and edge:\n");
    //     scanf("%d,%d", &G->numVertexes, &G->numEdges);    //輸入頂點數和邊數
    //     getchar();    //可以獲取回車符
    //     for (i = 0; i < G->numVertexes; i++)    //讀入頂點信息,建立頂點表
    //         scanf("%c", &G->vers[i]);

    G->numVertexes = 9;
    G->numEdges = 15;
    //讀入頂點信息
    G->vers[0] = 'A';
    G->vers[1] = 'B';
    G->vers[2] = 'C';
    G->vers[3] = 'D';
    G->vers[4] = 'E';
    G->vers[5] = 'F';
    G->vers[6] = 'G';
    G->vers[7] = 'H';
    G->vers[8] = 'I';

    //getchar();    //可以獲取回車符
    for (i = 0; i < G->numVertexes; i++)
        for (j = 0; j < G->numVertexes; j++)
            G->arc[i][j] = INFINITY;    //鄰接矩陣初始化

    G->arc[0][1] = 1;
    G->arc[0][5] = 1;
    G->arc[1][2] = 1;
    G->arc[1][8] = 1;
    G->arc[1][6] = 1;
    G->arc[2][3] = 1;
    G->arc[2][8] = 1;
    G->arc[3][4] = 1;
    G->arc[3][7] = 1;
    G->arc[3][6] = 1;
    G->arc[3][8] = 1;
    G->arc[4][5] = 1;
    G->arc[4][7] = 1;
    G->arc[5][6] = 1;
    G->arc[6][7] = 1;

    for (k = 0; k < G->numVertexes; k++)    //讀入numEdges條邊,建立鄰接矩陣
    {
        for (i = k; i < G->numVertexes; i++)
        {
            G->arc[i][k] = G->arc[k][i];    //因為是無向圖,所有是對稱矩陣
        }
    }
}
CreateMGraph創建鄰接矩陣
void showGraph(MGraph G)
{
    for (int i = 0; i < G.numVertexes; i++)
    {
        for (int j = 0; j < G.numVertexes; j++)
            printf("%2d", G.arc[i][j]);
        printf("\n");
    }
}
showGraph顯示鄰接矩陣
void DFSTraverse(MGraph M)
{
    int i;
    for (i = 0; i < M.numVertexes; i++)
        visited[i] = false;    //初始化所有頂點狀態都是未訪問過的未訪問狀態

    for (i = 0; i < M.numVertexes; i++)
        if (!visited[i])    //對未訪問的頂點調用DFS,若是連通圖,只會調用一次
            DFSInter(M, i);
            //DFS(M, i);
}
DFSTraverse深度優先前的初始化和調用
void DFS(MGraph M, int i)    //鄰接矩陣深度優先算法
{
    int j;
    visited[i] = true;    //訪問后我們會一直向后退,去訪問其他結點,不會再訪問這個結點,所有我們不需要再置為false
    printf("%c", M.vers[i]);
    for (j = 0; j < M.numVertexes; j++)
        if (M.arc[i][j] == 1 && !visited[j])    //因為鄰接矩陣是對稱的,所以當我們訪問到下半部時,有一些結點時前面已經訪問過的,我們就不要重復了
            DFS(M, j);    //對未訪問過的鄰接頂點遞歸調用
}
DFS深度優先遞歸實現
void DFSInter(MGraph M, int i)    //鄰接矩陣深度非遞歸優先算法
{
    int j,flag;
    Stack s;
    InitStack(&s);

    visited[i] = true;    //訪問后我們會一直向后退,去訪問其他結點,不會再訪問這個結點,所有我們不需要再置為false
    printf("%c", M.vers[i]);
    Push(&s, i);
    while (!EmptyStack(s))
    {
        i = getTop(s);
        for (j = 0; j < M.numVertexes; j++)
            if (M.arc[i][j] == 1 && !visited[j])    //因為鄰接矩陣是對稱的,所以當我們訪問到下半部時,有一些結點時前面已經訪問過的,我們就不要重復了
            {
                visited[j] = true;
                printf("%c", M.vers[j]);
                flag = 1;
                Push(&s, j);
                break;
            }
        if (!flag)
            Pop(&s, &i);
        flag = 0;
    }
}
DFSInter深度優先非遞歸實現
int main()
{
    MGraph MG;
    CreateMGraph(&MG);
    showGraph(MG);
    DFSTraverse(MG);
    system("pause");
    return 0;
}

注意:深度優先遍歷的方法不止一種,結果也有不同種,當我們使用方法一致時,結果是一樣的,無論遞歸還是迭代

(六)應用:馬踏棋盤

規則

8*8方格,將馬放在任意位置,按照馬走日,進行移動,要求一個方格進入一次,最后使得馬走遍64個方格

回溯法

一條路走到黑,碰壁了再回來一條路走。可以與遞歸很好搭配,也可以和深度優先搜索一起

哈密爾頓路徑

是指結果圖G中的每個頂點,且只經過一次的一條軌跡。如果這條軌跡是一個閉合的路徑(從起點出發不重復的遍歷所有點后仍能回到起始點),那么這條路徑叫做哈密爾頓回路

代碼實現

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#define X 8
#define Y 8

int chess[X][Y];

//找到x,y位置的下一個可走位置,並返回,其中count代表了我們嘗試了多少次,一個有八種走法,所有count從0-7
//按照棋盤顯示的來走
int nextxy(int* x, int* y, int count)
{
    switch (count)
    {
    case 0:
        if ((*x + 2) < X && (*y - 1) >= 0 && !chess[*x + 2][*y - 1])
        {
            *x += 2;
            *y -= 1;
            return 1;
        }
        break;
    case 1:
        if ((*x + 2) < X && (*y + 1) < Y && !chess[*x + 2][*y + 1])
        {
            *x += 2;
            *y += 1;
            return 1;
        }
        break;
    case 2:
        if ((*x + 1) < X && (*y - 2) >= 0 && !chess[*x + 1][*y - 2])
        {
            *x += 1;
            *y -= 2;
            return 1;
        }
        break;
    case 3:
        if ((*x + 1) < X && (*y + 2) < Y && !chess[*x + 1][*y + 2])
        {
            *x += 1;
            *y += 2;
            return 1;
        }
        break;
    case 4:
        if ((*x - 2) >= 0 && (*y - 1) >= 0 && !chess[*x - 2][*y - 1])
        {
            *x -= 2;
            *y -= 1;
            return 1;
        }
        break;
    case 5:
        if ((*x - 2) >= 0 && (*y + 1) < Y && !chess[*x - 2][*y + 1])
        {
            *x -= 2;
            *y += 1;
            return 1;
        }
        break;
    case 6:
        if ((*x - 1) >= 0 && (*y - 2) >= 0 && !chess[*x - 1][*y - 2])
        {
            *x -= 1;
            *y -= 2;
            return 1;
        }
        break;
    case 7:
        if ((*x - 1) >= 0 && (*y + 2) < Y && !chess[*x - 1][*y + 2])
        {
            *x -= 1;
            *y += 2;
            return 1;
        }
        break;
    default:
        break;
    }
    return 0;
}

void ShowChess()
{
    for (int i = 0; i < X;i++)
    {
        for (int j = 0; j < Y;j++)
        {
            printf("%5d", chess[i][j]);
        }
        printf("\n");
    }
}

//深度優先遍歷棋盤
//(x,y)為位置坐標
//第一次調用為我們輸入的參數
//之后就是遞歸進行
//tag代表我們在棋盤上走的正確步數
TravelChessBoard(int x, int y, int tag)
{
    int flag,count=0;
    int x1, y1;
    x1 = x;
    y1 = y;

    chess[x][y] = tag;

    if (tag==X*Y)
    {
        //打印棋盤
        ShowChess();
        return 1;
    }

    flag = nextxy(&x1, &y1, count);    //我們只找了其中一種走法,如果沒有找到,我們下面需要去遍歷其他走法
    while (++count < 8 && !flag)
    {
        flag = nextxy(&x1, &y1, count);
    }

    //找到路徑了
    while (flag)    //我們對這個點周圍的所有可以走的位置都要遍歷一下
    {
        if (TravelChessBoard(x1, y1, tag + 1))
            return 1;
        //若是這條路走不通,我們需要繼續換下一條路,上面的count代表我們走到第幾條路
        x1 = x;
        y1 = y;
        flag = nextxy(&x1, &y1, count);
        while (++count < 8 && !flag)
        {
            flag = nextxy(&x1, &y1, count);
        }
    }

    //如果這個點各個方向都不行,我們就要換點了,先將這個點置為0
    if (0 == flag)
    {
        chess[x][y] = 0;    //因為這里要用到原來x,y,所以我們需要保留他
    }

    return 0;
}

int main()
{
    clock_t start, end;
    int i, j;

    start = clock();
    for (i = 0; i < X; i++)
        for (j = 0; j < Y; j++)
            chess[i][j] = 0;

    if (!TravelChessBoard(2, 0, 1))
        printf("find ways failure!\n");

    end = clock();
    printf("time speed:%f(ms)\n", (double)(end - start)/CLOCKS_PER_SEC);

    system("pause");
    return 0;
}
View Code

二:廣度優先遍歷(鄰接矩陣)

(一)定義

圖的廣度優先遍歷BFS算法是一個分層搜索的過程,和樹的層序遍歷算法類同,它也需要一個隊列以保持遍歷過的頂點順序,以便按出隊的順序再去訪問這些頂點的鄰接頂點。 
我們需要用到隊列去實現廣度優先遍歷

(二)實現思路

1)頂點v入隊列。

(2)當隊列非空時則繼續執行,否則算法結束。

(3)出隊列取得隊頭頂點v;訪問頂點v並標記頂點v已被訪問。

(4)查找頂點v的第一個鄰接頂點col。

(5)若v的鄰接頂點col未被訪問過的,則col入隊列。

(6)繼續查找頂點v的另一個新的鄰接頂點col,轉到步驟(5)。

        直到頂點v的所有未被訪問過的鄰接點處理完。轉到步驟(2)。
廣度優先遍歷圖是以頂點v為起始點,由近至遠,依次訪問和v有路徑相通而且路徑長度為1,2,……的頂點。為了使“先被訪問頂點的鄰接點”先於“后被訪問頂點的鄰接點”被訪問,需設置隊列存儲訪問的頂點。

(三)偽代碼

1)初始化隊列Q;visited[n]=0;

(2)訪問頂點v;visited[v]=1;頂點v入隊列Q;

(3while(隊列Q非空)   

              v=隊列Q的對頭元素出隊;

              w=頂點v的第一個鄰接點;

             while(w存在) 

                     如果w未訪問,則訪問頂點w;

                     visited[w]=1;

                     頂點w入隊列Q;

                     w=頂點v的下一個鄰接點。

(四)代碼實現

#pragma once
#ifndef _QUEUE_H
#define _QUEUE_H

#include <stdio.h>
#include <stdlib.h>

#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0

#define MAXSIZE 100

typedef int ElemType;
typedef int Status;

typedef struct _qNode
{
    ElemType data;
    struct _qNode* next;
}QNode,*QNodePtr;

typedef struct
{
    QNodePtr front,rear;    //隊頭隊尾指針
}LinkQueue;

Status InitQueue(LinkQueue* Q);
Status EnQueue(LinkQueue* Q, ElemType e);
Status DeQueue(LinkQueue* Q, ElemType* e);
Status EmptyQueue(LinkQueue Q);
Status getHead(LinkQueue Q,ElemType* e);

#endif
queue.h
#include "queue.h"


Status InitQueue(LinkQueue* Q)
{
    if (!Q)
        return ERROR;
    Q->front = Q->rear = (QNodePtr)malloc(sizeof(QNode));
    if (!Q->front)
        return ERROR;
    Q->front->next = NULL;
    return OK;
}

Status EnQueue(LinkQueue* Q, ElemType e)
{
    //尾插法
    if (!Q)
        return ERROR;
    QNodePtr q = (QNodePtr)malloc(sizeof(QNode));
    if (!q)
        return ERROR;
    q->data = e;
    q->next = (*Q).rear->next;
    (*Q).rear->next = q;
    Q->rear = q;
    return OK;
}

Status DeQueue(LinkQueue* Q, ElemType* e)
{
    QNodePtr q;
    if (!Q || !e || EmptyQueue(*Q))
        return ERROR;
    q = Q->front->next;
    Q->front->next = q->next;
    *e = q->data;
    if (Q->rear == q)
        Q->rear = Q->front;
    free(q);
    return OK;
}

Status EmptyQueue(LinkQueue Q)
{
    if (!Q.front->next)
        return TRUE;
    return FALSE;
}

Status getHead(LinkQueue Q,ElemType* e)
{
    QNodePtr q;
    if (EmptyQueue(Q))
        return ERROR;
    q = Q.front->next;
    *e = q->data;
    return OK;
}
queue.c
void BFSTraverse(MGraph G)
{
    LinkQueue Q;
    int i,j,k;

    for (i = 0; i < G.numVertexes; i++)
        visited[i] = false;    //初始化所有頂點狀態都是未訪問過的未訪問狀態
    
    InitQueue(&Q);

    for (i = 0; i < G.numVertexes;i++)
    {
        if (!visited[i])    //若是未訪問過的就處理
        {
            visited[i] = true;    //設置當前頂點被訪問過了
            printf("%c", G.vers[i]);    //打印頂點
            EnQueue(&Q, i);    //將此頂點入隊
            while (!EmptyQueue(Q))    //若當前頂點不為空
            {
                DeQueue(&Q, &k);    //出隊,獲取出隊行的相關列
                for (j = 0; j < G.numVertexes;j++)    
                {
                    if (G.arc[k][j]==1&&!visited[j])    //若是該列未被訪問
                    {
                        visited[j] = true;    //標記訪問過
                        printf("%c", G.vers[j]);    //輸出數據
                        EnQueue(&Q, j);    //將其入隊
                    }
                }
            }
        }
    }
}
void BFSTraverse(MGraph G)廣度優先實現

三:鄰接表實現深度優先和廣度優先

隊列和棧的實現代碼如上面一致

#pragma once
#ifndef _SEARCH_H
#define _SEARCH_H

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>

#define MAXVEX 100    //最大頂點數
#define INFINITY 0    //用0表示∞

typedef char VertexType;    //頂點類型,字符型A,B,C,D...
typedef int EdgeType;    //邊上權值類型10,15,...

//鄰接矩陣結構
typedef struct
{
    VertexType vers[MAXVEX];    //頂點表
    EdgeType arc[MAXVEX][MAXVEX];    //鄰接矩陣,可看作邊表
    int numVertexes, numEdges;    //圖中當前的頂點數和邊數
}MGraph;

//鄰接表結構
//邊表結點
typedef struct _EdgeNode
{
    int adjvex;    //存放鄰接點
    struct _EdgeNode* next;    //指向下一個
}EdgeNode;

//頂點表結點
typedef struct _VertexNode
{
    VertexType data;    //頂點域,存儲頂點信息
    EdgeNode* fisrtedge;    //邊表頭指針
}VertexNode, AdjList[MAXVEX];

//鄰接表指針
typedef struct
{
    AdjList adjList;    //鄰接表數組
    int numVertexes, numEdges;    //圖中所存儲的頂點數和邊表數
}GraphAdjList;

#endif
01search.h
#include "01search.h"
#include "stack.h"
#include "queue.h"


bool visited[MAXVEX];    //訪問標志的數組

void CreateMGraph(MGraph* G);
void CreateALGraph(MGraph G, GraphAdjList *GL);//利用鄰接矩陣構建鄰接表

void DFSTraverse(GraphAdjList M);
void DFS(GraphAdjList G, int i);    //鄰接矩陣深度優先算法
void DFSInter(GraphAdjList G, int i);    //鄰接矩陣深度非遞歸優先算法

void BFSTraverse(GraphAdjList G);    //廣度優先遍歷

void showGraph(MGraph G);    //顯示鄰接矩陣
void ShowGraphAdjList(GraphAdjList GL);    //顯示鄰接表
int main()
{
    MGraph MG;
    GraphAdjList GL;
    CreateMGraph(&MG);
    showGraph(MG);
    CreateALGraph(MG, &GL);
    ShowGraphAdjList(GL);
    DFSTraverse(GL);
    BFSTraverse(GL);
    system("pause");
    return 0;
}

void CreateMGraph(MGraph* G)
{
    int i, j, k, w;
    //     printf("please input number of vertex and edge:\n");
    //     scanf("%d,%d", &G->numVertexes, &G->numEdges);    //輸入頂點數和邊數
    //     getchar();    //可以獲取回車符
    //     for (i = 0; i < G->numVertexes; i++)    //讀入頂點信息,建立頂點表
    //         scanf("%c", &G->vers[i]);

    G->numVertexes = 9;
    G->numEdges = 15;
    //讀入頂點信息
    G->vers[0] = 'A';
    G->vers[1] = 'B';
    G->vers[2] = 'C';
    G->vers[3] = 'D';
    G->vers[4] = 'E';
    G->vers[5] = 'F';
    G->vers[6] = 'G';
    G->vers[7] = 'H';
    G->vers[8] = 'I';

    //getchar();    //可以獲取回車符
    for (i = 0; i < G->numVertexes; i++)
        for (j = 0; j < G->numVertexes; j++)
            G->arc[i][j] = INFINITY;    //鄰接矩陣初始化

    G->arc[0][1] = 1;
    G->arc[0][5] = 1;
    G->arc[1][2] = 1;
    G->arc[1][8] = 1;
    G->arc[1][6] = 1;
    G->arc[2][3] = 1;
    G->arc[2][8] = 1;
    G->arc[3][4] = 1;
    G->arc[3][7] = 1;
    G->arc[3][6] = 1;
    G->arc[3][8] = 1;
    G->arc[4][5] = 1;
    G->arc[4][7] = 1;
    G->arc[5][6] = 1;
    G->arc[6][7] = 1;

    for (k = 0; k < G->numVertexes; k++)    //讀入numEdges條邊,建立鄰接矩陣
    {
        for (i = k; i < G->numVertexes; i++)
        {
            G->arc[i][k] = G->arc[k][i];    //因為是無向圖,所有是對稱矩陣
        }
    }
}


//利用鄰接矩陣構建鄰接表
void CreateALGraph(MGraph G, GraphAdjList *GL)
{
    EdgeNode* e;
    int i,j;
    //設置頂點數和邊表數
    GL->numEdges = G.numEdges;
    GL->numVertexes = G.numVertexes;
    //建立頂點表
    for (i = 0; i < G.numVertexes;i++)
    {
        GL->adjList[i].data = G.vers[i];
        GL->adjList[i].fisrtedge = NULL;
    }
    //建立邊表
    for (i = 0; i < G.numVertexes;i++)
    {
        for (j = 0; j < G.numVertexes;j++)
        {
            if (G.arc[i][j]==1)
            {
                e = (EdgeNode*)malloc(sizeof(EdgeNode));
                e->adjvex = j;
                e->next = GL->adjList[i].fisrtedge;
                GL->adjList[i].fisrtedge = e;
            }
        }
    }
}

void DFSTraverse(GraphAdjList G)
{
    int i;
    for (i = 0; i < G.numVertexes; i++)
        visited[i] = false;    //初始化所有頂點狀態都是未訪問過的未訪問狀態

    for (i = 0; i < G.numVertexes; i++)
        if (!visited[i])    //對未訪問的頂點調用DFS,若是連通圖,只會調用一次
            //DFSInter(G, i);
            DFS(G, i);
    printf("\n");
}

void DFS(GraphAdjList G, int i)    //鄰接矩陣深度優先算法
{
    int j;
    EdgeNode* p;
    visited[i] = true;    //訪問后我們會一直向后退,去訪問其他結點,不會再訪問這個結點,所有我們不需要再置為false
    printf("%c", G.adjList[i].data);    //打印頂點
    p = G.adjList[i].fisrtedge;
    while (p)
    {
        if (!visited[p->adjvex])
            DFS(G, p->adjvex);
        p = p->next;
    }
}

void DFSInter(GraphAdjList G, int i)    //鄰接矩陣深度非遞歸優先算法
{
    int j, flag;
    Stack s;
    EdgeNode* e;
    InitStack(&s);

    visited[i] = true;    //訪問后我們會一直向后退,去訪問其他結點,不會再訪問這個結點,所有我們不需要再置為false
    printf("%c", G.adjList[i].data);
    Push(&s, i);
    while (!EmptyStack(s))
    {
        i = getTop(s);
        e = G.adjList[i].fisrtedge;
        while (e)
        {
            if (!visited[e->adjvex])
            {
                printf("%c", G.adjList[e->adjvex].data);
                visited[e->adjvex] = true;
                flag = 1;
                Push(&s, e->adjvex);
                break;
            }
            e = e->next;
        }
        if (!flag)
            Pop(&s, &i);
        flag = 0;
    }
}

void BFSTraverse(GraphAdjList G)
{
    LinkQueue Q;
    int i, j, k;
    EdgeNode* q;

    for (i = 0; i < G.numVertexes; i++)
        visited[i] = false;    //初始化所有頂點狀態都是未訪問過的未訪問狀態

    InitQueue(&Q);

    for (i = 0; i < G.numVertexes; i++)
    {
        if (!visited[i])    //若是未訪問過的就處理
        {
            visited[i] = true;    //設置當前頂點被訪問過了
            printf("%c", G.adjList[i].data);    //打印頂點
            EnQueue(&Q, i);    //將此頂點入隊
            while (!EmptyQueue(Q))    //若當前頂點不為空
            {
                DeQueue(&Q, &k);    //出隊,獲取出隊行的相關列
                q = G.adjList[k].fisrtedge;
                while (q)
                {
                    if (!visited[q->adjvex])
                    {
                        visited[q->adjvex] = true;    //標記訪問過
                        printf("%c", G.adjList[q->adjvex].data);    //輸出數據
                        EnQueue(&Q, q->adjvex);    //將其入隊
                    }
                    q = q->next;
                }
            }
        }
    }
    printf("\n");
}


void showGraph(MGraph G)
{
    for (int i = 0; i < G.numVertexes; i++)
    {
        for (int j = 0; j < G.numVertexes; j++)
            printf("%2d", G.arc[i][j]);
        printf("\n");
    }
}

void ShowGraphAdjList(GraphAdjList GL)
{
    EdgeNode* e;
    for (int i = 0; i < GL.numVertexes;i++)
    {
        printf("%d: ", i);
        e = GL.adjList[i].fisrtedge;
        while (e)
        {
            printf("%5d", e->adjvex);
            e = e->next;
        }
        printf("\n");
    }
}

 


免責聲明!

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



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