有向图基本算法 -- 遍历算法

1. 图的表示

2. 有向图的遍历算法:深度优先

3. 有向图的遍历算法:广度优先

4 代码反思

5. 下载 

1. 图的表示  

1.1 图的定义

图G定义为V和E的集合G={V, E},其中V表示图中的所有的顶点集合,E表示的是G中的所有的边的集合。图按照E中的元素是否有方向,分为有向图和无向图。 

1.2 图的表示方法

上面给出的数学上图的定义,那么在计算机中如何表示图?通常意义上,有下面的两种方法:邻接表和邻接矩阵表示法。

无向图的邻接表和邻接矩阵表示如下所示:

 

有向图的邻接表和邻接矩阵表示如下所示:

 

根据上面的表示方法,下面定义图G的这种数据结构(邻接表),首先定义图的顶点GraphVertex:

// 顶点显示的符号
        public char Symbol { get; set; }
        
        // 顶点当前颜色
        public VertexColor Color { get; set; }
        
        // 顶点和开始节点之间的距离
        public int Distance { get; set; }
        
        // 广度遍历父节点
        public GraphVertex Parent { get; set; }
        
        // 深度优先搜索中的开始时间
        public int StartTime { get; set; }
        
        // 深度优先搜索中的结束时间
        public int FinishTime { get; set; }
        // 顶点对应的边

        public List<GraphEdge> FollowEdges { get; set; } 

定义图G的边的数据结构:

  // 边开始顶点,在邻接表的存储中其实没有必要存储
        public GraphVertex From { get; set; }
        // 结束顶点
        public GraphVertex To { get; set; } 
        // 边权重

        public int Weight { get; set; } 

定义图:

// 数据成员,这里假设的是顶点的symbol是各个不相同的
        private Hashtable graph = 
            new Hashtable();

        private int time = 0; 

整体上的结构如下:

 

2. 有向图的深度优先算法 

2.1 基本算法

其中d表明的是某个节点第一次被发现的时间点,f表明从节点出发的全部节点已经被发现的时间。  

 

2.2 设计实现 


  // 深度优先遍历算法
        public void DepthFirstVisit(GraphVertex v)
        {
            // 刚刚被发现,颜色为gray
            Console.WriteLine(v.Symbol);
            v.Color = VertexColor.GRAY;
            this.time++;
            // 开始时间
            v.StartTime = this.time;
            foreach (GraphEdge edge in v.FollowEdges)
            {
                // 还未被发现
                if (edge.To.Color == VertexColor.WHITE)
                {
                    edge.To.Parent = v;
                    DepthFirstVisit(edge.To);
                }
            }
            
            // 如果边都已经发现完成
            v.Color = VertexColor.BLACK;
            this.time++;
            v.FinishTime = this.time;
            
        }
        public void DepthFirstTravel()
        {
            // 全局时间变量
            this.time = 0;
            // 初始化
            GraphVertex v;
            foreach (DictionaryEntry e in this.graph)
            {
                v = (GraphVertex)e.Value;
                v.Color = VertexColor.WHITE;
                v.Parent = null;
            }
            // 递归调用
            // 队所有的顶点
            foreach (DictionaryEntry e in this.graph)
            {
                v = (GraphVertex)e.Value;
                // 顶点为白色
                if (v.Color == VertexColor.WHITE)
                {
                    DepthFirstVisit(v);
                }
            }

        } 


3. 有向图的遍历算法:广度优先 

3.1 基本算法

其中color域表示的是当前某个节点被发现的状态。如果是white表明没有被发现,gray表示当前顶点已经被发现,但是从该节点出发的节点还没有被全部发现。parent域定义的是在搜索算法时父节点。distance域表明的是从节点s到某个发现的节点v的路径距离。


3.2 设计实现 


// 广度优先遍历算法,同时生成广度优先树
        public void BreadthFirstTravel(GraphVertex s)
        {
            // 初始化所有节点
            GraphVertex v;
            foreach (DictionaryEntry e in this.graph)
            {
                v = (GraphVertex)e.Value;
                v.Color = VertexColor.WHITE;
                v.Distance = int.MaxValue;
                v.Parent = null;
            }
            // 发现第一个节点
            s.Color = VertexColor.GRAY;
            s.Distance = 0;
            s.Parent = null;
            // 初始化队列
            Queue context = 
                new Queue();
            context.Enqueue(s);
            // 如果队列不空的话
            while (context.Count != 0)
            {
                // 队首元素出队
                v = context.Dequeue() as GraphVertex;
                Console.WriteLine(v.Symbol);
                // 遍历v的节点
                foreach (GraphEdge item in v.FollowEdges)
                {
                    if ( item.To.Color == VertexColor.WHITE)
                    {
                        item.To.Color = VertexColor.GRAY;
                        item.To.Distance = v.Distance + 1;
                        item.To.Parent = v;
                        context.Enqueue(item.To);
                    }
                }
                v.Color = VertexColor.BLACK;
            }

        } 


4. 代码反思 

上面的搜索代码结构是比较典型的搜索结构:首先定义队列或者是栈来保存程序运行状态,如果容器不空,取出元素,然后对取出的元素做一些处理。 

5. 代码下载 

/Files/xuqiang/DirectedGraph1.rar 

posted @ 2011-03-28 14:06  qiang.xu  阅读(54677)  评论(3编辑  收藏  举报