当前位置: 首页>>算法&结构>>正文


深度优先搜索算法之非递归实现及实例源码(原创)

摘要:本文描述了深度优先算法非递归实现的思路,并给出了几个利用深度优先解决的问题的实例代码

关键字:DFS,非递归,深度优先,图论,搜索,经典实例,源码

深度优先搜索算法需要了解深度优先遍历的执行过程,本文中利用一个栈来模拟递归实现中系统设置的工作栈,算法的伪代码描述为:

(1)初始化栈

(2)输出起始节点,并标记为已访问,将该节点压入栈

(3)While(栈不为空)

a.取得栈顶节点Top,注意不要从站内删除;

b.遍历栈顶节点Top的相邻节点adjacentNode,如果该节点adjacentNode未被标记为已

访问,则

输出节点adjacentNode;

标记adjacentNode为已访问;

把adjacentNode压入栈;

c.如果没有满足条件的相邻节点adjacentNode,将栈顶节点Top出栈;

使用情形:

1.深度优先策略常用于连通图的遍历

2.深度优先策略也广泛应用于寻找一条满足某种条件的路径。

算法的时间复杂度为O(n),其中n为节点个数。

 

经典实例源码:

1.图的节点遍历(C++,VC6.0/VS2005)=================================================

//////////////////////////////////
//深度优先之节点遍历
//1---5
//|     |
//2---4--6----8
//|          |  
//3------7
// 1 2 3 4 5 6 7 8
//1 0 1 0 0 1 0 0 0
//2 1 0 1 1 0 0 0 0
//3 0 1 0 0 0 0 1 0
//4 0 1 0 0 1 1 0 0
//5 1 0 0 1 0 0 0 0
//6 0 0 0 1 0 0 1 1
//7 0 0 1 0 0 1 0 0
//8 0 0 0 0 0 1 0 0

#include 
#include 
using namespace std;

//节点数
#define M 8

//图的矩阵表示
int matrix[M][M] =
{
    0, 1, 0, 0, 1, 0, 0, 0,
    1, 0, 1, 1, 0, 0, 0, 0,
    0, 1, 0, 0, 0, 0, 1, 0,
    0, 1, 0, 0, 1, 1, 0, 0,
    1, 0, 0, 1, 0, 0, 0, 0,
    0, 0, 0, 1, 0, 0, 1, 1,
    0, 0, 1, 0, 0, 1, 0, 0,
    0, 0, 0, 0, 0, 1, 0, 0

};
//访问标记,初始化为0,
int visited[M + 1];


//graph traverse
void GT_DFS()
{
    visited[1] = 1;
    stack s;
    cout << 1 << " ";
    s.push(1);
    while(!s.empty())
    {
        int top = s.top();
        int i ;
        for(i = 1; i <= M; ++i)
        {
            if(visited[i] == 0 && matrix[top - 1][i - 1 ] == 1)
            {
                visited[i] = 1;
                s.push(i);
                cout << i << " ";

                break;
            }
        }
        if( i == M + 1)
        {
            s.pop();
        }
    }
}


int main()
{
    GT_DFS();
    system("pause");
    return 0;
}

2.迷宫问题(C++,VC6.0/VS2005)=====================================================

////////////////////////////////////////////////
//深度优先搜索之迷宫问题
#include 
#include 
using namespace std;
#define M 10
#define N 10

//迷宫矩阵,1为通道,0为障碍
//入口(1,0),出口(9,9)
int Matrix[M][N]={
    0,1,1,1,0,0,0,0,0,0,
    1,1,0,1,0,1,1,1,1,0,
    0,1,0,1,1,1,0,0,0,0,
    0,0,0,0,0,1,0,0,0,0,
    0,1,1,1,1,1,0,0,0,0,
    0,1,0,0,0,0,0,0,0,0,
    0,1,1,1,0,0,1,1,1,0,
    0,0,1,1,1,1,1,0,1,0,
    0,0,1,1,0,0,0,0,1,0,
    0,0,1,0,0,0,0,0,1,1};
//标记数组,初始化为0
bool visited[M * N + 1] ;

//节点
struct Node
{
    int x;
    int y;
    Node(int i,int j)
    {
        x = i;
        y = j;
    }
};
//////////////////////////////////
/*
   0
   ----------------->y
   |
   |
   |
   |
   |
   V
   x
   */
//右下上左
int x_off[] = {0,1,-1,0};
int y_off[] = {1,0,0,-1};

//输出迷宫
void PrintMatrix()
{
    cout << "入口(1,0),出口(9,9)的迷宫,1为通道,0为障碍:" << endl;
    for(int i = 0; i < M; ++i)
    {
        for(int j = 0; j < N; ++j)
            cout << Matrix[i][j];
        cout << endl;
    }
}

//输出一条路径
//由于入栈路径是正序,要倒过来输出才是从入口到出口的路劲
void PrintPath(stack s)
{
    cout << "一条迷宫路径:" << endl;
    stack t;
    while(!s.empty())
    {
        t.push(s.top());
        s.pop();
    }
    while(!t.empty())
    {
        cout << "(" << t.top().x << "," << t.top().y << ")->";
        t.pop();
    }
    cout << endl;
}

//深度优先搜索一条可能的路径
void MAZE_DFS()
{

    //1.初始化栈
    stack s;
    Node start(1,0);
    s.push(start);
    visited[0] = 1;
    while(!s.empty())
    {
        //2.取得栈顶元素(注意不从栈内删除)
        Node top = s.top();
        //3.遍历栈顶元素的邻节点
        //右节点
        //下节点
        //上节点
        //左节点
        int i;
        for(i = 0; i < 4; ++i)
        {
            int nx = top.x + x_off[i];
            int ny = top.y + y_off[i];
            if(nx >= 0 && nx < N && ny>=0 && ny< M && visited[nx * N + ny] != 1 && Matrix[nx][ny] == 1)
            {
                //4.把满足条件的元素标记为已处理,并压入栈内
                Node newNode(nx,ny);
                visited[nx*N + ny] = 1;
                s.push(newNode);
                //找到出口,终止搜索
                if(nx == 9 && ny == 9)
                {
                    //输出找到的路径
                    PrintPath(s);
                    return;
                }
                break;
            }
        }
        //5.当前节点没有满足条件的邻节点,把当前栈顶元素删除
        if(i == 4)
        {
            s.pop();
        }
    }
}

//测试代码主函数
void main()
{
    PrintMatrix();
    MAZE_DFS();
    system("pause");
}

 

参考文献:

[1] 深度优先遍历算法的非递归实现jsj.ccut.edu.cn/sjjg/index.php

[2]深度优先遍历演示动画

http://218.65.59.6/xinwen3/news/kj/flash/2004/0426/1301.htm

本文由《纯净天空》出品。文章地址: https://vimsky.com/article/181.html,未经允许,请勿转载。