數據結構(五)——圖的遍歷(遞歸)

圖的遍歷有多種方式,但是這裏從數據結構基礎出發,還是隻介紹基礎的兩種方式,深度優先遍歷和廣度優先遍歷。

深度優先遍歷

圖的深度優先搜索(Depth First Search),和樹的前序遍歷比較類似。

它的思想:假設初始狀態是圖中所有頂點均未被訪問,則從某個頂點v出發,首先訪問該頂點,然後依次從它的各個未被訪問的鄰接點出發深度優先搜索遍歷圖,直至圖中所有和v有路徑相通的頂點都被訪問到。 若此時尚有其他頂點未被訪問到,則另選一個未被訪問的頂點作起始點,重複上述過程,直至圖中所有頂點都被訪問到爲止。

顯然,深度優先搜索是一個遞歸的過程。一言以蔽之:“一路走到頭,不撞南牆不回頭”。

代碼實現(鄰接矩陣):

public void DFSSelf() {
    boolean[] beTraversed = new boolean[size];
    beTraversed[0] = true;
    System.out.print(vertexs[0] + " ");
    DFSSelf(0, beTraversed);//從頭節點開始
}

public void DFSSelf(int x, boolean[] beTraversed) {
    int y = 0;
    while (y <= size - 1) {
        if (matrix[x][y] != 0 && beTraversed[y] == false) { //遍歷與當前節點有邊的節點
            beTraversed[y] = true;
            System.out.print(vertexs[y] + " ");//遍歷
            DFSSelf(y, beTraversed);//遞歸進行深度遍歷
        }
        y++;
    }
}

鄰接表(思路完全一樣,只是獲取關係節點的方式不一樣):

public void DFS() {
    boolean[] beTraversed = new boolean[size];
    beTraversed[getPosition(vertexList[0].ch)] = true;
    DFS(beTraversed, vertexList[0]);
}

/**
 * 深度優先遍歷
 *
 * @param beTraversed
 * @param temp
 */
public void DFS(boolean[] beTraversed, Vertex temp) {
    System.out.print(temp.ch + " ");
    beTraversed[getPosition(temp.ch)] = true;
    while (temp != null) {
        if (beTraversed[getPosition(temp.ch)] == false) {
            DFS(beTraversed, vertexList[getPosition(temp.ch)]);
        }
        temp = temp.next;
    }
}

廣度優先遍歷

廣度優先搜索算法(Breadth First Search),又稱爲”寬度優先搜索”或”橫向優先搜索”,簡稱BFS。

它的思想是:從圖中某頂點v出發,在訪問了v之後依次訪問v的各個未曾訪問過的鄰接點,然後分別從這些鄰接點出發依次訪問它們的鄰接點,並使得“先被訪問的頂點的鄰接點先於後被訪問的頂點的鄰接點被訪問,直至圖中所有已被訪問的頂點的鄰接點都被訪問到。如果此時圖中尚有頂點未被訪問,則需要另選一個未曾被訪問過的頂點作爲新的起始點,重複上述過程,直至圖中所有頂點都被訪問到爲止。

換句話說,廣度優先搜索遍歷圖的過程是以v爲起點,由近至遠,依次訪問和v有路徑相通且路徑長度爲1,2…的頂點。

代碼實現(鄰接矩陣):

public void BFSSelf() {
    boolean[] beTraversed = new boolean[size];
    beTraversed[0] = true;
    System.out.print(vertexs[0] + " ");
    BFSSelf(0, beTraversed, new LinkedList<>());
}

/**
 * 廣度優先搜索遍歷
 *
 * @param x
 * @param beTraversed
 */
public void BFSSelf(int x, boolean[] beTraversed, LinkedList<Character> list) {
    int y = 0;
    while (y <= size - 1) {
        if (matrix[x][y] != 0 && beTraversed[y] == false) { //依次將與當前節點有聯繫的節點遍歷,然後入隊。
            beTraversed[y] = true;
            System.out.print(vertexs[y] + " ");
            list.add(vertexs[y]);
        }
        y++;
    }
    if (!list.isEmpty()) { //出隊進行遞歸操作
        Character node = list.pop();
        int pos = getPosition(node);
        BFSSelf(pos, beTraversed, list);
    }
}

鄰接表

public void BFS(){
    boolean[] beTraversed = new boolean[size];
    beTraversed[getPosition(vertexList[0].ch)] = true;
    System.out.print(vertexList[0].ch+" ");
    int startPos = getPosition(vertexList[0].ch);
    BFS(startPos,beTraversed);
}

/**
 * 廣度優先搜素遍歷
 * @param beTraversed
 */
public void BFS(int x,boolean[] beTraversed){
    Vertex temp = vertexList[x];
    LinkedList<Vertex> list = new LinkedList<>();
    while(temp!=null){
        if(beTraversed[getPosition(temp.ch)] == false){
            System.out.print(temp.ch+" ");
            beTraversed[getPosition(temp.ch)] = true;
            list.add(vertexList[getPosition(temp.ch)]);
        }
        temp = temp.next;
    }

    while(!list.isEmpty()){
        Vertex node = list.pop();
        int pos = getPosition(node.ch);
        BFS(pos,beTraversed);
    }
}
發佈了134 篇原創文章 · 獲贊 37 · 訪問量 9萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章