图的数据结构和基础算法c++

原创、转载请注明出处

一、表示方法、基本结构

大致有2种表示图的方法:

1、给定一个矩阵,上面一些符号,这个图就是这个样子。例如:

    

2、给出路径。例如:

      ●1 2、2 3、4 3、3 5(1到2有路径)

      ●01000

        00100

        00001

        00100

        00000(意义同上)

二、基本算法(dfs、bfs)

解决图的问题时,关键在于当前步如何处理且走过的结点或路径要标记。

 

图最基本的算法是dfs和bfs,dfs用递归实现,bfs用队列实现,dfs易于编写。

 

dfs既然是递归,也就有子问题和边界条件,在图中体现出来就是,当前步如何走(子问题)、什么时候不能再走了(边界问题)。(子问题想出来递归就好写了)

 

bfs把要访问结点放到队列中,队列尾进头出,每次访问头结点,并把头节点相连的结点加入队列末端,再把头节点从队列头拿出舍弃。这样就能实现宽度顺序的访问。

三、基本问题

1、连通块 

     uva572 连通块dfs    http://www.cnblogs.com/mu-ye/p/7644021.html

2、最短路

     记录路径的长度,在能到达目的地的路径中选最短的。若要打印路径,则搜路径时同时记录路径。路径问题可根据具体问题记录相关信息,最后比较。

 (个人感觉,解决连通块时,没有浪费的搜索(因为标记),而解决最短路时,搜了一些没用的路(标记不能解决))

四、图论基础算法

1、拓扑排序(有向无环图)

       和普通排序不同的是,拓扑排序不知道元素的具体大小,只有元素间的部分关系,最后的结果是把这些元素串起来。(拓扑排序是图论中的一个问题:把一个图的所有结点排序,使得每一条有向边(u,v)对应的u都排在v的前面)

       首先,我们知道,拓扑排序最终要确定一个序列,那么向这个序列放一个元素时,要确保所有指向这个元素的所有元素都放进去了。

       最直接的想法是,把每个元素前面的结点列出,没有前面结点的放入序列,把放入序列的结点从其他结点记录中删除,再把没有前面结点的放到序列中,一直到所有结点都放入序列中。(如果这个办法最终不能把所有结点都放到序列中,说明不能形成序列,对应图是有环图)

       另一种想法就是用dfs搜图,没有上面的好想,但是比上面的方法高效:从每个u结点((u,v)中的u)开始深搜,(发现不好讲,举个例子):

       比如说,从a点开始深搜,访问的序列是1,然后是2,2返回到2条路径的相交处才会访问3路径,在返回(也就是递归的回溯)时,把2路径上的结点从尾到头放到结果序列的头部,以此类推,会把4、5、3、1上的结点放到结果序列中,这样从a结点开始的深搜就结束了;然后深搜6、7上的结点时,6、7也会被访问到,回溯时把结点放到结果序列中。

       另外,判断有没有环就是把正在深搜中的结点设为-1,如果路径走到-1的结点了,说明有环。放到结果序列中的结点是1,不可能有路径再指向结点都为1的路径。没有访问过的结点是0。

2、欧拉回路

     欧拉道路:从无向图的一个结点出发,走出一条道路,每条边恰好经过一次。“一笔画”问题。

     目的是从起点走到终点,所以经过的点,进去必须能出来,出不来就到不了终点。所以除了起点和终点,其他点不能是奇点。所以:

     有2个及以下奇点的图,有欧拉道路(无向图)。奇点必须是起点或终点。

     所以:

     (无向图)输出一笔画路径的问题,先判断奇点个数,没有的话从哪个点开始搜都可以,一个的话从该点开始,2个的话从一个点开始,到一个点结束。搜图时标记走过的路(注意是路不是点)。

    

    

 

    

 

    

      

      

      

      

      

      

posted @ 2017-10-10 09:15  哲贤  阅读(451)  评论(0编辑  收藏  举报