数据结构之C++实现图的邻接矩阵、邻接表、深度优先DFS、广度优先BFS

c++实现图的邻接矩阵、邻接表、深度优先DFS、广度优先BFS

#include "stdio.h"    
#include "stdlib.h"   
#include "math.h"  
#include "time.h"
#include <iostream>
using namespace std;
#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0
#define MAXVEX 100 /* 最大顶点数,应由用户定义 */
#define GRAPH_INFINITY 65535 /* 用65535来代表∞ */
typedef int Status; /* Status是函数的类型,其值是函数结果状态代码,如OK等 */
typedef char VertexType; /* 顶点类型应由用户定义  */
typedef int EdgeType; /* 边上的权值类型应由用户定义 */
//邻接矩阵  ----  图
struct queue//辅助队列
{
    int front,rear;//头指针和尾指针,若队列不为空,则尾指针指向队尾元素的下一个元素
    int data[MAXVEX];
};
class MGraph
{
public:
    MGraph();
    //~MGraph();
    void CreateMGraph(void);
    void CreateMGraph_example(void);
    void show(void);
    bool isempty(void);
    void EnQueue(int e);
    void DeQueue(int *e);
    void DFS(int i);/* 邻接矩阵的深度优先递归算法 */
    void DFSTraverse(void);/* 邻接矩阵的深度遍历操作 */
    void BFSTraverse(void);//邻接矩阵广度遍历算法
public:
    VertexType vexs[MAXVEX];/*顶点表*/
    EdgeType arc[MAXVEX][MAXVEX];//邻接矩阵
    int numNodes,numEdges;//图中的顶点数和边数
    bool visited[MAXVEX];//访问遍历标志数组,辅助数组
    queue *q=new queue;
};
MGraph::MGraph()//初始化邻接点和邻接矩阵
{
    numNodes=0;
    numEdges=0;
    q->front=0;
    q->rear=0;
    for(int i=0;i<numNodes;i++) q->data[i]=0;
    for(int i=0;i<MAXVEX;i++) vexs[i]=0;
    for(int i=0;i<MAXVEX;i++) for(int j=0;j<MAXVEX;j++) arc[i][j]=GRAPH_INFINITY;
    for(int i=0;i<numNodes;i++) visited[i]=false;
}
void MGraph::CreateMGraph(void)
{
    int i,j,k,w;
    cout<<"输入顶点数和边数:"<<endl;
    cin>>numNodes>>numEdges;
    cout<<"读入顶点的值:"<<endl;
    for(i=0;i<numNodes;i++) cin>>vexs[i]; //读入顶点信息,建立顶点表
    //for(i=0;i<numNodes;i++) for(int j=0;j<numNodes;j++) arc[i][j]=GRAPH_INFINITY;//邻接矩阵初始化
    for(k=0;k<numEdges;k++) //读入numEdges条边,建立邻接矩阵
    {
        cout<<"输入边(vi,vj)上的下标i,下标j,权w:"<<endl;
        cin>>i>>j>>w;
        arc[i][j]=w;
        arc[j][i]=arc[i][j];//因为是无向图,矩阵对称   
    }
}
void MGraph::show(void) //打印邻接矩阵
{   if(numNodes==0) cout<<"顶点表为空,无顶点!!!"<<endl;
    else
    {
        cout<<"顶点表为: ";
        for(int i=0;i<numNodes;i++) cout<<vexs[i]<<"  ";
        cout<<endl<<"邻接矩阵为:"<<endl;
        for(int i=0;i<numNodes;i++) 
        {
            for(int j=0;j<numNodes;j++) cout<<arc[i][j]<<" ";
            cout<<endl;
        } 
    } 
}
bool MGraph::isempty(void)//判断队列是否为空
{
    if(q->front==q->rear) return true;
    else return false;
}
void MGraph::EnQueue(int e)
{
    if((q->rear+1)%MAXVEX==q->front)
    {
        cout<<"队列已满!!!"<<endl;
        exit(1);
    }
    else
    {
        q->data[q->rear]=e;//将元素赋值给队尾元素
        q->rear=(q->rear+1)%MAXVEX;//指针向后移动一个位置,若到最后则转到数组头部
    }
}
void MGraph::DeQueue(int *e)
{
    if(q->front==q->rear) cout<<"队列为空!!!"<<endl;
    else
    {
        *e=q->data[q->front];//将对头元素赋值给e
        q->front=(q->front+1)%MAXVEX;//front指针向后移动一位,若到最后则转到数组头部
    }
}
void MGraph::CreateMGraph_example(void)
{
    int i, j;
    numEdges=15;
    numNodes=9;    /* 读入顶点信息,建立顶点表 */
    vexs[0]='A';
    vexs[1]='B';
    vexs[2]='C';
    vexs[3]='D';
    vexs[4]='E';
    vexs[5]='F';
    vexs[6]='G';
    vexs[7]='H';
    vexs[8]='I';
    for (i=0;i<numNodes;i++)/*初始化图*/
    {
        for (j=0;j<numNodes;j++)
        {
            arc[i][j]=0;
        }
    }
    arc[0][1]=1;
    arc[0][5]=1;
    arc[1][2]=1; 
    arc[1][8]=1; 
    arc[1][6]=1; 
    
    arc[2][3]=1; 
    arc[2][8]=1; 
    
    arc[3][4]=1;
    arc[3][7]=1;
    arc[3][6]=1;
    arc[3][8]=1;

    arc[4][5]=1;
    arc[4][7]=1;

    arc[5][6]=1; 
    
    arc[6][7]=1; 
    for(i=0;i<numNodes;i++)
    {
        for(j=i;j<numNodes;j++)
        {
            arc[j][i]=arc[i][j];
        }
    }
}
/* 邻接矩阵的深度优先递归算法 */
void MGraph::DFS(int i)
{
    int j;
    visited[i]=true;
    cout<<vexs[i]<<" ";//打印顶点,也可以进行别的操作
    for(j=0;j<numNodes;j++)
    {
        if(!visited[j]&&arc[i][j]!=0) DFS(j);
    }
}
/* 邻接矩阵的深度遍历操作 */
void MGraph::DFSTraverse(void)
{
    for(int i=0;i<numNodes;i++)
    {
        if(!visited[i]) DFS(i);//对未访问过的顶点调用DFS,若是连通图,只会执行一次
    }
}
/* 邻接矩阵的广度遍历算法 */
void MGraph::BFSTraverse(void)
{
    int i,j;
    for(i=0;i<numNodes;i++)  /* 对每一个顶点做循环 */
    {
        if(!visited[i])
        {
            visited[i]=true;
            cout<<vexs[i]<<" ";
            EnQueue(i);//将此顶点加入辅助队列
            while(!isempty())
            {
                DeQueue(&i);
                for(j=0;j<numNodes;j++) 
                { 
                    /* 判断其它顶点若与当前顶点存在边且未访问过  */
                    if(arc[i][j] == 1 && !visited[j]) 
                    { 
                        visited[j]=TRUE;            /* 将找到的此顶点标记为已访问 */
                        cout<<vexs[j]<<" ";         /* 打印顶点 */
                        EnQueue(j);              /* 将找到的此顶点入队列  */
                    } 
                }
            }
        }
    }
}
    

//邻接表
struct EdgeNode //边表节点
{
    int adjvex; //邻接点域,存储该顶点对应的下标
    EdgeType info; //用于存储权值,对于非网图可不需要
    struct EdgeNode* next;//指向下一个邻接点
};
struct VertexNode//顶点表节点
{
    VertexType data;//顶点域,存储顶点信息
    EdgeNode* firstedge;//边表头指针
    int in; /* 顶点入度 */
};

//邻接表-----图
class GraphAdjList
{
public:
    GraphAdjList();
    //~GraphAdjList();
    void CreateALGraph(void);
    void CreateALGraph_example(void);
    bool isempty(void);
    void show(void); 
    void EnQueue(int e);/* 若队列未满,则插入元素e为新的队尾元素 */
    void DeQueue(int *e);//若队列不为空,则删除队列中对头元素
    void DFS(int i);//邻接表的深度优先递归算法
    void DFSTraverse(void);//邻接表的深度遍历操作
    void BFSTraverse(void);//邻接表的广度优先遍历算法
public:
    VertexNode AdjList[MAXVEX];//顶点表
    int numNodes,numEdges;//图中的顶点数和边数
    queue* q=new queue;//辅助队列
    bool visited[MAXVEX];//辅助数组
};
GraphAdjList::GraphAdjList()//初始化顶点表,顶点数和边数
{
    numNodes=0;
    numEdges=0;
    for(int i=0;i<MAXVEX;i++)
    {
        AdjList[i].data=0;
        AdjList[i].firstedge=NULL;
    }
    //初始化辅助队列
    q->front=q->rear=0;
    for(int i=0;i<numNodes;i++) q->data[i]=0;
    for(int i=0;i<numNodes;i++) visited[i]=false;
}
//创建图的邻接表结构
void GraphAdjList::CreateALGraph(void)
{
    int i,j,k;
    EdgeNode* e;
    cout<<"输入顶点数和边数:"<<endl;
    cin>>numNodes>>numEdges;
    for(i=0;i<numNodes;i++)//读入顶点信息,建立顶点表
    {
        cin>>AdjList[i].data;//输入顶点信息
        AdjList[i].firstedge=NULL;//将边表置空
    }
    //建立边表
    for(k=0;k<numEdges;k++)
    {
        cout<<"输入边(vi,vj)上的顶点序号: "<<endl;
        cin>>i>>j;
        e=new EdgeNode;//向内存申请空间,生成边表节点
        e->adjvex=j;//邻接序号为j
        e->next=AdjList[i].firstedge;//将e的指针指向当前顶点上指向的节点
        AdjList[i].firstedge=e;//将当前顶点的指针指向e

        e=new EdgeNode;//向内存申请空间,生成边表节点 
        e->adjvex=i;
        e->next=AdjList[j].firstedge;//将e的指针指向当前顶点上指向的节点
        AdjList[j].firstedge=e;//将当前顶点的指针指向e
    }
}
void GraphAdjList::CreateALGraph_example(void)
{
    int i;
    EdgeNode *e;
    numEdges=15;
    numNodes=9; 
    //读入顶点信息,建立顶点表
    AdjList[0].data='A';
    AdjList[1].data='B';
    AdjList[2].data='C';
    AdjList[3].data='D';
    AdjList[4].data='E';
    AdjList[5].data='F';
    AdjList[6].data='G';
    AdjList[7].data='H';
    AdjList[8].data='I';
    //将边表置为空表
    for(i=0;i<numNodes;i++) AdjList[i].firstedge=NULL;
    //建立边表
    e=new EdgeNode;
    e->adjvex=1;
    e->next=AdjList[0].firstedge;
    AdjList[0].firstedge=e;
    e=new EdgeNode;
    e->adjvex=5;
    e->next=AdjList[0].firstedge;
    AdjList[0].firstedge=e;


    e=new EdgeNode;
    e->adjvex=2;
    e->next=AdjList[1].firstedge;
    AdjList[1].firstedge=e; 
    e=new EdgeNode;
    e->adjvex=8;
    e->next=AdjList[1].firstedge;
    AdjList[1].firstedge=e;
    e=new EdgeNode;
    e->adjvex=6;
    e->next=AdjList[1].firstedge;
    AdjList[1].firstedge=e; 
  
    e=new EdgeNode;
    e->adjvex=3;
    e->next=AdjList[2].firstedge;
    AdjList[2].firstedge=e;  
    e=new EdgeNode;
    e->adjvex=8;
    e->next=AdjList[2].firstedge;
    AdjList[2].firstedge=e; 


    e=new EdgeNode;
    e->adjvex=4;
    e->next=AdjList[3].firstedge;
    AdjList[3].firstedge=e; 
    e=new EdgeNode;
    e->adjvex=7;
    e->next=AdjList[3].firstedge;
    AdjList[3].firstedge=e; 
    e=new EdgeNode;
    e->adjvex=6;
    e->next=AdjList[3].firstedge;
    AdjList[3].firstedge=e; 
    e=new EdgeNode;
    e->adjvex=8;
    e->next=AdjList[3].firstedge;
    AdjList[3].firstedge=e;  

    e=new EdgeNode;
    e->adjvex=5;
    e->next=AdjList[4].firstedge;
    AdjList[4].firstedge=e;   
    e=new EdgeNode;
    e->adjvex=7;
    e->next=AdjList[4].firstedge;
    AdjList[4].firstedge=e;   
 

    e=new EdgeNode;
    e->adjvex=6;
    e->next=AdjList[5].firstedge;
    AdjList[5].firstedge=e;    

    e=new EdgeNode;
    e->adjvex=7;
    e->next=AdjList[6].firstedge;
    AdjList[6].firstedge=e;       
    /*for(i=0;i<numNodes;i++) //建立边表 
    { 
        for(j=0;j<numNodes;j++)
        {
            e=(EdgeNode *)malloc(sizeof(EdgeNode));
            e->adjvex=j;                    // 邻接序号为j                          
            e->next=(*GL)->adjList[i].firstedge;    // 将当前顶点上的指向的结点指针赋值给e 
            (*GL)->adjList[i].firstedge=e;      // 将当前顶点的指针指向e   
            //(*GL)->adjList[j].in++;             
        }
    }*/
}
void GraphAdjList::show(void)
{
    if(numNodes == 0) cout<<"当前无顶点"<<endl;
    else 
    {
        cout<<"各个顶点的值为:";
        for(int i=0;i<numNodes;i++) cout<<AdjList[i].data<<"  ";
    }
}
bool GraphAdjList::isempty(void)
{
    if(q->front==q->rear) //队列为空
    {
        return true;
    }
    else
    {
        return false;
    }
}
void GraphAdjList::EnQueue(int e)
{
    if((q->rear+1)%MAXVEX == q->front)    /* 队列满的判断 */
    {
        cout<<"queue is full!!!"<<endl;
        exit(1);
    }
    else
    {
        q->data[q->rear]=e;         /* 将元素e赋值给队尾 */
        q->rear=(q->rear+1)%MAXVEX;/* rear指针向后移一位置, */
                                    /* 若到最后则转到数组头部 */
    }
}
void GraphAdjList::DeQueue(int *e)
{
    if(q->front==q->rear)//队列为空的判断
    {
        cout<<"queue is empty!!!"<<endl;
        exit(1);
    }
    else
    {
        *e=q->data[q->front];//将对头元素赋值给e
        q->front=(q->front+1)%MAXVEX;//front指针向后移动一个位置,若到最后则转到数组头部
    }
}
//邻接表的深度优先递归算法
void GraphAdjList::DFS(int i)
{
    EdgeNode* p;
    visited[i]=true;
    cout<<AdjList[i].data<<" ";//打印顶点也可执行其他操作
    p=AdjList[i].firstedge;
    while(p)
    {   
        if(!visited[p->adjvex]) DFS(p->adjvex);//对未访问的邻接顶点进行递归
        p=p->next;
    }   
}
//邻接表的深度遍历操作
void GraphAdjList::DFSTraverse(void)
{
    int i;
    for(i=0;i<numNodes;i++)
    {
        if(!visited[i]) DFS(i);//对未访问过的顶点调用DFS,若是连通图,只会执行一次
    }
}
//邻接表的广度优先遍历算法weile banh
void GraphAdjList::BFSTraverse(void)
{
    int i;
    EdgeNode *p;
    for(i=0;i<numNodes;i++)
    {
        if(!visited[i])
        {
            visited[i]=true;
            cout<<AdjList[i].data<<" ";//打印顶点也可执行其他操作 
            EnQueue(i);
            while(!isempty())
            {
                DeQueue(&i);
                p=AdjList[i].firstedge;//找到当前顶点的边表链表头指针
                while(p)
                {
                    if(!visited[p->adjvex])//当前顶点未被访问
                    {
                        visited[p->adjvex]=true;
                        cout<<AdjList[p->adjvex].data<<" ";
                        EnQueue(p->adjvex);//将此顶点入队列
                    }
                    p=p->next;//指针指向下一个邻接点
                }
            }
        }
    }
}
int main()
{
    //创建邻接矩阵测试
    MGraph* graph = new MGraph;
    //graph->show();    
    //graph->CreateMGraph();
    graph->CreateMGraph_example();
    graph->show();
    cout<<"深度遍历:"<<endl;
    graph->DFSTraverse();
    //遍历完成后,要将辅助数组重新初始化,这样才能重新遍历成功
    for(int i=0;i<graph->numNodes;i++) graph->visited[i]=false;
    cout<<endl<<"广度遍历:"<<endl;
    graph->BFSTraverse();
    cout<<endl;
    //创建邻接表测试
    GraphAdjList* AdjListgraph=new GraphAdjList;
    //AdjListgraph->CreateALGraph();
    //AdjListgraph->show();
    AdjListgraph->CreateALGraph_example();
    AdjListgraph->show();
    cout<<endl<<"深度遍历: ";
    AdjListgraph->DFSTraverse();
    cout<<endl<<"广度遍历: ";
    for(int i=0;i<AdjListgraph->numNodes;i++) AdjListgraph->visited[i]=false;//重新初始辅助数组
    AdjListgraph->BFSTraverse();
    cout<<endl;
    return 0;
}

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

早茶&&月光

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值