/************************************ 图的邻接矩阵(数组)表示 by Rowandjj 2014/6/22 ************************************/ #include<iostream> using namespace std; #define INFINTY_INT_MAX 0x7fffffff //代表正无穷 #define MAX_VERTIEX_NUM 20 //最大顶点个数 #define MAX_INFO 20 typedef enum{DG,DN,AG,AN}GraphKind;//有向图、有向网、无向图、无向网 typedef struct { int adj;//顶点关系类型 char *info;//该弧的相关信息 }ArcCell,AdjMatrix[MAX_VERTIEX_NUM][MAX_VERTIEX_NUM]; typedef struct { char vexs[MAX_VERTIEX_NUM];//顶点向量 AdjMatrix arcs;//邻接矩阵 int vexnum,arcnum;//顶点数、弧数 GraphKind kind;//种类 }MGraph,*pMGraph; bool visited[MAX_VERTIEX_NUM];//访问标志数组(全局) bool (*VisitFunc)(char); bool Visit(char v) { cout<<v; return true; } //----------------操作------------------------------- int LocateVex(MGraph G,char u);//若G中存在顶点u,则返回该顶点在图中位置;否则返回-1 bool CreateDG(pMGraph G);//创建有向图 bool CreateDN(pMGraph G);//创建有向网 bool CreateAG(pMGraph G);//创建无向图 bool CreateAN(pMGraph G);//创建无向网 bool CreateGraph(pMGraph G);//构造图 void DestroyGraph(pMGraph G);//销毁图G char GetVex(MGraph G,int v);//初始条件: 图G存在,v是G中某个顶点的序号。操作结果: 返回v的值 bool PutVex(pMGraph G,char v,char iValue);//初始条件: 图G存在,v是G中某个顶点。操作结果: 对v赋新值value int FirstAdjVex(MGraph G,char v);//返回v的第一个邻接顶点的序号 int NextAdjVex(MGraph G,char v,char w);//返回v的(相对于w的)下一个邻接顶点的序号,否则返回-1 void InsertVex(pMGraph G,char v);//在图G中增添新顶点v(不增添与顶点相关的弧,留待InsertArc()去做) bool DeleteVex(pMGraph G,char v);//删除G中顶点v及其相关的弧 bool InsertArc(pMGraph G,char v,char w);//在G中增添弧<v,w>,若G是无向的,则还增添对称弧<w,v> bool DeleteArc(pMGraph G,char v,char w);//在G中删除弧<v,w>,若G是无向的,则还删除对称弧<w,v> void DFSTravel(MGraph G,bool (*Visit)(char));//深度优先 void DFS(MGraph G,int v); void BFSTravel(MGraph G,bool (*Visit)(char));//广度优先 void Display(MGraph G); //----------------辅助队列-------------------------- typedef struct _QUEUENODE_ { int data; struct _QUEUENODE_ *next; }QueueNode,*pQueueNode; typedef struct _QUEUE_ { int size; pQueueNode pHead; pQueueNode pTail; }Queue,*pQueue; bool InitQueue(pQueue Q); bool DestroyQueue(pQueue Q); bool DeQueue(pQueue Q,int* e); bool EnQueue(pQueue Q, int e); bool QueueEmpty(Queue Q); //------------------------------------------ bool InitQueue(pQueue Q) { Q->pHead = Q->pTail = (pQueueNode)malloc(sizeof(QueueNode)); if(!Q->pHead) { return false; } Q->pHead->next = NULL; Q->size = 0; return true; } bool DestroyQueue(pQueue Q) { pQueueNode pTemp = Q->pHead->next; while(pTemp != NULL) { Q->pHead->next = pTemp->next; free(pTemp); pTemp = Q->pHead->next; } free(Q->pHead); Q->size = 0; return true; } bool QueueEmpty(Queue Q) { return Q.size == 0; } bool DeQueue(pQueue Q,int* e) { pQueueNode pDel = Q->pHead->next; if(pDel != NULL) { *e = pDel->data; Q->pHead->next = pDel->next; if(Q->pTail == pDel) { Q->pTail = Q->pHead; } free(pDel); Q->size--; } return true; } bool EnQueue(pQueue Q, int e) { pQueueNode pNew = (pQueueNode)malloc(sizeof(QueueNode)); if(!pNew) { return false; } pNew->next = NULL; pNew->data = e; Q->pTail->next = pNew; Q->pTail = pNew; Q->size++; return true; } //------------------------------------------ int LocateVex(MGraph G,char u) { int i = 0; for(i = 0; i < G.vexnum;i++) { if(u == G.vexs[i]) { return i; } } return -1; } bool CreateDG(pMGraph G) { int incInfo = 0; int i,j,k,l; char va,vb; char *info; char s[MAX_INFO] = {0};//存放弧信息 cout<<"请输入有向图G的顶点数,弧数,弧是否含其它信息(是:1,否:0)"<<endl; cin>>G->vexnum; cin>>G->arcnum; cin>>incInfo; cout<<"请输入顶点值"<<endl; for(i = 0; i < G->vexnum; i++)//构造顶点向量 { cin>>G->vexs[i]; } for(i = 0; i < G->vexnum; i++)//初始化邻接矩阵 { for(j = 0 ;j < G->vexnum; j++) { G->arcs[i][j].adj = 0; G->arcs[i][j].info = NULL; } } cout<<"请输入每条弧的弧头和弧尾"<<endl; for(k = 0; k < G->arcnum; k++) { cin>>va; cin>>vb; i = LocateVex(*G,va); j = LocateVex(*G,vb); G->arcs[i][j].adj = 1; if(incInfo) { cout<<"输入该弧的信息"<<endl; cin>>s; l = strlen(s); if(l) { info = (char *)malloc(sizeof(char) * (l+1)); strcpy(info,s); G->arcs[i][j].info = info; } } } G->kind = DG; return true; } bool CreateDN(pMGraph G) { int incInfo; int i,j,k,l,w; char s[MAX_INFO]; cout<<"请输入有向网G的顶点数,弧数,弧是否含其它信息(是:1,否:0)"<<endl; cin>>G->vexnum; cin>>G->arcnum; cin>>incInfo; char va,vb;//分别代表弧头、弧尾 char *pInfo; cout<<"请输入顶点值"<<endl; for(i = 0; i < G->vexnum; i++) { cin>>G->vexs[i]; } for(i = 0; i < G->vexnum; i++) { for(j = 0; j < G->vexnum; j++) { G->arcs[i][j].adj = INFINTY_INT_MAX;//网 G->arcs[i][j].info = NULL; } } cout<<"请输入弧的头、尾、权值"<<endl; for(k = 0; k < G->arcnum; k++) { cout<<"弧头"<<endl; cin>>va; cout<<"弧尾"<<endl; cin>>vb; cout<<"权值"<<endl; cin>>w; i = LocateVex(*G,va); j = LocateVex(*G,vb); G->arcs[i][j].adj = w; if(incInfo) { cout<<"请输入该弧的信息"<<endl; cin>>s; l = strlen(s); if(l) { pInfo = (char *)malloc(sizeof(char)*(l+1)); strcpy(pInfo,s); G->arcs[i][j].info = pInfo; } } } G->kind = DN; return true; } bool CreateAG(pMGraph G)//创建无向图 { int incInfo; int i,j,k,l; char va,vb; cout<<"请输入无向图G的顶点数,边数,边是否含其它信息(是:1,否:0):"<<endl; cin>>G->vexnum; cin>>G->arcnum; cin>>incInfo; char s[MAX_INFO]; char *info; //初始化顶点 for(i = 0; i < G->vexnum; i++) { cin>>G->vexs[i]; } //初始化邻接矩阵 for(i = 0; i < G->vexnum; i++) { for(j = 0; j < G->vexnum; j++) { G->arcs[i][j].adj = 0;//图 G->arcs[i][j].info = NULL; } } cout<<"请输入每条边的两个顶点"<<endl; for(k = 0; k < G->arcnum; k++) { cin>>va; cin>>vb; i = LocateVex(*G,va); j = LocateVex(*G,vb); G->arcs[i][j].adj = G->arcs[j][i].adj = 1; if(incInfo) { cin>>s; l = strlen(s); if(l) { info = (char *)malloc(sizeof(char)*(l+1)); strcpy(info,s); G->arcs[i][j].info = G->arcs[j][i].info = info; } } } G->kind = AG; return true; } bool CreateAN(pMGraph G) { int incInfo; int i,j,k; char va,vb; int w; char s[MAX_INFO]; char *info; cout<<"请输入无向网G的顶点数,边数,边是否含其它信息(是:1,否:0):"; cin>>G->vexnum; cin>>G->arcnum; cin>>incInfo; for(i = 0; i < G->vexnum; i++) { cin>>G->vexs[i]; } for(i = 0; i < G->vexnum; i++) { for(j = 0; j < G->vexnum; j++) { G->arcs[i][j].adj = INFINTY_INT_MAX; G->arcs[i][j].info = NULL; } } cout<<"请输入每条边的两个顶点以及权值"<<endl; for(k = 0; k < G->vexnum; k++) { cin>>va; cin>>vb; cin>>w; i = LocateVex(*G,va); j = LocateVex(*G,vb); G->arcs[i][j].adj = G->arcs[j][i].adj = w; if(incInfo) { cout<<"请输入该边的相关信息"<<endl; cin>>s; w = strlen(s); if(w) { info = (char *)malloc(sizeof(char)*(w+1)); strcpy(info,s); G->arcs[i][j].info = G->arcs[j][i].info = info; } } } G->kind = AN; return true; } bool CreateGraph(pMGraph G) { cout<<"请输入图G的类型(有向图:0,有向网:1,无向图:2,无向网:3):"; scanf("%d",&(*G).kind); switch((*G).kind) { case DG: return CreateDG(G); /* 构造有向图 */ case DN: return CreateDN(G); /* 构造有向网 */ case AG: return CreateAG(G); /* 构造无向图 */ case AN: return CreateAN(G); /* 构造无向网 */ default: return false; } } void DestroyGraph(pMGraph G) { int i,j; if(G->kind < 2)//有向tu { for(i = 0; i < G->vexnum; i++) { for(j = 0; j < G->vexnum; j++) { if(G->kind == 0 && G->arcs[i][j].adj == 1 || G->kind == 1 && G->arcs[i][j].adj != INFINTY_INT_MAX) { free(G->arcs[i][j].info); G->arcs[i][j].info = NULL; } } } }else { for(i = 0; i < G->vexnum; i++) { for(j = i+1; j < G->vexnum; j++) { if(G->kind == 2 && G->arcs[i][j].adj == 1 || G->kind == 3 && G->arcs[i][j].adj != INFINTY_INT_MAX) { free(G->arcs[i][j].info); G->arcs[i][j].info = G->arcs[j][i].info =NULL; } } } } } char GetVex(MGraph G,int v) { if(v > G.vexnum || v < 0) { exit(0); } return G.vexs[v]; } bool PutVex(pMGraph G,char v,char iValue) { int k = 0; k = LocateVex(*G,v); if( k < 0) { return false; } G->vexs[k] = iValue; return true; } int FirstAdjVex(MGraph G,char v) { int i,j = 0,k; k = LocateVex(G,v); if(G.kind == AN || G.kind == DN) { j = INFINTY_INT_MAX; } for(i = 0; i < G.vexnum; i++) { if(G.arcs[k][i].adj != j) { return i; } } return -1; } int NextAdjVex(MGraph G,char v,char w)//返回v的(相对于w的)下一个邻接顶点的序号,若w是v的最后一个邻接顶点,则返回-1 { int k1,k2; int i,j = 0; k1 = LocateVex(G,v); k2 = LocateVex(G,w); if(G.kind == AN || G.kind == DN) { j = INFINTY_INT_MAX; } for(i = k2+1; i < G.vexnum ; i++) { if(G.arcs[k1][i].adj != j) { return i; } } return -1; } void Display(MGraph G) { int i,j; cout<<"顶点:"; for(i = 0; i < G.vexnum; i++) { cout<<G.vexs[i]<<" "; } cout<<endl; cout<<"边"<<endl; for(i = 0; i < G.vexnum; i++) { for(j = 0; j < G.vexnum; j++) { cout<<G.arcs[i][j].adj<<" "; } cout<<endl; } } void InsertVex(pMGraph G,char v) { int index = G->vexnum; G->vexnum+=1; G->vexs[index] = v; for(int i = 0; i <= index; i++) { if(G->kind % 2)//网 { G->arcs[i][index].adj = G->arcs[index][i].adj = INFINTY_INT_MAX; }else { G->arcs[i][index].adj = G->arcs[index][i].adj = 0; } G->arcs[index][i].info = NULL; G->arcs[i][index].info = NULL; } } bool DeleteVex(pMGraph G,char v) { int k,m = 0; int i,j; //1.找到顶点v的序号 k = LocateVex(*G,v); if(k < 0) { return false; } if(G->kind == DN || G->kind == AN)//网 { m = INFINTY_INT_MAX; } //2.更改弧数(分有向图和无向图) for(i = 0; i < G->vexnum; i++) { if(G->arcs[i][k].adj != m) { if(G->arcs[i][k].info)//释放相关信息 { free(G->arcs[i][k].info); } G->arcnum--; } } if(G->kind == DG || G->kind == AG)//有向图 { for(i = 0; i < G->vexnum; i++) { if(G->arcs[k][i].adj != m) { if(G->arcs[k][i].info)//释放相关信息 { free(G->arcs[k][i].info); } G->arcnum--; } } } //3.更改顶点数组内容及大小 for(i = k+1; i < G->vexnum; i++) { G->vexs[i-1] = G->vexs[i]; } //4.更改邻接矩阵 for(i = 0; i < G->vexnum; i++) { for(j = k+1;j < G->vexnum; j++) { G->arcs[i][j-1] = G->arcs[i][j]; } } for(i = 0; i < G->vexnum; i++) { for(j = k+1;j < G->vexnum; j++) { G->arcs[j-1][i] = G->arcs[j][i]; } } G->vexnum--; return true; } bool InsertArc(pMGraph G,char v,char w) { int i,j,k,l; char s[MAX_INFO]; char *pinfo; //1.找到v、w的序号 i = LocateVex(*G,v); j = LocateVex(*G,w); if(i < 0 || j < 0) { return false; } //2.如果是网,需输入权值.是图则更改邻接矩阵相应值 if(G->kind == DN || G->kind == AN) { cout<<"输入权值:"; cin>>G->arcs[i][j].adj; }else { G->arcs[i][j].adj = 1; } //3.如果有相关信息,输入之 cout<<"该弧是否有相关信息(0:否 1:是):"<<endl; cin>>k; if(k) { cout<<"输入相关信息:"; cin>>s; l = strlen(s); if(l) { pinfo = (char *)malloc(sizeof(char)*(l+1)); strcpy(pinfo,s); G->arcs[i][j].info = pinfo; } } //4.如果是无向的,添加对称弧 if(G->kind == AG || G->kind == AN) { G->arcs[j][i].adj = G->arcs[i][j].adj; G->arcs[j][i].info = G->arcs[i][j].info; } G->arcnum++; return true; } bool DeleteArc(pMGraph G,char v,char w) { int i,j; //1.找到v、w的位置 i = LocateVex(*G,v); j = LocateVex(*G,w); if(i < 0 || j < 0) { return false; } //2.如果是图则将邻接矩阵对应位置的值改为0,否则改为INT_MAX if(G->kind == DG || G->kind == AG) { G->arcs[i][j].adj = 0; }else { G->arcs[i][j].adj = INFINTY_INT_MAX; } if(G->arcs[i][j].info) { free(G->arcs[i][j].info); G->arcs[i][j].info = NULL; } //3.如果是无向的,需删除对称弧 if(G->kind == AG || G->kind == AN) { G->arcs[j][i].adj = G->arcs[i][j].adj; G->arcs[j][i].info = NULL; } G->arcnum--; return true; } void DFSTravel(MGraph G,bool (*Visit)(char)) { int v; VisitFunc = Visit; for(v = 0; v < G.vexnum; v++) { visited[v] = false; } for(v = 0; v < G.vexnum; v++) { if(!visited[v]) { DFS(G,v); } } cout<<endl; } void DFS(MGraph G,int v) { char w1,v1; int w; visited[v] = true; VisitFunc(G.vexs[v]); v1 = GetVex(G,v); for(w = FirstAdjVex(G,v1);w>=0;w = NextAdjVex(G,v1,w1=GetVex(G,w))) { if(!visited[w]) { DFS(G,w); } } } void BFSTravel(MGraph G,bool (*Visit)(char)) { Queue q; InitQueue(&q); char w1,u1; int i,u,w; for(i = 0; i < G.vexnum; i++) { visited[i] = false; } for(i = 0; i < G.vexnum; i++) { if(!visited[i]) { visited[i] = true; Visit(G.vexs[i]); EnQueue(&q,i); while(!QueueEmpty(q)) { DeQueue(&q,&u); u1 = GetVex(G,u); for(w = FirstAdjVex(G,u1);w>=0;w = NextAdjVex(G,u1,w1=GetVex(G,w))) { if(!visited[w]) { visited[w] = true; Visit(G.vexs[w]); EnQueue(&q,w); } } } } } DestroyQueue(&q); cout<<endl; } int main() { MGraph G; CreateDG(&G); Display(G); cout<<"深度优先遍历"<<endl; DFSTravel(G,Visit); cout<<"广度优先遍历"<<endl; BFSTravel(G,Visit); return 0; }
图的存储形式——邻接矩阵(数组),布布扣,bubuko.com
原文:http://blog.csdn.net/chdjj/article/details/34099147