C++使用邻接表储存图与DFS、BFS遍历(使用类模板)详细注释

用邻接表实现图:

(先放上总代码吧,仔细看也不多的😁)

#include <iostream>
#include <queue>
using namespace std;
const int MaxSize = 10;    //图的最大顶点数
bool visited[10] = {0,0,0,0,0,0,0,0,0,0};

struct ArcNode   //边表
{
    int adjvex;  //邻接点域,存储该顶点对应的下标
    struct ArcNode *next;
};

struct VertexNode   //顶点表V0,V1,V2,V3...
{
    int vertex;   /* 顶点域,储存顶点信息 */
    struct ArcNode *firstedge;   //指向边表的头指针
};

template <class DataType>
class ALGraph
{
   public:
       ALGraph(DataType a[], int n, int e);
       void Output();
       void DFS(int v);
       void BFS();
       void DFSTraverse();
   private:
       VertexNode adjlist[MaxSize];//顶点表数组V0,V1,V2,V3...
       int vertexNum, edgeNum;  //图中的顶点数与边数
};

/** 构造函数
 *@param n 顶点数
 *@param e 边数
 */
template <class DataType>
ALGraph<DataType> :: ALGraph(DataType a[], int n, int e)
{   int i,j,k;
    vertexNum = n; edgeNum = e;
    for (i = 0; i < vertexNum; i++)//赋顶点表数组V0,V1,V2,V3...的值(0,1,2,3),并指向NULL成为空表
    {                                             //输入顶点信息,初始化顶点表
        adjlist[i].vertex = a[i];
        adjlist[i].firstedge = NULL;
    }
     for (k = 0; k < edgeNum; k++) //输入边的信息存储在边表中
     {
         cin>>i>>j;
         ArcNode *s;       //指向边表的指针
         s = new ArcNode;  //new一个节点
         s->adjvex = j;    //邻接序号为j
         s->next = adjlist[i].firstedge;
         adjlist[i].firstedge = s;
         /*两份类似代码是为了形成无向图,去掉是有向图 */
         ArcNode *p;       //指向边表的指针
         p = new ArcNode;  //new一个节点
         p->adjvex = i;    //邻接序号为j
         p->next = adjlist[j].firstedge;
         adjlist[j].firstedge = p;
     }
}

template <class DataType>
void ALGraph<DataType> :: Output()
{
    int i,j;
    for (i = 0; i < vertexNum; i++){         //输出邻接表
        cout << "与顶点"<< i <<"相邻的顶点:"<< endl;
        ArcNode *p;
        p = new ArcNode;
    	p = adjlist[i].firstedge;       //工作指针p指向顶点i的边表
    	while (p != NULL)             //依次输出顶点i的邻接点j
    	{
        	j = p->adjvex;
        	cout << j << " ";
        	p = p->next;
    	}
   		cout << endl;
    }
}


template <class DataType>
void ALGraph<DataType> :: DFS(int v)
{
    ArcNode *p; //边表指针
    visited[v] = true;
    cout<<adjlist[v].vertex<<" ";//利用顶点表打印顶点
    p = adjlist[v].firstedge;
    while(p){
        if(!visited[p->adjvex])
            DFS(p->adjvex);//传入边表的值-->再到顶点表里面找对应位置
        p=p->next;
    }
}

//邻接表的深度遍历操作
template <class DataType>
void ALGraph<DataType> :: DFSTraverse()
{
    int i;
    for(i=0; i<vertexNum; i++){//i小于顶点数
        visited[i] = false;  //初始化所有顶点都是未访问状态
    }
    for(i=0; i<vertexNum; i++){
        if(!visited[i])/*对未访问过的顶点调用DFS,若是连通图,只会执行一次  */
            DFS(i);
    }
}


template <class DataType>
void ALGraph<DataType> :: BFS()/*从0开始BFS遍历*/
{
    int i;
    ArcNode *p; //边表指针
    queue<int> Q;//初始化顺序队列
    for(i=0; i<vertexNum; i++)
        visited[i] = false;
    for(i=0; i<vertexNum; i++){
        if(!visited[i]){
            visited[i] = true;
            cout<<adjlist[i].vertex<<" ";//打印顶点
            Q.push(i);//i入队列
            while(!Q.empty())
            {
                Q.pop();
                p = adjlist[i].firstedge;//找到当前顶点表边表链表的头指针
                while(p){
                    if(!visited[p->adjvex]){//顶点没有被访问
                        visited[p->adjvex] = true;
                        cout << adjlist[p->adjvex].vertex <<" ";//输出顶点表的对应的下标
                        Q.push(p->adjvex);//将此顶点入队列
                    }
                    p=p->next;
                }
            }
        }
    }
}


int main()
{
    int a[5]={0,1,2,3};
    ALGraph<int> g(a,4,4);
    g.Output();
    cout<<"-------"<<endl;
    g.DFS(2);
    cout<<"\n-------"<<endl;
    g.BFS();
    return 0;
}

分析一下构造函数

/** 构造函数
 *@param n 顶点数
 *@param e 边数
 */
template <class DataType>
ALGraph<DataType> :: ALGraph(DataType a[], int n, int e)
{   int i,j,k;
    vertexNum = n; edgeNum = e;
    for (i = 0; i < vertexNum; i++)//赋顶点表数组V0,V1,V2,V3...的值(0,1,2,3),并指向NULL成为空表
    {                                             //输入顶点信息,初始化顶点表
        adjlist[i].vertex = a[i];
        adjlist[i].firstedge = NULL;
    }
     for (k = 0; k < edgeNum; k++) //输入边的信息存储在边表中
     {
         cin>>i>>j;
         ArcNode *s;       //指向边表的指针
         s = new ArcNode;  //new一个节点
         s->adjvex = j;    //邻接序号为j
         s->next = adjlist[i].firstedge;
         adjlist[i].firstedge = s;
         /*两份类似代码是为了形成无向图,去掉是有向图 */
         ArcNode *p;       //指向边表的指针
         p = new ArcNode;  //new一个节点
         p->adjvex = i;    //邻接序号为j
         p->next = adjlist[j].firstedge;
         adjlist[j].firstedge = p;
     }
}

图片分析

第一步:输入0,1

第一步

第二步:输入0,2

在这里插入图片描述测试的总图
在这里插入图片描述

数据

在这里插入图片描述

/*
0 1
0 2
2 1
2 3
与顶点0相邻的顶点:
2 1
与顶点1相邻的顶点:
2 0
与顶点2相邻的顶点:
3 1 0
与顶点3相邻的顶点:
2
-----
2 3 1 0
*/




下面是重复的

下面是DFS深度遍历操作的代码

template <class DataType>
void ALGraph<DataType> :: DFS(int v)
{
    ArcNode *p; //边表指针
    visited[v] = true;
    cout<<adjlist[v].vertex<<" ";//利用顶点表打印顶点
    p = adjlist[v].firstedge;
    while(p){
        if(!visited[p->adjvex])
            DFS(p->adjvex);//传入边表的值-->再到顶点表里面找对应位置
        p=p->next;
    }
}

//邻接表的深度遍历操作
template <class DataType>
void ALGraph<DataType> :: DFSTraverse()
{
    int i;
    for(i=0; i<vertexNum; i++){//i小于顶点数
        visited[i] = false;  //初始化所有顶点都是未访问状态
    }
    for(i=0; i<vertexNum; i++){
        if(!visited[i])/*对未访问过的顶点调用DFS,若是连通图,只会执行一次  */
            DFS(i);
    }
}

BFS代码

template <class DataType>
void ALGraph<DataType> :: BFS()/*从0开始BFS遍历*/
{
    int i;
    ArcNode *p; //边表指针
    queue<int> Q;//初始化顺序队列
    for(i=0; i<vertexNum; i++)
        visited[i] = false;
    for(i=0; i<vertexNum; i++){
        if(!visited[i]){
            visited[i] = true;
            cout<<adjlist[i].vertex<<" ";//打印顶点
            Q.push(i);//i入队列
            while(!Q.empty())
            {
                Q.pop();
                p = adjlist[i].firstedge;//找到当前顶点表边表链表的头指针
                while(p){
                    if(!visited[p->adjvex]){//顶点没有被访问
                        visited[p->adjvex] = true;
                        cout << adjlist[p->adjvex].vertex <<" ";//输出顶点表的对应的下标
                        Q.push(p->adjvex);//将此顶点入队列
                    }
                    p=p->next;
                }
            }
        }
    }
}

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值