图的深搜(DFS)和广搜(BFS)


一般用G=(V,E)来表示图。经常用邻接矩阵或者邻接表来描述一副图。图的遍历算法,根据访问节点的顺序,可分为广度优先搜索(BFS)和深度优先搜索(DFS)。

广度优先搜索

在这里插入图片描述
访问顺序是:A -> C -> D -> F -> B -> G -> E

/*
 * 广度优先搜索(类似于树的层次遍历)
 */
void MatrixUDG::BFS()
{
    int head = 0;//队列头
    int rear = 0;//队列尾
    int queue[MAX];     // 辅助队列
    int visited[MAX];   // 顶点访问标记
    int i, j, k;
	//顶点访问初始化为0
    for (i = 0; i < mVexNum; i++)
        visited[i] = 0;
        
    for (i = 0; i < mVexNum; i++)
    {
        if (!visited[i])
        {
            visited[i] = 1;
            queue[rear++] = i;  // 入队列
        }
        while (head != rear)//队列不空时
        {
            j = queue[head++];  // 出队列
            for (k = firstVertex(j); k >= 0; k = nextVertex(j, k)) 
            {
                if (!visited[k])
                {
                    visited[k] = 1;
                    queue[rear++] = k;// 入队列
                }
            }
        }
    }
}
/*
 * 返回顶点v的第一个邻接顶点的索引,失败则返回-1
 */
int MatrixUDG::firstVertex(int v)
{
    int i;
    if (v<0 || v>(mVexNum-1))
        return -1;
    for (i = 0; i < mVexNum; i++)
        if (mMatrix[v][i] == 1)
            return i;
    return -1;
}
/*
 * 返回顶点v相对于w的下一个邻接顶点的索引,失败则返回-1
 */
int MatrixUDG::nextVertex(int v, int w)
{
    int i;
    if (v<0 || v>(mVexNum-1) || w<0 || w>(mVexNum-1))
        return -1;
    for (i = w + 1; i < mVexNum; i++)
        if (mMatrix[v][i] == 1)
            return i;

    return -1;
}

深度优先搜索

在这里插入图片描述
访问顺序是:A -> C -> B -> D -> F -> G -> E

 MatrixUDG::DFS(int i, int *visited)
{
    int w;
    visited[i] = 1;
    // 遍历该顶点的所有邻接顶点。若是没有访问过,那么继续往下走
    for (w = firstVertex(i); w >= 0; w = nextVertex(i, w))
    {
        if (!visited[w])
            DFS(w, visited);
    }
}
/*
 * 深度优先搜索遍历图,入口
 */
void MatrixUDG::DFS()
{
    int i;
    int visited[MAX];       // 顶点访问标记
    // 初始化所有顶点都没有被访问
    for (i = 0; i < mVexNum; i++)
        visited[i] = 0;
    for (i = 0; i < mVexNum; i++)
    {
        if (!visited[i])
            DFS(i, visited);
    }
}

完整代码:

/**
 * C++: 邻接矩阵表示的"无向图(Matrix Undirected Graph)"
 */
#include <iomanip>
#include <iostream>
#include <vector>
using namespace std;

#define MAX 100
class MatrixUDG {
	private:
        char mVexs[MAX];    // 顶点集合
        int mVexNum;             // 顶点数
        int mEdgNum;             // 边数
        int mMatrix[MAX][MAX];   // 邻接矩阵

    public:
        // 创建图(自己输入数据)
		MatrixUDG();
        // 创建图(用已提供的矩阵)
        MatrixUDG(char vexs[], int vlen, char edges[][2], int elen);
		~MatrixUDG();

        // 深度优先搜索遍历图
        void DFS();
        // 广度优先搜索(类似于树的层次遍历)
        void BFS();
        // 打印矩阵队列图
        void print();
	private:
        // 读取一个输入字符
        char readChar();
        // 返回ch在mMatrix矩阵中的位置
        int getPosition(char ch);
        // 返回顶点v的第一个邻接顶点的索引,失败则返回-1
        int firstVertex(int v);
        // 返回顶点v相对于w的下一个邻接顶点的索引,失败则返回-1
        int nextVertex(int v, int w);
        // 深度优先搜索遍历图的递归实现
        void DFS(int i, int *visited);

};
/*
 * 创建图(自己输入数据)
 */
MatrixUDG::MatrixUDG()
{
    char c1, c2;
    int i, p1, p2;

    // 输入"顶点数"和"边数"
    cout << "input vertex number: ";
    cin >> mVexNum;
    cout << "input edge number: ";
    cin >> mEdgNum;
    if ( mVexNum < 1 || mEdgNum < 1 || (mEdgNum > (mVexNum * (mVexNum-1))))
    {
        cout << "input error: invalid parameters!" << endl;
        return ;
    }
    // 初始化"顶点"
    for (i = 0; i < mVexNum; i++)
    {
        cout << "vertex(" << i << "): ";
        mVexs[i] = readChar();
    }
    // 初始化"边"
    for (i = 0; i < mEdgNum; i++)
    {
        // 读取边的起始顶点和结束顶点
        cout << "edge(" << i << "): ";
        c1 = readChar();
        c2 = readChar();

        p1 = getPosition(c1);
        p2 = getPosition(c2);
        if (p1==-1 || p2==-1)
        {
            cout << "input error: invalid edge!" << endl;
            return ;
        }
        mMatrix[p1][p2] = 1;
        mMatrix[p2][p1] = 1;
    }
}
/*
 * 创建图(用已提供的矩阵)
 *
 * 参数说明:
 *     vexs  -- 顶点数组
 *     vlen  -- 顶点数组的长度
 *     edges -- 边数组
 *     elen  -- 边数组的长度
 */
MatrixUDG::MatrixUDG(char vexs[], int vlen, char edges[][2], int elen)
{
    int i, p1, p2;
    // 初始化"顶点数"和"边数"
    mVexNum = vlen;
    mEdgNum = elen;
    // 初始化"顶点"
    for (i = 0; i < mVexNum; i++)
        mVexs[i] = vexs[i];
    // 初始化"边"
    for (i = 0; i < mEdgNum; i++)
    {
        // 读取边的起始顶点和结束顶点
        p1 = getPosition(edges[i][0]);
        p2 = getPosition(edges[i][1]);
        mMatrix[p1][p2] = 1;
        mMatrix[p2][p1] = 1;
    }
}

/*
 * 析构函数
 */
MatrixUDG::~MatrixUDG()
{
}
/*
 * 返回ch在mMatrix矩阵中的位置
 */
int MatrixUDG::getPosition(char ch)
{
    int i;
    for(i=0; i<mVexNum; i++)
        if(mVexs[i]==ch)
            return i;
    return -1;
}
/*
 * 读取一个输入字符
 */
char MatrixUDG::readChar()
{
    char ch;

    do {
        cin >> ch;
    } while(!((ch>='a'&&ch<='z') || (ch>='A'&&ch<='Z')));
    return ch;
}
/*
 * 返回顶点v的第一个邻接顶点的索引,失败则返回-1
 */
int MatrixUDG::firstVertex(int v)
{
    int i;
    if (v<0 || v>(mVexNum-1))
        return -1;
    for (i = 0; i < mVexNum; i++)
        if (mMatrix[v][i] == 1)
            return i;
    return -1;
}
/*
 * 返回顶点v相对于w的下一个邻接顶点的索引,失败则返回-1
 */
int MatrixUDG::nextVertex(int v, int w)
{
    int i;
    if (v<0 || v>(mVexNum-1) || w<0 || w>(mVexNum-1))
        return -1;
    for (i = w + 1; i < mVexNum; i++)
        if (mMatrix[v][i] == 1)
            return i;

    return -1;
}
/*
 * 深度优先搜索遍历图的递归实现
 */
void MatrixUDG::DFS(int i, int *visited)
{
    int w;
    visited[i] = 1;
    cout << mVexs[i] << " ";
    // 遍历该顶点的所有邻接顶点。若是没有访问过,那么继续往下走
    for (w = firstVertex(i); w >= 0; w = nextVertex(i, w))
    {
        if (!visited[w])
            DFS(w, visited);
    }
}
/*
 * 深度优先搜索遍历图
 */
void MatrixUDG::DFS()
{
    int i;
    int visited[MAX];       // 顶点访问标记

    // 初始化所有顶点都没有被访问
    for (i = 0; i < mVexNum; i++)
        visited[i] = 0;
    cout << "DFS: ";
    for (i = 0; i < mVexNum; i++)
    {
        //printf("\n== LOOP(%d)\n", i);
        if (!visited[i])
            DFS(i, visited);
    }
    cout << endl;
}
/*
 * 广度优先搜索(类似于树的层次遍历)
 */
void MatrixUDG::BFS()
{
    int head = 0;
    int rear = 0;
    int queue[MAX];     // 辅组队列
    int visited[MAX];   // 顶点访问标记
    int i, j, k;

    for (i = 0; i < mVexNum; i++)
        visited[i] = 0;
    cout << "BFS: ";
    for (i = 0; i < mVexNum; i++)
    {
        if (!visited[i])
        {
            visited[i] = 1;
            cout << mVexs[i] << " ";
            queue[rear++] = i;  // 入队列
        }
        while (head != rear)
        {
            j = queue[head++];  // 出队列
            for (k = firstVertex(j); k >= 0; k = nextVertex(j, k)) //k是为访问的邻接顶点
            {
                if (!visited[k])
                {
                    visited[k] = 1;
                    cout << mVexs[k] << " ";
                    queue[rear++] = k;// 入队列
                }
            }
        }
    }
    cout << endl;
}
/*
 * 打印矩阵队列图
 */
void MatrixUDG::print()
{
    int i,j;

    cout << "Martix Graph:" << endl;
    for (i = 0; i < mVexNum; i++)
    {
        for (j = 0; j < mVexNum; j++)
            cout << mMatrix[i][j] << " ";
        cout << endl;
    }
}
int main()
{
    char vexs[] = {'A', 'B', 'C', 'D', 'E', 'F', 'G'};
    char edges[][2] = {
        {'A', 'C'},
        {'A', 'D'},
        {'A', 'F'},
        {'B', 'C'},
        {'C', 'D'},
        {'E', 'G'},
        {'F', 'G'}};
    int vlen = sizeof(vexs)/sizeof(vexs[0]);
    int elen = sizeof(edges)/sizeof(edges[0]);
    MatrixUDG* pG;

    // 自定义"图"(输入矩阵队列)
    //pG = new MatrixUDG();
    // 采用已有的"图"
    pG = new MatrixUDG(vexs, vlen, edges, elen);

    pG->print();   // 打印图
    pG->DFS();     // 深度优先遍历
    pG->BFS();     // 广度优先遍历
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值