图论:BFS算法与DFS算法的C++实现

关于算法的准确性,本人只测试了比较简单的情况,两个算法是否存在未发现的漏洞,本人不做任何担保

BFS算法:
类似于树的层序遍历,需要借助队列实现`

算法的基本流程:起始点——探索未遍历的邻接点——未遍历的邻接点作为新的起始点重复`

#include <iostream>
#include <vector>
#include <queue>
#include "adjacency_list.h"
using namespace std;
//构建邻接表
struct adjNode        
{
    int data;
    adjNode *next;
};
struct Vertice
{
    int vertice;
    adjNode *next;
    bool flag = false;
};
//函数声明
void BFS(vector<Vertice> &adjacenty_list,int n);
void adjSearch(vector<Vertice> &adjacenty_list, Vertice vertice, queue<int> &q);
void BFS(vector<Vertice> &adjacenty_list, int n)
{
    queue<int> q;
    adjacenty_list[n].flag = true;
    q.push(adjacenty_list[n].vertice);
    cout << adjacenty_list[n].vertice << endl; //测试以下是否按照我们想要的顺序进行了遍历
    adjSearch(adjacenty_list, adjacenty_list[n], q);
    q.pop();
    BFS(adjacenty_list, q.front());
}
//该函数的作用是探索某一顶点所有未遍历的邻接点
void adjSearch(vector<Vertice> &adjacenty_list, Vertice vertice, queue<int> &q)
{
    adjNode *tmp = vertice.next;
    while (tmp) //邻接列表非空时,检测该链表是否已经遍历,如果没有遍历,则将其放入队列中,然后下一个邻接结点,反之,下一个,并continue
    {
        if (adjacenty_list[tmp->data].flag)   
        {
            tmp = tmp->next;
            continue;
        }
        q.push(tmp->data);
        tmp = tmp->next;
    }
}
//测试程序,大部分代码都是在读入一个想要的邻接表(图)
int main()
{
    int n, x;
    adjList adjLink;
    vector<Vertice> adjacenty_list;
    cout << "input the numbers of the vertices: " << endl;
    cin >> n;
    for (int i = 0; i < n; i++)
    {
        queue<adjNode> q;
        Vertice vertice = {i, nullptr};
        adjacenty_list.push_back(vertice);
        cout << "input the adjcent point or #: " << endl;
        while (cin >> x)
        {
            adjLink = (adjList)malloc(sizeof(adjNode));
            if (!q.empty())
            {
                adjNode *tmp;
                tmp = &q.front();
                q.pop();
                adjLink->data = x;
                adjLink->next = nullptr;
                q.push(*adjLink);
                tmp->next = &q.front();
            }
            else
            {
                adjLink->data = x;
                adjLink->next = nullptr;
                adjacenty_list[i].next = adjLink;
                q.push(*adjLink);
            }
        }
        cin.clear();
        cin.ignore();
    }
    BFS(adjacenty_list, 0);
}

图的DFS算法,类似于树的先序遍历,难点在于如何处理算法的记忆性
这就需要用到栈的数据结构来实现了,将遍历过的点记录在栈中,探索不下去了就返回,看看有没有值得继续探索的点
代码如下:

#include <iostream>
#include <vector>
#include <stack>
#include <queue>
#include "adjacency_list.h"
using namespace std;
int k = 0;// k在这里是作为测试用例,用来观察DFS执行了几次,如果其次数等于V+E(顶点数与边数和),粗略表明,算法还不错
struct adjNode
{
    int data;
    adjList next;
};
struct V_list
{
    int v;
    adjList next;
    bool flag = false;
};
stack<int> Stack;
vector<V_list> verticeList;
void DFS(V_list &vertice);
int adjSearch(V_list &adjNode);
int adjSearch(V_list &vertice)  // 查询可以探索的邻接点
{
    adjNode *tmp = vertice.next;
    while (verticeList[tmp->data].flag)     //对初学者而言,比较困难的点在这里。检测某顶点的邻接点是否都被遍历
    {                                        //如果该点被遍历,那就下一个,如果没有被遍历,则对返回该点对应的顶点,作为下次DFS
        tmp = tmp->next;					//注意探索到最后的情形,tmp为空,需要跳出循环,并给出一个标志,表明该顶点没有未遍历的邻接点
        if (tmp == nullptr)                //该顶点为底部,需要回溯
            break;
    }
    if (tmp != nullptr)
        return (*tmp).data;
    else
        return -1;
}
void DFS(V_list &vertice)
{
    k++;
    cout << k << endl;
    int next_v;
    if (vertice.flag != true)
        Stack.push(vertice.v);
    vertice.flag = true;
    next_v = adjSearch(vertice);
    if (next_v != -1)
    {
        DFS(verticeList[next_v]);
    }
    else
    {
        Stack.pop();
        if (Stack.empty())
            return;
        DFS(verticeList[Stack.top()]);
    }
}
//测试程序与BFS相似但不相同,但部分代码在构建想要测试的图,或者说是邻接表
int main()
{
    int n, x;
    adjList adjLink;
    cout << "input the numbers of the vertices: " << endl;
    cin >> n;
    for (int i = 0; i < n; i++)
    {
        queue<adjNode> q;
        V_list vertice = {i, nullptr};
        verticeList.push_back(vertice);
        cout << "input the adjcent point or #: " << endl;
        while (cin >> x)
        {
            adjLink = (adjList)malloc(sizeof(adjNode));
            if (!q.empty())
            {
                adjNode *tmp;
                tmp = &q.front();
                q.pop();
                adjLink->data = x;
                adjLink->next = nullptr;
                q.push(*adjLink);
                tmp->next = &q.front();
            }
            else
            {
                adjLink->data = x;
                adjLink->next = nullptr;
                verticeList[i].next = adjLink;
                q.push(*adjLink);
            }
        }
        cin.clear();
        cin.ignore();
    }
    DFS(verticeList[0]);
    cout << k;
}
  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值