深度优先搜索算法(Depth-First-Search),是搜索算法的一种。它沿着树的深度遍历树的节点,尽可能深的搜索树的分支。当节点v的所有边都己被探寻过,搜索将回溯到发现节点v的那条边的起始节点。这一过程一直进行到已发现从源节点可达的所有节点为止。如果还存在未被发现的节点,则选择其中一个作为源节点并重复以上过程,整个进程反复进行直到所有节点都被访问为止。
深度优先搜索是图论中的经典算法,利用深度优先搜索算法可以产生目标图的相应拓扑排序表,利用拓扑排序表可以方便的解决很多相关的图论问题,如最大路径问题等等。一般用堆数据结构来辅助实现 DFS 算法。
深度优先遍历图算法步骤:
1. 访问顶点v;
2. 依次从v的未被访问的邻接点出发,对图进行深度优先遍历;直至图中和v有路径相通的顶点都被访问;
3. 若此时图中尚有顶点未被访问,则从一个未被访问的顶点出发,重新进行深度优先遍历,直到图中所有顶点均被访问过为止。
上述描述可能比较抽象,举个实例:
DFS 在访问图中某一起始顶点 v 后,由 v 出发,访问它的任一邻接顶点 w1;再从 w1 出发,访问与 w1 邻 接但还没有访问过的顶点 w2;然后再从 w2 出发,进行类似的访问,… 如此进行下去,直至到达所有的邻接顶点都被访问过的顶点 u 为止。
接着,退回一步,退到前一次刚访问过的顶点,看是否还有其它没有被访问的邻接顶点。如果有,则访问此顶点,之后再从此顶点出发,进行与前述类似的访问;如果没有,就再退回一步进行搜索。重复上述过程,直到连通图中所有顶点都被访问过为止。
2.BFS (广度优先搜索)
广度优先搜索算法(Breadth-First-Search),是一种图形搜索算法。简单的说,BFS 是从根节点开始,沿着树(图)的宽度遍历树(图)的节点。如果所有节点均被访问,则算法中止。一般用队列数据结构来辅助实现 BFS 算法。
算法步骤:
1. 首先将根节点放入队列中。
2. 从队列中取出第一个节点,并检验它是否为目标。
- 如果找到目标,则结束搜寻并回传结果。
- 否则将它所有尚未检验过的直接子节点加入队列中。
3. 若队列为空,表示整张图都检查过了——亦即图中没有欲搜寻的目标。结束搜寻并回传“找不到目标”。
4. 重复步骤2。
3.拓扑排序
算法思想:
1、在AOV网络中选一个没有直接前驱的顶点, 并输出之;
2、从图中删去该顶点, 同时删去所有它发出的有向边;
3、重复以上步骤, 直到
◆ 全部顶点均已输出,拓扑有序序列形成,拓扑排序完成;
◆ 或者图中还有未输出的顶点,但已跳出处理循环。这说明图中还剩下一些顶点,它们都有直接前驱,再也找不到没有前驱的顶点了。这时AOV网络中必定存在有向环。
4.深度优先或广度优先遍历的方法进行拓扑排序。
应用有:
1、判断一个有向图是否存在回路,为求有向图的最长路径。
2、排队
下面举一个排队的例子:
题目要求如上图
程序如下:
1 #include<iostream> 2 #include<queue> 3 #include<stack> 4 using namespace std; 5 void breadth_sort(int **neighbors,int count,queue<int>&topological_order); 6 void depth_sort(int **neighbors,int count,stack<int>&topological_order); 7 void recursive_depth_sort(int **neighbors,int v,bool *visited,stack<int>&topological_order); 8 int main() 9 {//为了测试宽度与深度,本程序两种排序同时输出 10 int number,com; 11 int task_number; 12 int **array; 13 int *b; 14 queue<int>breadth_order; 15 stack<int>depth_order; 16 cin>>task_number; 17 for(int i=0;i<task_number;i++)//题目要求的任务数 18 { 19 cin>>number>>com; 20 array=new int*[number+1]; 21 b=new int[number+1]; 22 for(int k=0;k<=number;k++) 23 { 24 array[k]=new int[number+1]; 25 b[k]=0; 26 } 27 for(int m=0;m<=number;m++) 28 for(int n=0;n<=number;n++)//矩阵初始化 29 array[m][n]=0; 30 for(int j=0;j<com;j++) 31 { 32 int p,q; 33 cin>>p>>q; 34 array[p][b[p]]=q; //添加后继 35 b[p]++; //添加一个后继,值+1 36 } 37 breadth_sort(array,number,breadth_order);//广度排序 38 while(breadth_order.size()!=NULL) 39 { 40 cout<<breadth_order.front()<<' '; 41 breadth_order.pop(); 42 } 43 cout<<endl; 44 depth_sort(array,number,depth_order);//深度排序 45 while(depth_order.size()!=NULL) 46 { 47 cout<<depth_order.top()<<' '; 48 depth_order.pop(); 49 } 50 cout<<endl; 51 } 52 return 0; 53 } 54 void breadth_sort(int **neighbors,int count,queue<int>&topological_order) 55 {//广度优先排序,无前驱的先输出,用了队列 56 int v; 57 int *predecessor_count=new int[count+1]; 58 for(v=1;v<=count;v++)predecessor_count[v]=0; 59 for(v=1;v<=count;v++) 60 for(int i=0;neighbors[v][i]!=0;i++){ 61 predecessor_count[neighbors[v][i]]++; 62 } 63 queue<int>ready_to_process; 64 for(v=1;v<=count;v++) 65 if(predecessor_count[v]==0) 66 ready_to_process.push(v); 67 while(!ready_to_process.empty()){ 68 v=ready_to_process.front(); 69 topological_order.push(v); 70 for(int j=0;neighbors[v][j]!=0;j++){ 71 predecessor_count[neighbors[v][j]]--; 72 if(predecessor_count[neighbors[v][j]]==0) 73 ready_to_process.push(neighbors[v][j]); 74 } 75 ready_to_process.pop(); 76 } 77 } 78 void depth_sort(int **neighbors,int count,stack<int>&topological_order) 79 {//深度优先排序,无前驱的先输出,用了堆栈 80 bool *visited=new bool[count+1]; 81 int v; 82 for(v=1;v<=count;v++)visited[v]=false; 83 for(v=1;v<=count;v++) 84 if(!visited[v]) 85 recursive_depth_sort(neighbors,v,visited,topological_order); 86 } 87 88 void recursive_depth_sort(int **neighbors,int v,bool *visited,stack<int>&topological_order) 89 { 90 visited[v]=true; 91 for(int i=0;neighbors[v][i]!=0;i++){ 92 93 if(!visited[neighbors[v][i]]) 94 recursive_depth_sort(neighbors,neighbors[v][i],visited,topological_order); 95 } 96 topological_order.push(v); 97 }