基于邻接表的无向图实现

 

 

存储结构:

ArcNode 边表节点数据结构(包含索引值vertex和next)

VertexNode 顶点表节点数据结构(包含顶点数据和第一个边表节点firstEnde)
adjlist[] 顶点表节点数组
vertexNum 顶点数
arcNum 边数
visited[] 标志数组

 

 

功能:
1.构建基于邻接表的无向图
2.深度优先遍历
3.广度优先遍历

伪代码:
构建
1.标志数组初始化
2.顶点表节点数组初始化赋值
3.重复arcNum次下列操作
  3.1 输入边的两顶点
  3.2 new一个边表节点i,j
  3.3 将索引值赋为j
  3.4 将该节点用头插法插入i的链表
  3.5 i,j互换,重复上述操作

深度遍历
1.输出一个顶点v的数据并将v的firstEdge赋给p
2.重复下列操作直到p==NULL
  2.1 将p的索引值赋给j
  2.2 如果该索引值对应的顶点节点未被访问深度遍历j
  2.3 p指向p->next

广度遍历
1.初始化visited数组
2.重复下列操作vertexNum次
  2.1 初始化队列
  2.2 输出该顶点数据并将其入队
  2.3 当队列不为空时重复下列操作
     2.3.1 队首出队(++front)并赋给i
     2.3.2 将i对应的顶点的firstEdge赋给p
     2.3.3 重复下列擦欧洲哦直到p==NULL
           2.3.3.1 获得p的下标
           2.3.3.2 如果p的下标对应的顶点未被访问输出该顶点数据并标志其已访问,并将其入队

           2.3.3.3 p=p->next;

 

 

#include<iostream>

using namespace std;

#define MaxSize 100

//边表节点
struct ArcNode
{
    int adjvex;                //下标,索引值
    ArcNode *next;             //指向下一个边表节点
};

//顶点表表节点(最开始的那批数据)
template<class T>
struct VertexNode
{
    T vertexData;               //顶点数据
    ArcNode *firstEdge;         //指向第一个边表节点
};

/**基于邻接表的无向图*/
template<class T>
class ALGraph
{
private:
    void DFS(int v);
public:
    ALGraph();
    ~ALGraph() {}
    void DFSTraverse();
    void BFSTraverse();
private:
    VertexNode<T> adjlist[MaxSize];        //储存顶点表节点的数组
    int VertexNum,arcNum;
    int visited[MaxSize];
};

template<class T>
ALGraph<T>::ALGraph()
{
    int i,j,k;
    cout<<"依次输入顶点数n、边数e、及n个顶点的编号和顶点之间的连通关系的两个顶点的编号:"<<endl;

    cin>>VertexNum;
    cin>>arcNum;

    //把标志数组初始化
    //虽然两个遍历都会初始化,但是先行初始化总是好的,避免还未遍历便要用vidited的情况
    for(i=0; i<MaxSize; i++)
        visited[i]=0;

    //顶点数据赋值
    for(i=0; i<VertexNum; i++)
    {
        cin>>adjlist[i].vertexData;
        adjlist[i].firstEdge=NULL;
    }

    //边关系
    for(k=0; k<arcNum; k++)
    {
        cin>>i>>j;
        ArcNode *s1=new ArcNode;
        s1->adjvex=j;
        s1->next=adjlist[i].firstEdge;
        adjlist[i].firstEdge=s1;

        ArcNode *s2=new ArcNode;
        s2->adjvex=i;
        s2->next=adjlist[j].firstEdge;
        adjlist[j].firstEdge=s2;
    }
}

template<class T>
void ALGraph<T>::DFS(int v)
{
    int j;
    ArcNode *p;

    cout<<adjlist[v].vertexData<<' ';
    visited[v]=1;
    p=adjlist[v].firstEdge;

    while(p!=NULL)                  //依次搜索各个邻接点
    {
        j=p->adjvex;

        if(visited[j]==0)
            DFS(j);         //中途抢占,深度遍历

        p=p->next;
    }
}


template<class T>
void ALGraph<T>::DFSTraverse()
{
    int i,v;
    //标记数组初始化
    for(i=0; i<MaxSize; i++)
        visited[i]=0;

    cout<<"深度优先遍历的结果为:";
    for(i=0; i<VertexNum; i++)      //直接从头开始一个顶点一个顶点的遍历,虽然好像有点流氓
    {
        v=adjlist[i].vertexData;
        if(!visited[v])
        {
            DFS(v);
        }
    }

    cout<<endl;
}

template<class T>
void ALGraph<T>::BFSTraverse()
{
    int front,rear,i,j,v;
    int Q[MaxSize];
    ArcNode *p;

    //把标志数组初始化
    for(i=0; i<MaxSize; i++)
        visited[i]=0;

    cout<<"广度优先遍历的结果为:";
    for(i=0; i<VertexNum; i++)      //直接从头开始一个顶点一个顶点的遍历,虽然好像有点流氓
    {
        v=adjlist[i].vertexData;

        if(visited[v]==0)
        {
            front=rear=-1;
            cout<<adjlist[i].vertexData<<' ';
            visited[v]=1;

            Q[++rear]=v;                //下标入队

            while(front!=rear)          //队列不空,循环
            {
                v=Q[++front];
                p=adjlist[v].firstEdge;

                while(p!=NULL)
                {
                    j=p->adjvex;        //获得下标
                    if(visited[j]==0)
                    {
                        cout<<adjlist[j].vertexData<<' ';
                        visited[j]=1;
                        Q[++rear]=j;
                    }
                    p=p->next;
                }
            }
        }
    }

    cout<<endl;
}

int main()
{
    int n,e,i;
    int a[MaxSize];

    ALGraph<int> G;

    G.DFSTraverse();
    G.BFSTraverse();

    return 0;
}

 

 

 

测试数据:

输入:
6 5
0 1 2 3 4 5
0 1
0 3
1 2
2 3
4 5


输出:
深度优先遍历的结果为:0 3 2 1 4 5

广度优先遍历的结果为:0 3 1 2 4 5

 

该图为数据的图示

  • 1
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值