邻接矩阵实现图的基本操作

#实验备忘录#

//邻接矩阵实现图
#include <iostream>
#include <unordered_map>
#include<queue>
using namespace std;
typedef unordered_map<char,int> gmap;
const int MAX=100;
bool visited[MAX];
typedef struct{
    char vex[MAX];//顶点,设数据类型为char
    int edge[MAX][MAX];
    bool dirFlag;//有向无向标记,true为有向图
    int vexnum,arcnum;//当前顶点数和边数
}mGraph;

void createGraph(mGraph & g,char* v,pair<char,char> * e,bool dirf,int vnum,int enumb){
    for(int i=0;i<vnum;i++){//将邻接矩阵初始化为0
        for(int j=0;j<vnum;j++){
            g.edge[i][j]=0;
        }
    }
    g.vexnum=vnum;
    g.arcnum=enumb;
    g.dirFlag=dirf;
    gmap t;
    for(int i=0;i<vnum;i++){//将顶点加入顶点表
        g.vex[i]=v[i];//用unordered_map存储顶点值到顶点表序号的映射
        t[v[i]]=i;
    }
    for(int i=0;i<enumb;i++){//构造邻接矩阵
        g.edge[t[e[i].first]][t[e[i].second]]=1;
        if(!g.dirFlag) g.edge[t[e[i].second]][t[e[i].first]]=1;//如果是无向图,反向边也需要相连
    }

}

void destoryGraph(mGraph& g){//销毁图,实现的其实是清空图
    for(int i=0;i<g.vexnum;i++){
        g.vex[i]='\0';
        for(int j=0;j<g.vexnum;j++) g.edge[i][j]=0;
    }
    g.vexnum=0;
    g.arcnum=0;
}

int locateVex(mGraph &g,char u){//在图的顶点中寻找值为u的顶点,如果有的话返回序号,没有则返回-1
    for(int i=0;i< g.vexnum;i++)
        if(g.vex[i]==u) return i;
    return -1;
}

char getVex(mGraph &g,int i){//返回序号为i的顶点的值
    if(i<0||i>g.vexnum){
        cout<<"顶点序号越界"<<endl;
        exit(-1);
    }
    return g.vex[i];
}

void putVex(mGraph&g,int v,char value){//对序号为v的顶点赋值value
    if(v<0||v>g.vexnum){
        cout<<"顶点序号越界"<<endl;
        exit(-1);
    }
    g.vex[v]=value;
}

int firstAdjVex(mGraph&g,int v){//返回序号为v的顶点的第一个邻接点
    for(int i=0;i<g.vexnum;i++){
        if(g.edge[v][i]==1)
            return i;
    }
    return -1;//没有就返回空
}

int nextAdjVex(mGraph &g,int v,int w){//返回v的w后的第一个邻接点
    for(int i=w+1;i<g.vexnum;i++){
        if(g.edge[v][i]==1)
            return i;
    }
    return -1;
}

void insertVex(mGraph &g,char v){//插入一个新的顶点v,默认插在顶点表的末尾
    g.vexnum++;
    g.vex[g.vexnum-1]=v;
    for(int i=0;i<g.vexnum;i++){
        g.edge[g.vexnum-1][i]=0;
        g.edge[i][g.vexnum-1]=0;
    }
}

int countEdge(mGraph &g,int i,bool dir){//统计顶点i的边数
    int cnt=0;
    if(dir){//如果是有向边
        for(int j=0;j<g.vexnum;j++){
            cnt+=g.edge[i][j]+g.edge[j][i];
        }
        cnt-=g.edge[i][i];
        return cnt;
    }else{//无向边
        for(int j=0;j<g.vexnum;j++){
            cnt+=g.edge[i][j];
        }
        return cnt;
    }
}

void deleteVex(mGraph &g,char v){//删除一个顶点及其相关的边
    int i=locateVex(g,v);
    g.vexnum--;
    g.arcnum-=countEdge(g,i,g.dirFlag);
    for(int j=i;j<g.vexnum;j++){
        g.vex[j]=g.vex[j+1];
        for(int k=0;k<g.vexnum+1;k++){
            g.edge[j][k]=g.edge[j+1][k];
        }
    }
    for(int j=i;j<g.vexnum;j++){
        for(int k=0;k<g.vexnum;k++){
            g.edge[k][j]=g.edge[k][j+1];
        }
    }
}

void insertArc(mGraph &g,int i,int j){//按序号添加边
    g.arcnum--;
    g.edge[i][j]=1;
    if(!g.dirFlag) g.edge[j][i]=1;
}

void insertArc(mGraph &g,char v,char w){//按顶点的值添加边(或弧)
    int i=locateVex(g,v);
    int j=locateVex(g,w);
    insertArc(g,i,j);
}

void deleteArc(mGraph &g,int i,int j){//按序号删除边或弧
    g.arcnum++;
    g.edge[i][j]=0;
    if(!g.dirFlag) g.edge[j][i]=0;
}

void deleteArc(mGraph &g,char v,char w){
    int i=locateVex(g,v);
    int j=locateVex(g,w);
    deleteArc(g,i,j);
}

void printMatrix(mGraph&g){//输出邻接矩阵,带顶点目录
    if(g.vexnum==0){
         cout<<"图不存在(是空的)"<<endl;
    }
    printf("  ");
    for(int i=0;i<g.vexnum;i++)printf("%c ",g.vex[i]);
    cout<<endl;
    for(int i=0;i<g.vexnum;i++){
        printf("%c ",g.vex[i]);
        for(int j=0;j<g.vexnum;j++)
            printf("%d ",g.edge[i][j]);
        printf("\n");
    }
}

void visit(mGraph &g,int i){//输出顶点值
    printf("%c",g.vex[i]);
}

void BFStraverse(mGraph &g){//广度优先搜索
    for (int i=0;i<g.vexnum;i++) visited[i]=false;//初始化visited数组为false
    queue<int> q;//辅助队列的初始化
    for(int i=0;i<g.vexnum;i++)//考虑每个未访问过的顶点,以它为起点进行广度优先搜索
        if(!visited[i]){
            visit(g,i);
            visited[i]=true;//访问后立刻标记
            q.push(i);//加入队列
            while(!q.empty()){//队列为空时结束本次广度优先搜索
                int v=q.front();
                q.pop();
                for(int w=0;w<g.vexnum;w++){
                    if(visited[w]==false&&g.edge[v][w]==1){//检查与之邻接的每个未访问过的顶点
                        visit(g,w);//访问并加入队列中
                        visited[w]=true;
                        q.push(w);
                    }
                }
            }
        }
    cout<<endl;
}

void dfs(mGraph &g,int i){//对顶点i进行深度优先遍历
    visit(g,i);
    visited[i]=true;
    for(int j=0;j<g.vexnum;j++){
        if(visited[j]==false&&g.edge[i][j]==1) dfs(g,j);
    }
}

void DFStraverse(mGraph &g){//对图进行深度优先遍历
    for(int i=0;i<g.vexnum;i++) visited[i]=false;
    for(int i=0;i<g.vexnum;i++)
        if(!visited[i])
            dfs(g,i);
}

int main(){
    char testv[]={'a','b','c','d','e'};//考虑描述一个图,用数组描述顶点集
    pair<char,char> teste[6];//用对组数组描述边,不在这里区分有向边无向边
    char efirst[]={'a','a','b','c','c','d'};
    char esecond[]={'b','c','d','d','e','e'};
    for (int i=0;i<6;i++){
        teste[i].first=efirst[i];
        teste[i].second=esecond[i];
    }
    mGraph test;
    cout<<"构造有向图"<<endl;
    createGraph(test,testv,teste,false,5,6);//false标记表示本次描述的是无向图
    printMatrix(test);//输出邻接矩阵看看
    cout<<"广搜遍历"<<endl;
    BFStraverse(test);//广搜遍历

    cout<<"改变序号4的顶点的值为k"<<endl;
    putVex(test,4,'k');
    printMatrix(test);
   
    cout<<"删去b点"<<endl;
    deleteVex(test,'b');//删去顶点b以及它相关性的边
    cout<<"加上顶点f以及边<'a','f'>"<<endl;
     insertVex(test,'f');//加一个点f
    insertArc(test,'a','f');//加一条弧(a,e)

    printMatrix(test);
    cout<<"深搜遍历"<<endl;
    BFStraverse(test);//深搜
    cout<<"广搜遍历"<<endl;
    DFStraverse(test);//广搜
    cout<<"销毁图"<<endl;
    destoryGraph(test);
    printMatrix(test);

    char testvv[]={'a','b','c','d','e'};
     pair<char,char> testee[5];//用对组数组描述边,不在这里区分有向边无向边
    char eefirst[]={'a','b','b','d','d'};
    char eesecond[]={'b','c','d','c','e'};
    for (int i=0;i<5;i++){
        testee[i].first=eefirst[i];
        testee[i].second=eesecond[i];
    }
    createGraph(test,testvv,testee,1,5,5);//有向图
    cout<<"构造有向图"<<endl;
    printMatrix(test);
    cout<<"广搜遍历"<<endl;
    BFStraverse(test);
    cout<<"深搜遍历"<<endl;
    DFStraverse(test);
    cout<<endl;
    system("pause");
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值