C++ 深度优先搜索(邻接表+栈实现)

C++ 深度优先搜索(邻接表+栈实现)

深度优先搜索的结果是图的生成树,也就是极小连通图(n个顶点有n-1条边)

图的生成树的结果是不唯一的,它是根据你的存储方式的变化而变化的。

深度搜索步骤:
1.确定一个开始顶点,并将该顶点标记为已访问。
2.访问开始顶点的第一个邻接顶点,
if(未被访问)
将该邻接顶点标记为已访问。
将该邻接顶点作为新的开始顶点。
重复2
else
搜索下一个邻接顶点。重复2
3.当开始顶点的所有邻接顶点均已被访问
回溯到上一个开始顶点,重复2
4.直到所有的顶点都已被访问过(没有点作为开始顶点),程序结束。

假设我们有以下这个图:

那么我们深度搜索的结果应该是:

v1->v2->v4->v8->v5->v3->v6->v7

深度搜索的代码实现(栈实现)

像这种先深入后回溯的算法 很适合我们栈这样先进后出的数据结构。当然也可以用递归解决。这里我们选用栈实现上面那个图的深度搜索过程

1.邻接表的实现

//AdjanceyList.h
#pragma once
#include<iostream>
#include<vector>

using namespace std;

//邻接表+DFS实现图的深度优先搜索(无向图)
struct AdjacenyList
{
    int adjacenyNode;
    AdjacenyList *nextarc;
};

//邻接表表头
struct headerList
{
    int headerNode;
    AdjacenyList *firstarc;
};

//邻接表
class graphAdjacencyList
{
public:
    graphAdjacencyList(int nodeNum)
    {
        this->nodeNum=nodeNum;
        this->hvexArray=new headerList[nodeNum]();
        if(hvexArray==NULL)
        {
            cout<<"out of space"<<endl;
            exit(1);
        }
        for(int i=0;i<nodeNum;++i)
        {
            hvexArray[i].firstarc=NULL;
            hvexArray[i].headerNode=-1;
        }
    }
    ~graphAdjacencyList()
    {
        if(hvexArray!=NULL)
        {
            delete[] hvexArray;
        }
        if(!adjvector.empty())
        {
            for(vector<AdjacenyList*>::iterator it=adjvector.begin();it!=adjvector.end();++it)
            {
                delete (*it);
            }
        }
    }
    void addEdge(int tail,int head)//(tail,head)
    {
        AdjacenyList *adjvex=new AdjacenyList();
        adjvex->nextarc=NULL;
        adjvex->adjacenyNode=head;//邻接顶点信息
        if((hvexArray+tail)->headerNode==-1)
        {
            //设置头列表
            (hvexArray+tail)->headerNode=tail;
            (hvexArray+tail)->firstarc=adjvex;
        }
        else
        {
            //设置邻接表
            AdjacenyList *tempAdjList=(hvexArray+tail)->firstarc;
            while(tempAdjList->nextarc!=NULL)//迭代找到最后一个列表接上
            {
                tempAdjList=tempAdjList->nextarc;
            }
            tempAdjList->nextarc=adjvex;
        }
        adjvector.push_back(adjvex);
    }

    headerList *getList()
    {
        return hvexArray;
    }

private:
    //AdjacenyList *adjvex;
    vector<AdjacenyList*> adjvector;//用vector来管理领接顶点的内存
    headerList *hvexArray;
    int nodeNum;
};

2.深度搜索(DFS)实现

void dfs(graphAdjacencyList &graph, int start,int nodeNum)
{
    stack<int> s;
    vector<bool> visited(nodeNum,false);//顶点是否被访问
    s.push(start);
    cout<<start;
    visited[start]=true;
    while(!s.empty())
    {
        int currentNode=s.top();

        AdjacenyList *temp=graph.getList()[currentNode].firstarc;
        //栈顶元素顶点存在未被访问过的领接点

        //1.找到未被访问的点
        while(temp!=NULL)
        {
            if(visited[temp->adjacenyNode]!=false)//已被访问
            {
                temp=temp->nextarc;
            }
            else//未被访问
            {
            //输出顶点
                cout<<"-->"<<temp->adjacenyNode;
            //将顶点改为:已访问
                visited[temp->adjacenyNode]=true;
            //将顶点入栈,作为新的起点开始搜索
                s.push(temp->adjacenyNode);
                break;//跳出搜索
            }
        }
        if(temp==NULL)//无领接点未被访问(叶顶点)
        {
            s.pop();
        }
    }
    cout<<endl;
}

实现上图的深度搜索

int main(int argc, const char** argv) {
    graphAdjacencyList graph_adjlist(8);
    graph_adjlist.addEdge(0,1);
    graph_adjlist.addEdge(0,2);
    graph_adjlist.addEdge(1,0);
    graph_adjlist.addEdge(1,3);
    graph_adjlist.addEdge(1,4);
    graph_adjlist.addEdge(2,0);
    graph_adjlist.addEdge(2,5);
    graph_adjlist.addEdge(2,6);
    graph_adjlist.addEdge(3,1);
    graph_adjlist.addEdge(3,7);
    graph_adjlist.addEdge(4,1);
    graph_adjlist.addEdge(4,7);
    graph_adjlist.addEdge(5,2);
    graph_adjlist.addEdge(5,6);
    graph_adjlist.addEdge(6,2);
    graph_adjlist.addEdge(6,5);
    graph_adjlist.addEdge(7,3);
    graph_adjlist.addEdge(7,4);

//    printgraphAdjList(graph_adjlist,8);
    dfs(graph_adjlist,0,8);
//    bfs(graph_adjlist,0,8);

    system("pause");
    return 0;
}

结果显示

  • 6
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
邻接表非递归深度优先遍历需要使用来辅助实现,下面是C++代码实现: ```c++ #include <iostream> #include <stack> #include <vector> using namespace std; const int MAXN = 100; // 最大顶点数 struct ArcNode { int adjvex; // 该弧所指向的顶点的位置 ArcNode* nextarc; // 指向下一条弧的指针 }; struct VNode { int data; // 顶点信息 ArcNode* firstarc; // 指向第一条依附该顶点的弧的指针 }; struct ALGraph { VNode adjlist[MAXN]; // 邻接表 int n, e; // 顶点数和边数 }; // 初始化邻接表 void init(ALGraph& G) { G.n = G.e = 0; for (int i = 0; i < MAXN; ++i) { G.adjlist[i].firstarc = nullptr; } } // 添加边 void add_edge(ALGraph& G, int u, int v) { auto p = new ArcNode; p->adjvex = v; p->nextarc = G.adjlist[u].firstarc; G.adjlist[u].firstarc = p; } // 非递归深度优先遍历 void DFS(ALGraph& G, int v) { bool visited[MAXN] = { false }; // 标记顶点是否被访问过 stack<int> s; // s.push(v); // 先将起始顶点入 visited[v] = true; // 标记起始顶点已被访问 while (!s.empty()) { int u = s.top(); // 取出顶元素 s.pop(); cout << u << " "; // 访问该顶点 auto p = G.adjlist[u].firstarc; while (p != nullptr) { int w = p->adjvex; if (!visited[w]) { // 如果该顶点未被访问过 visited[w] = true; // 标记该顶点已被访问 s.push(w); // 将该顶点入 } p = p->nextarc; } } } int main() { ALGraph G; init(G); G.n = 6; add_edge(G, 0, 1); add_edge(G, 0, 2); add_edge(G, 1, 3); add_edge(G, 1, 4); add_edge(G, 2, 4); add_edge(G, 3, 5); add_edge(G, 4, 5); DFS(G, 0); // 从顶点0开始遍历 return 0; } ``` 以上代码演示了如何使用邻接表来存储,并实现非递归深度优先遍历。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值