数据结构---图---遍历---3

图的遍历和树的遍历类似,我们希望从图中某一顶点出发访遍图中其余顶点,且使每一个顶点仅被访问一次,这一过程就叫做图的遍历。

由于图比较复杂,我们在遍历的过程中把访问过的顶点打上标记,以避免访问多次而不自知。具体办法是设置一个访问数组visited[n],n是图中顶点的个数,初始值为0,访问过后设置为1。

遍历方案:
1.深度优先遍历(DepthFirstSearch),也称深度优先搜索,简称DFS
2.广度优先遍历(BreadthFirstSearch),又称为广度优先搜索,简称BFS

1.深度优先遍历
在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述

深度优先遍历其实就是一个递归的过程,就像是一棵树的前序遍历。
它从图中某个顶点v出发,访问此顶点,然后从v的未被访问的邻接点出发深度优先遍历图,直至图中所有和v有路径相通的顶点都被访问到。对于非连通图,只需要对它的连通分量分别进行深度优先遍历,即在先前一个顶点进行一次深度优先遍历后,若图中有顶点未被访问,则另选图中一个未曾被访问的顶点作起始点,重复上述过程,直至图中所有顶点都被访问到为止。

    private bool[] visited;

    /// <summary>
    /// 邻接矩阵的深度优先遍历
    /// </summary>
    /// <param name="gl"></param>
    public void DFSTraverse()
    {
        visited = new bool[maxNumVertex];

        for (int i = 0; i < vertexs.Length; i++)
        {
            visited[i] = false; //初始化所有顶点都是未访问的状态
        }

        for (int i = 0; i < vertexs.Length; i++)
        {
            //对未访问过的顶点调用DFS,若是连通图,只会执行一次
            if (!visited[i])
            {
                DFS(i);
            }
        }
    }

    /// <summary>
    /// 邻接矩阵的深度优先递归算法
    /// </summary>
    /// <param name="gl"></param>
    /// <param name="i"></param>
    private void DFS(int i)
    {
        visited[i] = true;

        //这里对顶点的操作,这里简单的打印
        Debug.Log(vertexs[i]);

        for (int j = 0; j < vertexs.Length; j++)
        {
            //edges[i, j] == 1表示两顶点是连通的
            //如果是权值,可以判断: edges[i,j]!=0 && edges[i,j]! = MaxValue
            //MaxValue自己定,可以用int.MaxValue,long.MaxValue,float.MaxValue等
            //具体权值用int long 还是float自己定
            if (edges[i, j] == 1 && !visited[j])
            {
                DFS(j);
            }
        }
    }
}
    private bool[] visited;  

    /// <summary>
    /// 邻接表的深度优先遍历
    /// </summary>   
    public void DFSTraverse()
    {
        visited = new bool[adjacencyArr.Length];

        for (int i = 0; i < adjacencyArr.Length; i++)
        {
            visited[i] = false; //初始化所有顶点都是未访问的状态
        }

        for (int i = 0; i < adjacencyArr.Length; i++)
        {
            //对未访问过的顶点调用DFS,若是连通图,只会执行一次
            if (!visited[i])
            {
                DFS(i);
            }
        }
    }

    /// <summary>
    /// 邻接表的深度优先递归算法
    /// </summary>
    /// <param name="gl"></param>
    /// <param name="i"></param>
    private void DFS(int i)
    {
        visited[i] = true;

        //这里对顶点的操作,这里简单的打印
        Debug.Log(adjacencyArr[i].data);

        EdgeNode temp = adjacencyArr[i].firstEdge;

        while (temp != null)
        {
            if (!visited[temp.adjvex])
                DFS(temp.adjvex);
            temp = temp.next;
        }
    }
}

在这里插入图片描述
2.广度优先遍历:

图的深度优先遍历类似树的前序遍历。
图的广度优先遍历类似树的层序遍历。

 	/// <summary>
    /// 邻接矩阵:广度优先遍历
    /// </summary>
    /// <param name="graph"></param>
    public void BFSTraverse()
    {
        Queue<int> queue = new Queue<int>();  //初始化辅助队列
        visited = new bool[maxNumVertex];

        for (int i = 0; i < vertexs.Length; i++)
        {
            visited[i] = false;
        }

        for (int i = 0; i < vertexs.Length; i++)   //对每一个顶点做循环
        {
            if (!visited[i])            //若是未访问过就处理
            {
                visited[i] = true;      //设置当前顶点访问过

                //这里对顶点的操作,这里简单的打印
                Debug.Log(vertexs[i]);

                queue.Enqueue(i);       //将此顶点入队列

                while (queue.Count > 0) //当前队列有元素
                {
                    i = queue.Dequeue();    //出队列

                    for (int j = 0; j < vertexs.Length; j++)
                    {
                        //edges[i, j] == 1表示两顶点是连通的
                        //如果是权值,可以判断: edges[i,j]!=0 && edges[i,j]! = MaxValue
                        //MaxValue自己定,可以用int.MaxValue,long.MaxValue,float.MaxValue等
                        //具体权值用int long 还是float自己定
                        if (edges[i, j] == 1 && !visited[j])
                        {
                            visited[j] = true;

                            //这里对顶点的操作,这里简单的打印
                            Debug.Log(vertexs[j]);

                            queue.Enqueue(j);
                        }
                    }
                }
            }
        }
    }
	/// <summary>
    /// 邻接表:广度优先遍历
    /// </summary>
    /// <param name="gl"></param>
    public void BFSTraverse()
    {
        visited = new bool[adjacencyArr.Length];

        Queue<int> queue = new Queue<int>();  //初始化辅助队列

        EdgeNode p;

        for (int i = 0; i < adjacencyArr.Length; i++)
        {
            visited[i] = false;
        }

        for (int i = 0; i < adjacencyArr.Length; i++)   //对每一个顶点做循环
        {
            if (!visited[i])            //若是未访问过就处理
            {
                visited[i] = true;      //设置当前顶点访问过

                //这里对顶点的操作,这里简单的打印
                Debug.Log(adjacencyArr[i].data);

                queue.Enqueue(i);       //将此顶点入队列

                while (queue.Count > 0) //当前队列有元素
                {
                    i = queue.Dequeue();    //出队列

                    p = adjacencyArr[i].firstEdge;   //找到当前顶点边表链表头指针

                    while (p != null)
                    {
                        //此顶点未访问过
                        if (!visited[p.adjvex])
                        {
                            visited[p.adjvex] = true;

                            //这里对顶点的操作,这里简单的打印
                            Debug.Log(adjacencyArr[p.adjvex].data);

                            queue.Enqueue(p.adjvex);        //将此顶点入队列
                        }

                        p = p.next;     //指针指向下一个邻接点
                    }
                }
            }
        }
    }

深度优先遍历与广度优先遍历算法,在时间复杂度上是一样的,不同之处仅仅对顶点访问的顺序不同。
在全图遍历上没有优劣之分,只是视不同的情况选择不同的算法。

在这里插入图片描述
源码:

邻接矩阵:

/// <summary>
/// 泛型邻接矩阵
/// </summary>
public class AdjacentMatrix<T>
{
    #region 数据
    //数据
    private T[] vertexs;        //顶点数组:数据
    private int[,] edges;       //边数组:权值  
    private int maxNumVertex;   //最大顶点数                              
    #endregion

    #region 操作
    /// <summary>
    /// 创建无向网图的邻接矩阵表示
    /// </summary>    
    /// <param name="vertexs">顶点数据</param>
    /// <param name="edges">边数据:权值</param>   
    public AdjacentMatrix(T[] vertexs, int[,] edges)
    {
        maxNumVertex = vertexs.Length;
        this.vertexs = new T[maxNumVertex];
        this.edges = new int[maxNumVertex, maxNumVertex];
        Array.Copy(vertexs, this.vertexs, vertexs.Length);
        Array.Copy(edges, this.edges, edges.Length);
    }

    /// <summary>
    /// 创建无向网图的邻接矩阵表示
    /// </summary>    
    /// <param name="vertexs">顶点数据</param>
    /// <param name="edges">边数据:权值</param>
    /// <param name="maxNumVertex">最大顶点数组容量</param>
    public AdjacentMatrix(T[] vertexs, int[,] edges, int maxNumVertex)
    {
        maxNumVertex = maxNumVertex < vertexs.Length ? vertexs.Length : maxNumVertex;

        this.vertexs = new T[maxNumVertex];
        this.edges = new int[maxNumVertex, maxNumVertex];
        this.maxNumVertex = maxNumVertex;
        Array.Copy(vertexs, this.vertexs, vertexs.Length);
        Array.Copy(edges, this.edges, edges.Length);
    }

    private bool[] visited;

    /// <summary>
    /// 邻接矩阵的深度优先遍历
    /// </summary>
    /// <param name="gl"></param>
    public void DFSTraverse()
    {
        visited = new bool[maxNumVertex];

        for (int i = 0; i < vertexs.Length; i++)
        {
            visited[i] = false; //初始化所有顶点都是未访问的状态
        }

        for (int i = 0; i < vertexs.Length; i++)
        {
            //对未访问过的顶点调用DFS,若是连通图,只会执行一次
            if (!visited[i])
            {
                DFS(i);
            }
        }
    }

    /// <summary>
    /// 邻接矩阵的深度优先递归算法
    /// </summary>
    /// <param name="gl"></param>
    /// <param name="i"></param>
    private void DFS(int i)
    {
        visited[i] = true;

        //这里对顶点的操作,这里简单的打印
        Debug.Log(vertexs[i]);

        for (int j = 0; j < vertexs.Length; j++)
        {
            //edges[i, j] == 1表示两顶点是连通的
            //如果是权值,可以判断: edges[i,j]!=0 && edges[i,j]! = MaxValue
            //MaxValue自己定,可以用int.MaxValue,long.MaxValue,float.MaxValue等
            //具体权值用int long 还是float自己定
            if (edges[i, j] == 1 && !visited[j])
            {
                DFS(j);
            }
        }
    }

    /// <summary>
    /// 邻接矩阵:广度优先遍历
    /// </summary>
    /// <param name="graph"></param>
    public void BFSTraverse()
    {
        Queue<int> queue = new Queue<int>();  //初始化辅助队列
        visited = new bool[maxNumVertex];

        for (int i = 0; i < vertexs.Length; i++)
        {
            visited[i] = false;
        }

        for (int i = 0; i < vertexs.Length; i++)   //对每一个顶点做循环
        {
            if (!visited[i])            //若是未访问过就处理
            {
                visited[i] = true;      //设置当前顶点访问过

                //这里对顶点的操作,这里简单的打印
                Debug.Log(vertexs[i]);

                queue.Enqueue(i);       //将此顶点入队列

                while (queue.Count > 0) //当前队列有元素
                {
                    i = queue.Dequeue();    //出队列

                    for (int j = 0; j < vertexs.Length; j++)
                    {
                        //edges[i, j] == 1表示两顶点是连通的
                        //如果是权值,可以判断: edges[i,j]!=0 && edges[i,j]! = MaxValue
                        //MaxValue自己定,可以用int.MaxValue,long.MaxValue,float.MaxValue等
                        //具体权值用int long 还是float自己定
                        if (edges[i, j] == 1 && !visited[j])
                        {
                            visited[j] = true;

                            //这里对顶点的操作,这里简单的打印
                            Debug.Log(vertexs[j]);

                            queue.Enqueue(j);
                        }
                    }
                }
            }
        }
    }
    #endregion
}

邻接表:

	/// <summary>
    /// 边表结点
    /// </summary>
    public class EdgeNode
    {
        public int adjvex;      //邻接点域,存储该顶点对应的下标
        public int weight;      //用于存储权值,对于非网图可以不需要(关键路径需要权值)
        public EdgeNode next;   //链域,指向下一个邻接点
    }

    /// <summary>
    /// 顶点表结点
    /// </summary>
    public class VertexNode<T>
    {
        public int inDegree;            //入度:拓扑排序用
        public T data;                  //顶点域,存储顶点信息
        public EdgeNode firstEdge;      //边表头指针
    }

/// <summary>
/// 泛型邻接表:一维数组 + 链表(数组和链表自行提供)
/// </summary>
public class AdjacencyList<T>
{
    private VertexNode<T>[] adjacencyArr;   //顶点表

    /// <summary>
    /// 说明:没有按书上写,需要的数据自行提供
    /// </summary>
    /// <param name="vertexData">顶点数据</param>    
    public AdjacencyList(VertexNode<T>[] vertexData)
    {
        adjacencyArr = vertexData;
    }

    /// <summary>
    /// 说明:没有按书上写,需要的数据自行提供,包括顶点数据和边表数据
    /// </summary>
    /// <param name="vertexData">顶点数据</param>
    /// <param name="edgeData">边表数据</param>
    public AdjacencyList(VertexNode<T>[] vertexData, EdgeNode[] edgeData)
    {
        adjacencyArr = new VertexNode<T>[vertexData.Length];

        for (int i = 0; i < vertexData.Length; i++)                //建立顶点表
        {
            adjacencyArr[i] = vertexData[i];                 //顶点数据
            adjacencyArr[i].firstEdge = edgeData[i];         //建立边表
        }
    }

    private bool[] visited;

    #region 操作

    /// <summary>
    /// 邻接表的深度优先遍历
    /// </summary>   
    public void DFSTraverse()
    {
        visited = new bool[adjacencyArr.Length];

        for (int i = 0; i < adjacencyArr.Length; i++)
        {
            visited[i] = false; //初始化所有顶点都是未访问的状态
        }

        for (int i = 0; i < adjacencyArr.Length; i++)
        {
            //对未访问过的顶点调用DFS,若是连通图,只会执行一次
            if (!visited[i])
            {
                DFS(i);
            }
        }
    }

    /// <summary>
    /// 邻接表的深度优先递归算法
    /// </summary>
    /// <param name="gl"></param>
    /// <param name="i"></param>
    private void DFS(int i)
    {
        visited[i] = true;

        //这里对顶点的操作,这里简单的打印
        Debug.Log(adjacencyArr[i].data);

        EdgeNode temp = adjacencyArr[i].firstEdge;

        while (temp != null)
        {
            if (!visited[temp.adjvex])
                DFS(temp.adjvex);
            temp = temp.next;
        }
    }

    /// <summary>
    /// 邻接表:广度优先遍历
    /// </summary>
    /// <param name="gl"></param>
    public void BFSTraverse()
    {
        visited = new bool[adjacencyArr.Length];

        Queue<int> queue = new Queue<int>();  //初始化辅助队列

        EdgeNode p;

        for (int i = 0; i < adjacencyArr.Length; i++)
        {
            visited[i] = false;
        }

        for (int i = 0; i < adjacencyArr.Length; i++)   //对每一个顶点做循环
        {
            if (!visited[i])            //若是未访问过就处理
            {
                visited[i] = true;      //设置当前顶点访问过

                //这里对顶点的操作,这里简单的打印
                Debug.Log(adjacencyArr[i].data);

                queue.Enqueue(i);       //将此顶点入队列

                while (queue.Count > 0) //当前队列有元素
                {
                    i = queue.Dequeue();    //出队列

                    p = adjacencyArr[i].firstEdge;   //找到当前顶点边表链表头指针

                    while (p != null)
                    {
                        //此顶点未访问过
                        if (!visited[p.adjvex])
                        {
                            visited[p.adjvex] = true;

                            //这里对顶点的操作,这里简单的打印
                            Debug.Log(adjacencyArr[p.adjvex].data);

                            queue.Enqueue(p.adjvex);        //将此顶点入队列
                        }

                        p = p.next;     //指针指向下一个邻接点
                    }
                }
            }
        }
    }
    #endregion
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值