实验报告4 图的有关操作
无向网的创建、求度、深度遍历、广度遍历
1 #include <iostream> 2 #include <stdlib.h> 3 #include <stdio.h> 4 #include <string> 5 #define MAX_VERTEX_NUM 20 6 7 using namespace std; 8 //1.建立无向网的邻接表 9 10 typedef int InfoType;//权值 11 typedef char VertexType ; 12 13 typedef struct ArcNode 14 { 15 int adjvex;//该弧的弧尾 16 struct ArcNode *nextarc;//指向的下一个弧 17 InfoType *info; 18 }ArcNode; 19 typedef struct VNode 20 { 21 VertexType data;//顶点类型和数据 22 ArcNode *firstarc;//指向的第一条邻接弧 23 }VNode,AdjList[MAX_VERTEX_NUM];//表头 24 typedef struct 25 { 26 AdjList vertices;// 27 int vexnum,arcnum; 28 int kind; //DG 0 DN 1 UDG 2 UDN 3 29 }ALGraph;//adjacency list graph 邻接表 30 31 int locate(ALGraph &g,char v) 32 { 33 int i=0; 34 for (i;i<g.vexnum;i++) 35 { 36 if (g.vertices[i].data == v) 37 return i; 38 } 39 40 } 41 void createUDN(ALGraph &g) 42 { 43 cout<<"构造无向网:请输入网的顶点个数和弧的个数"<<endl; 44 cin>>g.vexnum>>g.arcnum; 45 g.kind = 3; 46 47 //构造顶点向量 48 int i,j,k; 49 //请输入每个顶点的值 50 for (i=0;i<g.vexnum;i++)//初始化 51 { 52 cin>> g.vertices[i].data; 53 g.vertices[i].firstarc = NULL;//头结点置空 54 } 55 56 //构造链表们 57 char v1,v2; 58 int w; 59 cout<<"请输入每条弧的弧头 、弧尾、权值"<<endl; 60 for(k=0;k<g.arcnum;k++) 61 { 62 cin>>v1>>v2>>w; 63 i = locate(g,v1);//弧尾 64 j = locate(g,v2);//弧头 65 ArcNode *p ; 66 p = (ArcNode *)malloc(sizeof(ArcNode));//新建一块表结点空间 67 p->adjvex = j; 68 p->info = (int *)malloc(sizeof(int));//对于网,用来存放权值 69 p->info = &w; 70 p->nextarc = g.vertices[i].firstarc;//置空 71 g.vertices[i].firstarc = p;//头插法建表 72 if (g.kind >= 2) //如果是无向图或者无向网,需要做对称 73 { 74 p = (ArcNode *)malloc(sizeof(ArcNode)); 75 p->adjvex = i; 76 p->info = (int *)malloc(sizeof(int)); 77 p->info = &w; 78 p->nextarc = g.vertices[j].firstarc ; 79 g.vertices[j].firstarc = p; 80 } 81 82 } 83 84 } 85 86 //求邻接表的入度和出度 87 int* out(ALGraph &g) 88 { 89 int *p,*q; 90 p = (int *) malloc((g.vexnum)*sizeof(int));//申请一个动态数组,存放的是每一个顶点对应的出度 91 q=p; 92 int i =0; 93 int cou =1;//计数器 94 for (i;i<g.vexnum ; i++) 95 { 96 //对每一个结点进行计算出度,循环一遍 97 ArcNode *q=g.vertices[i].firstarc;//q指向第一个结点 98 while (q->nextarc) 99 { 100 cou++; 101 q=q->nextarc; 102 } 103 *p = cou; 104 p++; 105 cou=0;//清空计数器 106 } 107 return q; 108 } 109 int * in(ALGraph &g) 110 { 111 int *p; 112 p = (int *)malloc((g.vexnum)*sizeof(int)); 113 int i=0; 114 int j=0; 115 int cou=0; 116 ArcNode *q; 117 for (i;i<g.vexnum;i++) 118 {//外层循环遍历每个结点,计算入度 119 for (j;j<g.vexnum;j++) 120 { 121 //内层循环遍历全部表元素 122 q = g.vertices[j].firstarc; 123 while (q->nextarc) 124 { 125 if (q->adjvex == i) 126 cou++; 127 } 128 129 } 130 *p=cou; 131 p++; 132 cou=0; 133 134 } 135 return p; 136 } 137 //深度优先搜索 138 bool visited[MAX_VERTEX_NUM]; 139 140 void DFSTraverse(ALGraph g) 141 { 142 void DFS(ALGraph g,int v); 143 int v; 144 //visited数组初始化 145 for (v=0;v<g.vexnum;v++) 146 visited[v]=false; 147 148 for(v=0;v<g.vexnum;v++) 149 if (!visited[v])//如果结点未被访问过 ,则深度遍历该结点 150 DFS(g,v); 151 } 152 int FirstAdjVex(ALGraph &g,int v) 153 { 154 //对于无向网来说,每个顶点必定有一个邻接点 155 return g.vertices[v].firstarc->adjvex;//返回V结点的第一个邻接结点的序号 156 } 157 int NextAdjVex(ALGraph &g,int v,int w) 158 {//必须要讨论有没有除了第一个邻接点之外的第二个邻接点 159 //注意要找 160 ArcNode *p=g.vertices[v].firstarc; 161 while (p->adjvex!=w) 162 p=p->nextarc; 163 p = p->nextarc; 164 if (!p) 165 return -1; 166 else 167 return p->adjvex;//所以我们的条件为w>=0 168 } 169 void DFS(ALGraph g,int v) 170 { 171 visited[v]=true;//置标志 172 cout<<g.vertices[v].data<<" "; 173 int w; 174 for (w = FirstAdjVex(g,v);w>=0;w=NextAdjVex(g,v,w)) 175 if (!visited[w]) 176 DFS(g,w); 177 } 178 //广度优先搜索 179 typedef int Elemtype; 180 //进队出队为序号,输出时打印char数据,这样比较方便 181 typedef struct 182 { 183 Elemtype data[MAX_VERTEX_NUM]; 184 int rear,front; 185 }SeqQueue; 186 void InitQueue(SeqQueue &q) 187 { 188 q.rear = q.front = -1; 189 } 190 void EnQueue(SeqQueue &q,Elemtype e ) 191 { 192 q.rear = (q.rear+1)%MAX_VERTEX_NUM; 193 q.data[q.rear] = e; 194 } 195 void deQueue(SeqQueue &q,Elemtype &e) 196 { 197 if (q.rear == q.front) 198 { 199 printf("empty queue"); 200 } 201 q.front = (q.front + 1)% MAX_VERTEX_NUM; 202 e = q.data[q.front]; 203 204 } 205 int QueueEmpty(SeqQueue &q) 206 { 207 return q.rear == q.front; 208 } 209 void BFSTraverse(ALGraph &g) 210 { 211 int v,u,w; 212 for (v=0;v<g.vexnum;v++) 213 visited[v]=false; 214 SeqQueue q; 215 InitQueue(q); 216 for (v=0;v<g.vexnum;v++) 217 { 218 if (!visited[v]) 219 { 220 visited[v]=true; 221 printf("%c ",g.vertices[v].data); 222 EnQueue(q,v); 223 while (!QueueEmpty(q)) 224 { 225 deQueue(q,u); 226 for ( w = FirstAdjVex(g,u);w>=0;w=NextAdjVex(g,u,w)) 227 { 228 if (!visited[w]) 229 { 230 visited[w]=true; 231 printf("%c ",g.vertices[w].data); 232 EnQueue(q,w); 233 234 } 235 } 236 237 238 239 } 240 } 241 } 242 243 244 } 245 int main() 246 { 247 ALGraph g; 248 createUDN(g); 249 //1.求无向网的度 250 cout<<"无向图的度为"<<endl; 251 int *p;p=out(g);int i=0; 252 for (p,i;i<g.vexnum;i++,p++) 253 cout<<*p<<" "; 254 cout<<endl; 255 //2.深度优先遍历 256 cout<<"深度优先遍历无向图"<<endl; 257 DFSTraverse(g); 258 //3.广度优先遍历 259 cout<<"广度优先遍历无向图"<<endl; 260 BFSTraverse(g); 261 262 return 0; 263 }
实验报告内容:
1.键盘输入数据,建立一个有向图的邻接表。
2.输出该邻接表。
*3.建立一个无向图的十字链表。
4.在有向图的邻接表的基础上计算各顶点的度,并输出。
5.以有向图的邻接表为基础实现输出它的拓扑排序序列。
*6.采用邻接矩阵存储一个有向图,输出单源点到其它顶点的最短路径。
7.采用邻接表存储实现无向图的深度优先非递归遍历。
8.采用邻接表存储实现无向图的广度优先遍历。
*9.采用邻接矩阵存储实现无向图的最小生成树的PRIM算法。
*10.判断无向图任意两个顶点间是否有路径,若有输出路径上的顶点序列。
11.在主函数中设计一个简单的菜单,分别调试上述算法。
*12.综合训练:为计算机专业设计教学计划:4个学年,每学年2个学期,开设50门课程,每学期所开课程门数尽量均衡,课程的安排必须满足先修关系。
#include <iostream> #include <stdlib.h> #include <stdio.h> #include <string> #define INFINITY INT_MAX #define MAX_VERTEX_NUM 20 using namespace std; //1.定义有向网的邻接表结构 typedef int InfoType;//权值 typedef char VertexType ; typedef struct ArcNode { int adjvex;//该弧的弧尾 struct ArcNode *nextarc;//指向的下一个弧 InfoType info; }ArcNode; typedef struct VNode { VertexType data;//顶点类型和数据 ArcNode *firstarc;//指向的第一条邻接弧 }VNode,AdjList[MAX_VERTEX_NUM];//表头 typedef struct { AdjList vertices; int vexnum,arcnum; int kind; //DG 0 DN 1 UDG 2 UDN 3 kind =1 }ALGraph;//adjacency list graph 邻接表 //一个桟 typedef int Elemtype; typedef struct { VertexType data[MAX_VERTEX_NUM]; int top; }SeqStack; void InitStack(SeqStack &s) { s.top=-1; } int isEmpty(SeqStack &s) { return s.top==-1; } void push(SeqStack &s,Elemtype e) { if (s.top == MAX_VERTEX_NUM) printf("full stack!"); s.top++; s.data[s.top]=e; } void pop(SeqStack &s,Elemtype &e) { if (isEmpty(s)) printf("empty stack !"); e = s.data[s.top--]; } int getTop(SeqStack &s) { return s.data[s.top]; } //2.创建有向网 //定位函数 int locate(ALGraph &g,char v) { int i=0; for (i;i<g.vexnum;i++) { if (g.vertices[i].data == v) return i; } } void createDN(ALGraph &g) { cout<<"构造有向网:请输入网的顶点个数和弧的个数"<<endl; cin>>g.vexnum>>g.arcnum; g.kind = 1; //构造顶点向量 int i,j,k; cout<<"请输入每个顶点的值"<<endl; for (i=0;i<g.vexnum;i++)//初始化 { cin>> g.vertices[i].data; g.vertices[i].firstarc = NULL;//头结点置空 } //构造链表们 char v1,v2; int w; cout<<"请输入每条弧的弧头 、弧尾、权值"<<endl; for(k=0;k<g.arcnum;k++) { cin>>v1>>v2>>w; i = locate(g,v1);//弧尾 j = locate(g,v2);//弧头 ArcNode *p ; p = (ArcNode *)malloc(sizeof(ArcNode));//新建一块表结点空间 p->adjvex = j; // InfoType *info; // p->info = (int *)malloc(sizeof(int));//对于网,用来存放权值 // p->info = &w; p->info = w; p->nextarc = g.vertices[i].firstarc;//置空 g.vertices[i].firstarc = p;//头插法建表 } } // 创建无向网 void createUDN(ALGraph &g) { cout<<"构造无向网:请输入网的顶点个数和弧的个数"<<endl; cin>>g.vexnum>>g.arcnum; g.kind = 3; //构造顶点向量 int i,j,k; //请输入每个顶点的值 for (i=0;i<g.vexnum;i++)//初始化 { cin>> g.vertices[i].data; g.vertices[i].firstarc = NULL;//头结点置空 } //构造链表们 char v1,v2; int w; cout<<"请输入每条弧的弧头 、弧尾、权值"<<endl; for(k=0;k<g.arcnum;k++) { cin>>v1>>v2>>w; i = locate(g,v1);//弧尾 j = locate(g,v2);//弧头 ArcNode *p ; p = (ArcNode *)malloc(sizeof(ArcNode));//新建一块表结点空间 p->adjvex = j; p->info = w; p->nextarc = g.vertices[i].firstarc;//置空 g.vertices[i].firstarc = p;//头插法建表 if (g.kind >= 2) //如果是无向图或者无向网,需要做对称 { p = (ArcNode *)malloc(sizeof(ArcNode)); p->adjvex = i; p->info = w; p->nextarc = g.vertices[j].firstarc ; g.vertices[j].firstarc = p; } } } //3.输出邻接表 void printALGraph(ALGraph &g) { int i=0; ArcNode *p; for (i;i< g.vexnum ;i++) { printf("弧头:%c ",g.vertices[i].data); p=g.vertices[i].firstarc;//P指向链表的第一个结点 while (p) { printf("(弧尾:%d,权值:%d) ",p->adjvex,p->info); p=p->nextarc; } cout<<endl; } } // 4.有向网的十字链表 typedef struct ArcBox { int tailvex,headvex; struct ArcBox *hlink,*tlink; InfoType info; }ArcBox; typedef struct VexNode { VertexType data; ArcBox *firstin,*firstout; }VexNode; typedef struct { VexNode xlist[MAX_VERTEX_NUM];//表头向量 int vexnum,arcnum; }OLGraph; int locate(OLGraph &g,char v) { int i=0; for (i;i<g.vexnum;i++) { if (g.xlist[i].data == v) { return i; } } } void createOLDN(OLGraph &g) { cout <<"请输入有向网的顶点个数、弧的个数"<<endl; cin>>g.vexnum>>g.arcnum; int i,j,k; cout<<"请输入顶点值"<<endl; for (i=0;i<g.vexnum;i++) { cin>>g.xlist[i].data; g.xlist[i].firstin=g.xlist[i].firstout=NULL; } cout<<"请输入每条弧的弧头和弧尾和权值"<<endl; char v1,v2;int w; ArcBox *p; fflush(stdin); for (k=0;k<g.arcnum;k++) { cin>>v1>>v2>>w; i=locate(g,v1); j=locate(g,v2); p=(ArcBox *)malloc(sizeof(ArcBox)); //对弧结点赋值 p->headvex = j;//弧的弧头 p->tailvex = i;//弧的弧尾 逆邻接表 p->hlink = g.xlist[j].firstin;//弧头相同的结点 逆邻接表 p->tlink = g.xlist[i].firstout;//弧尾相同的结点 p->info = w; g.xlist[j].firstin = g.xlist[i].firstout = p; } } //输出有向网的十字链表,分为邻接表和逆邻接表 void printOLGraph(OLGraph &g) { cout<<"输出邻接表"<<endl; int i=0; ArcBox *p; for (i;i< g.vexnum ;i++) { printf("弧头:%c ",g.xlist[i].data); p=g.xlist[i].firstout;//P指向链表的第一个结点 while (p) { printf("(弧尾:%d,权值:%d) ",p->headvex,p->info); p=p->tlink; } cout<<endl; } cout<<"输出逆邻接表"<<endl; for (i=0;i< g.vexnum ;i++) { printf("弧头:%c ",g.xlist[i].data); p=g.xlist[i].firstin;//P指向链表的第一个结点 while (p) { printf("(弧尾:%d,权值:%d) ",p->tailvex,p->info); p=p->hlink; } cout<<endl; } } //5.无向图的十字链表 void createOLUDG(OLGraph &g) { cout <<"请输入有向网的顶点个数、弧的个数"<<endl; cin>>g.vexnum>>g.arcnum; int i,j,k; cout<<"请输入顶点值"<<endl; for (i=0;i<g.vexnum;i++) { cin>>g.xlist[i].data; g.xlist[i].firstin=g.xlist[i].firstout=NULL; } cout<<"请输入每条弧的弧头和弧尾"<<endl; char v1,v2; ArcBox *p; fflush(stdin); for (k=0;k<g.arcnum;k++) { cin>>v1>>v2; i=locate(g,v1); j=locate(g,v2); p=(ArcBox *)malloc(sizeof(ArcBox)); //对弧结点赋值 p->headvex = j;//弧的弧头 p->tailvex = i;//弧的弧尾 逆邻接表 p->hlink = g.xlist[j].firstin;//弧头相同的结点 逆邻接表 p->tlink = g.xlist[i].firstout;//弧尾相同的结点 g.xlist[j].firstin = g.xlist[i].firstout = p; //无向图做对称 p=(ArcBox *)malloc(sizeof(ArcBox)); //对弧结点赋值 p->headvex = i;//弧的弧头 p->tailvex = j;//弧的弧尾 逆邻接表 p->hlink = g.xlist[i].firstin;//弧头相同的结点 逆邻接表 p->tlink = g.xlist[j].firstout;//弧尾相同的结点 g.xlist[i].firstin = g.xlist[j].firstout = p; } } //输出无向图 void printOLGraph2(OLGraph &g) { cout<<"输出邻接表"<<endl; int i=0; ArcBox *p; for (i=0;i< g.vexnum ;i++) { printf("弧头:%c->",g.xlist[i].data); p=g.xlist[i].firstout;//P指向链表的第一个结点 while (p) { printf("%d->",p->headvex); p=p->tlink; } cout<<"NULL"<<endl; } cout<<"输出逆邻接表"<<endl; for (i=0;i< g.vexnum ;i++) { printf("弧头:%c->",g.xlist[i].data); p=g.xlist[i].firstin;//P指向链表的第一个结点 while (p) { printf("%d->",p->tailvex); p=p->hlink; } cout<<"NULL"<<endl; } } //6.求邻接表的入度和出度 int* out(ALGraph &g) { int *p,*q; p = (int *) malloc((g.vexnum)*sizeof(int));//申请一个动态数组,存放的是每一个顶点对应的出度 q=p; int i =0; int cou =0;//计数器 for (i=0;i<g.vexnum ; i++) { //对每一个结点进行计算出度,循环一遍 ArcNode *q=g.vertices[i].firstarc;//q指向第一个结点 while (q) { cou++; q=q->nextarc; } *p = cou; p++; cou=0;//清空计数器 } return q; } int * in(ALGraph &g) { int *p; p = (int *)malloc((g.vexnum)*sizeof(int)); int i=0; int j=0; int cou=0; ArcNode *q; for (i=0;i<g.vexnum;i++) {//外层循环遍历每个结点,计算入度 for (j=0;j<g.vexnum;j++) { //内层循环遍历全部表元素 q = g.vertices[j].firstarc; while (q) { if (q->adjvex == i) cou++; q=q->nextarc; } } p[i]=cou; cou=0; } return p; } int *InAndOut(ALGraph &g) { int *p=in(g); int *q=out(g); int *k; k=(int *)malloc((g.vexnum)*sizeof(int)); for (int i=0;i<g.vexnum;i++) { k[i]=p[i]+q[i]; } return k; } //7.深度优先搜索 bool visited[MAX_VERTEX_NUM]; void DFSTraverse(ALGraph g) { void DFS(ALGraph g,int v); int v; //visited数组初始化 for (v=0;v<g.vexnum;v++) visited[v]=false; for(v=0;v<g.vexnum;v++) if (!visited[v])//如果结点未被访问过 ,则深度遍历该结点 DFS(g,v); } int FirstAdjVex(ALGraph &g,int v) { //对于无向网来说,每个顶点必定有一个邻接点 return g.vertices[v].firstarc->adjvex;//返回V结点的第一个邻接结点的序号 } int NextAdjVex(ALGraph &g,int v,int w) {//必须要讨论有没有除了第一个邻接点之外的第二个邻接点 //注意要找 ArcNode *p=g.vertices[v].firstarc; while (p->adjvex!=w) p=p->nextarc; p = p->nextarc; if (!p) return -1; else return p->adjvex;//所以我们的条件为w>=0 } void DFS(ALGraph g,int v) { visited[v]=true;//置标志 cout<<g.vertices[v].data<<" "; int w; for (w = FirstAdjVex(g,v);w>=0;w=NextAdjVex(g,v,w)) if (!visited[w]) DFS(g,w); } // 非递归 /* 1.栈初始化 2.输出起始顶点;起始顶点改为“已访问”标记;将起始顶点进桟 3.重复直到桟空 3.1 取栈顶元素(不出桟) 3.2 栈顶元素顶点存在未被访问过的邻接点W,则 3.2.1 输出顶点W 3.2.2 将顶点W改为已访问标志 3.2.3 将顶点W进桟 3.3 否则,当前顶点退桟 */ int hasNextAdjVex(ALGraph &g,int h) { //找到H的未被访问过的邻接点 ArcNode *p=g.vertices[h].firstarc; if (!p) return -1; while (visited[p->adjvex]) { p=p->nextarc; } return p->adjvex; } void DFS_2(ALGraph &g,int v) { SeqStack s; InitStack(s); printf("%c",g.vertices[v].data); visited[v]=true; push(s,v); int h,w,e; while (!isEmpty(s)) { h=getTop(s); w=hasNextAdjVex(g,h); if (w>=0) { printf("%c",g.vertices[w].data); visited[w]=true; push(s,w); } else pop(s,e); } } void DFSTraverse_2(ALGraph g) { int v; //visited数组初始化 for (v=0;v<g.vexnum;v++) visited[v]=false; for(v=0;v<g.vexnum;v++) if (!visited[v])//如果结点未被访问过 ,则深度遍历该结点 DFS_2(g,v); } //8.广度优先搜索 typedef int Elemtype; //进队出队为序号,输出时打印char数据,这样比较方便 typedef struct { Elemtype data[MAX_VERTEX_NUM]; int rear,front; }SeqQueue; void InitQueue(SeqQueue &q) { q.rear = q.front = -1; } void EnQueue(SeqQueue &q,Elemtype e ) { q.rear = (q.rear+1)%MAX_VERTEX_NUM; q.data[q.rear] = e; } void deQueue(SeqQueue &q,Elemtype &e) { if (q.rear == q.front) { printf("empty queue"); } q.front = (q.front + 1)% MAX_VERTEX_NUM; e = q.data[q.front]; } int QueueEmpty(SeqQueue &q) { return q.rear == q.front; } void BFSTraverse(ALGraph &g) { int v,u,w; for (v=0;v<g.vexnum;v++) visited[v]=false; SeqQueue q; InitQueue(q); for (v=0;v<g.vexnum;v++) { if (!visited[v]) { visited[v]=true; printf("%c ",g.vertices[v].data); EnQueue(q,v); while (!QueueEmpty(q)) { deQueue(q,u); for ( w = FirstAdjVex(g,u);w>=0;w=NextAdjVex(g,u,w)) { if (!visited[w]) { visited[w]=true; printf("%c ",g.vertices[w].data); EnQueue(q,w); } } } } } } //9.拓扑排序 // 建立辅助数组indegree 存放每个顶点的入度 void FindInDegree(ALGraph &g,int in[]) { int i=0,j=0; ArcNode *p; int count=0; for (i;i<g.vexnum;i++) { for (j=0;j<g.vexnum;j++) { p=g.vertices[j].firstarc; while (p) { if (p->adjvex == i) count++; p=p->nextarc; } } in[i] = count; cout<<count<<' ' ; count = 0; } } //这里需要一个栈 //拓扑排序算法 void TopologicalSort(ALGraph g) { int indegree[g.vexnum];//定义一个入度的辅助数组 int i,k; for (i=0;i<g.vexnum;i++) indegree[i]=0; FindInDegree(g,indegree); SeqStack s; InitStack(s); //如果入度为零则进栈 for (i=0;i<g.vexnum;i++) { if (!indegree[i]) push(s,i);//序号进栈 } int count = 0;//对输出顶点个数进行计数 ArcNode *p; while (!isEmpty(s)) { pop(s,i); printf("%d:%c ",i,g.vertices[i].data); count++; for (p=g.vertices[i].firstarc;p;p=p->nextarc) { k=p->adjvex; if (!(--indegree[k])) push(s,k); } } if (count < g.vexnum) printf("该有向图有回路 "); else printf("该有向图无回路 "); } //10. PRIM 算法 //prim algorithm //邻接矩阵 typedef int VRType; typedef int VertexType2; typedef int InfoType; typedef struct ArcCell { VRType adj; InfoType info; }ArcCell,AdjMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM]; typedef struct { VertexType2 vex[MAX_VERTEX_NUM];//顶点向量 AdjMatrix arcs;//邻接矩阵 int vexnum,arcnum; int kind; }MGraph; int locate(MGraph &g,int v) { int i; for (i=0;i<g.vexnum;i++) { if (g.vex[i] == v) return i; } } //邻接数组创建无向图 void createUDG(MGraph &g) { cout<<"请输入无向图的顶点个数和边的个数"<<endl; cin>>g.vexnum>>g.arcnum; int i,j,k; //初始化顶点向量 for (i=0;i<g.vexnum;i++) cin>>g.vex[i]; //初始化邻接矩阵 for (i=0;i<g.vexnum;i++) for (j=0;j<g.vexnum;j++) g.arcs[i][j].adj = INFINITY; cout<<"请输入每条边的顶点和权值"<<endl; for (k=0;k<g.arcnum;k++) { int v1,v2; int w; cin>>v1>>v2>>w; i=locate(g,v1); j=locate(g,v2); g.arcs[i][j].adj=w; g.arcs[j][i].adj=g.arcs[i][j].adj;//无向图为对称的! } } typedef struct node { VertexType2 adjvex;//权最小的顶点 VRType lowcost;//最小的权 }closedge[MAX_VERTEX_NUM]; int mininum(closedge close,int n) { int i=0; int min = 999; int k; for (i=1;i<n;i++) { if (close[i].lowcost < min && close[i].lowcost !=0) { min = close[i].lowcost; k = i; } } return k; //k记录最小权值顶点的序号 } //最小生成树——PRIM算法 void MinispanTree_PRIM(MGraph g,VertexType2 u) { closedge close; int k=locate(g,u); int i,j; //辅助数组初始化 for (j=0;j<g.vexnum;j++) if (j!=k) { close[j].adjvex=u; close[j].lowcost = g.arcs[k][j].adj; } close[k].lowcost = 0; for (i=1;i<g.vexnum;i++) { k = mininum(close,g.vexnum); cout<<"("<<close[k].adjvex<<","<<g.vex[k]<<")";//输出这条边的两个顶点 close[k].lowcost = 0; for (j=0;j<g.vexnum;j++) { if (g.arcs[k][j].adj < close[j].lowcost) { close[j].adjvex = g.vex[k]; close[j].lowcost = g.arcs[k][j].adj; } } } } int main() { cout << "------------------------------------"<<endl; cout << "1.createDN():建立一个有向网的邻接表 "<<endl; cout << "2.printALGraph():输出邻接表"<<endl; cout << "3.createOLDN():创建有向网十字链表并输出其邻接表和逆邻接表"<<endl; cout << "4.createOLUDG():创建无向图十字链表并输出其邻接表和逆邻接表"<<endl; cout << "5.in():求有向图/网的出度"<<endl; cout << "6.out():求有向图/网的入度"<<endl; cout << "7.InAndOut():求有向图的度"<<endl; cout << "8.DFSTraverse():无向图的深度优先遍历"<<endl; cout << "9.BFSTraverse():无向图的广度优先遍历"<<endl; cout << "10.TopologicalSort():以有向图的邻接表为基础实现输出它的拓扑排序序列。"<<endl; cout << "11.MinispanTree_PRIM():采用邻接矩阵存储实现无向图的最小生成树的PRIM算法"<<endl; cout << "12.DFS_2():非递归实现深度优先搜索"<<endl; cout << "------------------------------------"<<endl; LL1: cout<< "请输入您要选择的函数序号:)"<<endl; int num,i;cin>>num;int *p; switch(num) { case 1: ALGraph g; createDN(g); cout<<"创建一个有向网的邻接表成功!"<<endl; break; case 2: createDN(g); printALGraph(g); break; case 3: OLGraph g1; createOLDN(g1); printOLGraph(g1); break; case 4: createOLUDG(g1); printOLGraph2(g1); break; case 5: createDN(g); p=in(g); for (i=0;i<g.vexnum;i++,p++) cout<<g.vertices[i].data<<":"<<*p<<" "; cout<<endl; break; case 6: createDN(g); p=out(g); for (i=0;i<g.vexnum;i++,p++) cout<<g.vertices[i].data<<":"<<*p<<" "; cout<<endl; break; case 7: createDN(g); p=InAndOut(g); for (i=0;i<g.vexnum;i++) cout<<g.vertices[i].data<<":"<<(p[i])<<" "; cout<<endl; break; case 8: createUDN(g); DFSTraverse(g); break; case 9: createUDN(g); BFSTraverse(g); break; case 10: createDN(g); TopologicalSort(g); break; case 11: MGraph gg; createUDG(gg); MinispanTree_PRIM(gg,0); break; case 12: createUDN(g); DFSTraverse_2(g); } fflush(stdin); char c; cout <<"您是否要继续测试函数?y/n"<<endl; cin >> c; if (c == 'y') goto LL1; else return 0; }
第6,10题在此单独测试:
1 #include <iostream> 2 #define MAX_VERTEX_NUM 20 3 #define INFINITY INT_MAX 4 using namespace std; 5 //判断无向图任意两个顶点间是否有路径,若有输出路径上的顶点序列。 6 //floid 算法 7 //邻接矩阵 8 9 typedef char VertexType; 10 typedef int VRType; 11 typedef int InfoType; 12 typedef struct ArcCell 13 { 14 VRType adj; 15 InfoType *info; 16 }ArcCell,ArcMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM]; 17 18 typedef struct 19 { 20 int kind ; 21 int vexnum,arcnum; 22 VertexType vexs[MAX_VERTEX_NUM]; 23 ArcMatrix arcs; 24 }MGraph; 25 26 int locate(MGraph &g,VertexType v) 27 { 28 int i; 29 for (i=0;i<g.vexnum;i++) 30 { 31 if (g.vexs[i] == v) 32 return i; 33 } 34 } 35 void createUDN(MGraph &g) 36 { 37 cout <<"请输入顶点个数和弧的条数"<<endl; 38 cin >> g.vexnum>>g.arcnum; 39 int i,j,k; 40 cout <<"请输入顶点集合"<<endl; 41 for (i=0;i<g.vexnum;i++) 42 { 43 cin >>g.vexs[i]; 44 for (j=0;j<g.vexnum;j++) 45 { 46 if (i!=j) 47 g.arcs[i][j].adj=INFINITY; 48 else 49 g.arcs[i][j].adj=0; 50 } 51 52 } 53 54 55 cout <<"请输入各条弧的弧头、弧尾以及权值"<<endl; 56 char v1,v2; 57 int w; 58 for (k=0;k<g.arcnum;k++) 59 { 60 cin >>v1>>v2>>w; 61 i=locate(g,v1); 62 j=locate(g,v2); 63 g.arcs[i][j].adj=w; 64 //无向网做对称 65 g.arcs[j][i].adj=w; 66 67 } 68 } 69 void printAdjMatrix(MGraph &g) 70 { 71 int i,j; 72 for (i=0;i<g.vexnum;i++) 73 { 74 for (j=0;j<g.vexnum;j++) 75 cout <<g.arcs[i][j].adj<<" "; 76 cout <<endl; 77 } 78 79 } 80 typedef bool PathMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM][MAX_VERTEX_NUM]; 81 typedef int distanceMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM]; 82 83 void ShortestPath_FLOYD(MGraph &g,PathMatrix &p,distanceMatrix &d) 84 { 85 void printD(MGraph g,distanceMatrix &d); 86 int v,w,u,i; 87 for (v=0;v<g.vexnum;v++) 88 for (w=0;w<g.vexnum;w++) 89 { 90 d[v][w]=g.arcs[v][w].adj; 91 for (u=0;u<g.vexnum;u++) 92 { 93 p[v][w][u]=false; 94 } 95 if (d[v][w] < INFINITY ) 96 { 97 p[v][w][v]=true; 98 p[v][w][w]=true; 99 } 100 } 101 102 for (u=0;u<g.vexnum;u++) 103 for (v=0;v<g.vexnum;v++) 104 for (w=0;w<g.vexnum;w++) 105 { 106 if (d[v][u]!=INFINITY && d[u][w]!=INFINITY ) 107 if (d[v][u] + d[u][w] < d[v][w]) 108 { 109 d[v][w] = d[v][u]+d[u][w]; 110 for (i=0;i<g.vexnum ;i++) 111 p[v][w][i]=p[v][u][i] || p[u][w][i]; 112 113 } 114 115 } 116 117 } 118 void printD(MGraph g,distanceMatrix &d) 119 { 120 int i,j; 121 for(i=0;i<g.vexnum;i++) 122 { 123 for (j=0;j<g.vexnum;j++) 124 { 125 cout << d[i][j]<<" "; 126 } 127 cout <<endl; 128 } 129 130 } 131 132 void printShortestPath_FLOIY(MGraph g,PathMatrix &p,distanceMatrix &d) 133 { 134 int i,j,k; 135 for (i=0;i<g.vexnum;i++) 136 { 137 for (j=0;j<=i;j++) // 输出一半即可 138 { 139 cout <<"顶点对: <"<<g.vexs[i]<<","<<g.vexs[j]<<"> ("; 140 for (k=0;k<g.vexnum;k++) 141 { 142 if (p[i][j][k]) 143 cout <<g.vexs[k]<<" "; 144 } 145 cout <<" )"<<" 路径长度:"<<d[i][j]<<endl; 146 } 147 } 148 } 149 int main() 150 { 151 MGraph g; 152 createUDN(g); 153 PathMatrix p; 154 distanceMatrix d; 155 ShortestPath_FLOYD(g,p,d); 156 cout << " 输出每对顶点的最短路径"<<endl; 157 printShortestPath_FLOIY(g,p,d); 158 159 160 161 return 0; 162 } 163 #include <iostream> 164 #define MAX_VERTEX_NUM 20 165 #define INFINITY INT_MAX 166 using namespace std; 167 //采用邻接矩阵存储一个有向图,输出单源点到其它顶点的最短路径。 168 //迪杰特斯拉 169 170 typedef char VertexType; 171 typedef int VRType; 172 typedef int InfoType; 173 typedef struct ArcCell 174 { 175 VRType adj; 176 InfoType *info; 177 }ArcCell,ArcMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM]; 178 179 typedef struct 180 { 181 int kind ; 182 int vexnum,arcnum; 183 VertexType vexs[MAX_VERTEX_NUM]; 184 ArcMatrix arcs; 185 }MGraph; 186 187 int locate(MGraph &g,VertexType v) 188 { 189 int i; 190 for (i=0;i<g.vexnum;i++) 191 { 192 if (g.vexs[i] == v) 193 return i; 194 } 195 } 196 void createDN(MGraph &g) 197 { 198 cout <<"请输入顶点个数和弧的条数"<<endl; 199 cin >> g.vexnum>>g.arcnum; 200 int i,j,k; 201 cout <<"请输入顶点集合"<<endl; 202 for (i=0;i<g.vexnum;i++) 203 { 204 cin >>g.vexs[i]; 205 for (j=0;j<g.vexnum;j++) 206 g.arcs[i][j].adj=INFINITY; 207 } 208 209 210 cout <<"请输入各条弧的弧头、弧尾以及权值"<<endl; 211 char v1,v2; 212 int w; 213 for (k=0;k<g.arcnum;k++) 214 { 215 cin >>v1>>v2>>w; 216 i=locate(g,v1); 217 j=locate(g,v2); 218 g.arcs[i][j].adj=w; 219 220 } 221 } 222 223 void printAdjMatrix(MGraph &g) 224 { 225 int i,j; 226 for (i=0;i<g.vexnum;i++) 227 { 228 for (j=0;j<g.vexnum;j++) 229 cout <<g.arcs[i][j].adj<<" "; 230 cout <<endl; 231 } 232 233 } 234 235 typedef int ShortPathTable[MAX_VERTEX_NUM]; 236 typedef bool PathMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM]; 237 238 void shortestPath_DIJ(MGraph &g,int v0,PathMatrix &p,ShortPathTable &d) 239 { 240 // final d p 241 bool final[g.vexnum]; 242 int v,w,i,j; 243 for (v=0;v<g.vexnum;v++) 244 { 245 final[v]=false; 246 d[v]=g.arcs[v0][v].adj; 247 for (w=0;w<g.vexnum;w++) 248 p[v][w]=false; 249 250 if (d[v] < INFINITY) 251 { 252 p[v][v0]=true; 253 p[v][v]=true; 254 } 255 } 256 257 d[v0]=0;//自己到自己 258 final[v0]=true;//并到S集合中 259 int min; 260 for (i=0;i<g.vexnum;i++) 261 { 262 min = INFINITY; 263 for (w=0;w<g.vexnum;w++) 264 { 265 if (!final[w]) 266 if (d[w]<min) 267 { 268 v=w; 269 min=d[w]; 270 } 271 } 272 final[v]=true; 273 for (w=0;w<g.vexnum;w++) 274 { 275 //对于每个顶点,在介入离V0最近的点之后是否会离v0更近呢? 276 if (!final[w]&&(min+g.arcs[v][w].adj<d[w])) 277 { 278 d[w]=min+g.arcs[v][w].adj; 279 //p[w]=p[v]; 280 for (j=0;j<g.vexnum;j++) 281 p[w][j]=p[v][j]; 282 p[w][w]=true; 283 } 284 } 285 } 286 } 287 void printP(PathMatrix &p) 288 { 289 int i,j; 290 for (i=0;i<6;i++) 291 { 292 for (j=0;j<6;j++) 293 cout << p[i][j]<<" "; 294 cout <<endl; 295 } 296 297 } 298 void printD(ShortPathTable &d) 299 { 300 int i; 301 for (i=0;i<6;i++) 302 cout<<d[i]<<" "; 303 cout<<endl; 304 } 305 void printShortestPath(MGraph &g,PathMatrix &p,ShortPathTable &d) 306 { 307 int i,j; 308 for (i=1;i<g.vexnum;i++) 309 { 310 cout <<g.vexs[i]<<":"; 311 cout <<" 最短路径:("; 312 for (j=0;j<g.vexnum;j++) 313 if (p[i][j]) 314 cout <<g.vexs[j]<<" "; 315 cout <<") 路径长度:"<<d[i]<<endl; 316 } 317 } 318 int main() 319 { 320 MGraph g; 321 createDN(g); 322 printAdjMatrix(g); 323 PathMatrix p; 324 ShortPathTable d; 325 shortestPath_DIJ(g,0,p,d); 326 // v0 = 0 为单源点 327 printP(p); 328 printD(d); 329 printShortestPath(g,p,d); 330 return 0; 331 }