#实验备忘录#
//邻接矩阵实现图
#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");
}