數據結構和算法學習筆記七:圖的搜索


一.簡介

  圖的搜索是指對圖中的頂點進行搜索,指定某個頂點,搜索出這個頂點能訪問到的所有頂點.圖的搜索分為深度優先和廣度優先兩種,深度優先是指先沿着一條搜索線進行搜索,在搜索到已經搜索過的頂點時再回退到上一個頂點繼續深入搜索這個頂點的所有分支...一直回退直到回退到起始頂點,顯然這種搜索方式是遞歸結構.廣度搜索是指先搜索當前頂點,再搜索這個頂點的所有關聯頂點,再繼續搜索關聯頂點的關聯頂點...當然,已經搜索過的頂點不再重復搜索.

  圖的搜索實現我寫成了工具類,實現了基於鄰接矩陣和鄰接表結構的圖的兩種搜索方案.圖的結構實現使用的是上一篇博客:;數據結構和算法學習筆記六:圖的相關實現 - movin2333 - 博客園 (cnblogs.com)中的圖的實現.

二.深度優先搜索:

/************************************
* 創建人:movin
* 創建時間:2021/7/4 8:41:02
* 版權所有:個人
***********************************/
using System;
using System.Collections.Generic;
using System.Text;

namespace GraphCore
{
    /// <summary>
    /// 深度優先遍歷算法工具
    /// </summary>
    public class DepthFirstSearchUtil
    {
        /// <summary>
        /// 鄰接矩陣的深度優先遍歷
        /// 訪問與給定下標頂點相連通的所有頂點
        /// 無向圖
        /// </summary>
        /// <param name="graph">鄰接矩陣形式存儲的圖</param>
        /// <param name="whenVisited">當遍歷到頂點后的回調</param>
        /// <param name="whenVisited">記錄頂點是否訪問過的數組</param>
        /// <param name="index">當前遍歷的頂點下標,默認0</param>
        public static void DFS(AdjacencyMatrixGraph graph,Action<AdjacencyMatrixVertex> whenVisited,bool[] visited = null,int index = 0)
        {
            if(visited == null)
            {
                visited = new bool[graph.Count];
            }
            if(index >= graph.Count || index < 0)
            {
                return;
            }
            visited[index] = true;
            if(whenVisited != null)
            {
                whenVisited(graph.vertices[index]);
            }
            for(int i = 0;i < graph.adjacencyMatrix.GetLength(1); i++)
            {
                //在滿足條件時才會進入遞歸,否則終止遞歸
                if(graph.adjacencyMatrix[index,i] != 0 && !visited[i])
                {
                    DFS(graph, whenVisited, visited, i);
                }
            }
        }
        /// <summary>
        /// 鄰接表的深度優先遍歷
        /// 訪問與給定下標頂點相連通的所有頂點
        /// 無向圖
        /// </summary>
        /// <param name="graph">鄰接表形式存儲的圖</param>
        /// <param name="whenVisited">當遍歷到頂點后的回調</param>
        /// <param name="visited">記錄頂點是否訪問過的數組</param>
        /// <param name="index">當前遍歷的頂點下標,默認0</param>
        public static void DFS(AdjacencyListGraph graph, Action<AdjacencyListVertex> whenVisited, bool[] visited = null, int index = 0)
        {

            if (visited == null)
            {
                visited = new bool[graph.Count];
            }
            if (index >= graph.Count || index < 0)
            {
                return;
            }
            //遞歸終止條件
            if (visited[index])
            {
                return;
            }
            visited[index] = true;
            if (whenVisited != null)
            {
                whenVisited(graph.vertices[index]);
            }
            AdjacencyListEdgeNode node = graph.vertices[index].firstEdge;
            //遍歷鏈表的所有結點並遞歸
            while(node != null)
            {
                DFS(graph, whenVisited, visited, node.vertexIndex);
                node = node.next;
            }
        }
    }
}

三.廣度優先搜索:

/************************************
* 創建人:movin
* 創建時間:2021/7/4 15:23:35
* 版權所有:個人
***********************************/
using System;
using System.Collections.Generic;
using System.Text;

namespace GraphCore
{
    /// <summary>
    /// 廣度優先遍歷算法工具
    /// </summary>
    public class BreadthFirstSearchUtil
    {
        /// <summary>
        /// 鄰接矩陣的廣度優先遍歷
        /// 訪問與給定下標頂點相連通的所有頂點
        /// 無向圖
        /// </summary>
        /// <param name="graph"></param>
        /// <param name="whenVisited">訪問到頂點后的回調</param>
        /// <param name="startIndex">開始訪問的頂點下標</param>
        public static void BFS(AdjacencyMatrixGraph graph, Action<AdjacencyMatrixVertex> whenVisited, int startIndex = 0)
        {
            if(startIndex >= graph.Count || startIndex < 0)
            {
                return;
            }
            //頂點是否訪問的標識
            bool[] visited = new bool[graph.Count];
            //是否遍歷頂點的關聯頂點的標識
            bool[] searched = new bool[graph.Count];
            //存儲所有訪問到的頂點的棧
            Queue<AdjacencyMatrixVertex> vertexQueue = new Queue<AdjacencyMatrixVertex>();
            //輔助棧,存儲之前訪問到的所有頂點的對應下標,和存儲頂點的棧同存同取
            Queue<int> indexQueue = new Queue<int>();
            //開始結點入棧
            vertexQueue.Enqueue(graph.vertices[startIndex]);
            indexQueue.Enqueue(startIndex);
            visited[startIndex] = true;

            //所有頂點出棧
            while (vertexQueue.Count > 0)
            {
                AdjacencyMatrixVertex vertex = vertexQueue.Dequeue();
                int currentIndex = indexQueue.Dequeue();
                //訪問頂點
                if (whenVisited != null)
                {
                    whenVisited(vertex);
                }
                //沒有遍歷過的情況下
                if (!searched[currentIndex])
                {
                    //遍歷此下標頂點的所有關聯頂點,沒有訪問過的入棧
                    for (int i = 0; i < graph.adjacencyMatrix.GetLength(1); i++)
                    {
                        if (graph.adjacencyMatrix[currentIndex, i] != 0 && !visited[i])
                        {
                            vertexQueue.Enqueue(graph.vertices[i]);
                            indexQueue.Enqueue(i);
                            visited[i] = true;
                        }
                    }
                    searched[currentIndex] = true;
                }
                
            }
        }
        /// <summary>
        /// 鄰接矩陣的廣度優先遍歷
        /// 訪問與給定下標頂點相連通的所有頂點
        /// 無向圖
        /// </summary>
        /// <param name="graph"></param>
        /// <param name="whenVisited">訪問到頂點之后的回調</param>
        /// <param name="startIndex">開始訪問的頂點下標</param>
        public static void BFS(AdjacencyListGraph graph, Action<AdjacencyListVertex> whenVisited, int startIndex = 0)
        {
            if (startIndex >= graph.Count || startIndex < 0)
            {
                return;
            }
            //頂點是否訪問的標識
            bool[] visited = new bool[graph.Count];
            //是否遍歷頂點的關聯頂點的標識
            bool[] searched = new bool[graph.Count];
            //存儲所有訪問到的頂點的棧
            Queue<AdjacencyListVertex> vertexQueue = new Queue<AdjacencyListVertex>();
            //輔助棧,存儲之前訪問到的所有頂點的對應下標,和存儲頂點的棧同存同取
            Queue<int> indexQueue = new Queue<int>();
            //開始結點入棧
            vertexQueue.Enqueue(graph.vertices[startIndex]);
            indexQueue.Enqueue(startIndex);
            visited[startIndex] = true;

            while(vertexQueue.Count > 0)
            {
                AdjacencyListVertex vertex = vertexQueue.Dequeue();
                int currentIndex = indexQueue.Dequeue();
                if(whenVisited != null)
                {
                    whenVisited(vertex);
                }
                if (!searched[currentIndex])
                {
                    //訪問邊表,將沒有訪問過的頂點加入隊列
                    AdjacencyListEdgeNode node = vertex.firstEdge;
                    do
                    {
                        int vertexIndex = node.vertexIndex;
                        if (!visited[vertexIndex])
                        {
                            vertexQueue.Enqueue(graph.vertices[vertexIndex]);
                            indexQueue.Enqueue(vertexIndex);
                            visited[vertexIndex] = true;
                        }
                        node = node.next;
                    }
                    while (node != null);
                    searched[currentIndex] = true;
                }
            }
        }
    }
}

 


免責聲明!

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



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