alGraph.h
1 #ifndef ALGRAPH_H 2 #define ALGRAPH_H 3 4 #include <stdio.h> 5 #include <stdlib.h> 6 #include <malloc.h> 7 #include <queue> 8 9 #define MAX_VERTEX_NUM 20 10 11 typedef char InfoType; 12 typedef int VertexType; 13 14 typedef enum{ERROR,OK} Status; 15 16 //---图的邻接表存储,本程序中为使用此存储方式 17 typedef struct ArcNode//弧节点 18 { 19 int adjvex; 20 InfoType *info; 21 struct ArcNode *nextarc; 22 }ArcNode; 23 24 typedef struct VNode//顶点节点 25 { 26 VertexType data;//顶点信息 27 ArcNode *firstAdj;//指向第一条依附该顶点的弧的指针 28 }VNode,AdjList[MAX_VERTEX_NUM]; 29 30 typedef struct 31 { 32 AdjList vertices; 33 int vexnum,arcnum; 34 int kind; 35 }ALGraph; 36 37 //---图的十字链表存储,本程序中使用的此存储方式 38 typedef struct ArcBox 39 { 40 int tailvex,headvex; 41 struct ArcBox *hlink,*tlink; 42 InfoType *info; 43 }ArcBox; 44 45 typedef struct VexNode 46 { 47 VertexType data; 48 ArcBox *firstin,*firstout; 49 }VexNode; 50 51 typedef struct 52 { 53 VexNode xlist[MAX_VERTEX_NUM]; 54 int vexnum,arcnum; 55 }OLGraph; 56 57 Status (*VisitFun)(VexNode ar);//遍历树时使用的函数 58 int visited[MAX_VERTEX_NUM];//访问数组,用来标志是否被访问过 59 60 int Locate(OLGraph g,int x)//根据值获取数组下标 61 { 62 for(int i = 0;i < g.arcnum;i++) 63 { 64 if(x == g.xlist[i].data) 65 { 66 return i; 67 } 68 } 69 return -1; 70 } 71 72 Status CreateOLGraph(OLGraph &g)//用户输入值,转化为位置存储,输出时再将位置转化为值输出给用户,即相当于在内部存取都是位置,从0开始,但在与用户交互时都是使用值而非位置 73 { 74 int incinfo; 75 scanf("%d %d %d",&g.vexnum,&g.arcnum,&incinfo);//incinfo如果为0则边的info为空,incinfo为1则需要输入info 76 77 printf("please input the value of vex :\n"); 78 for(int i = 0;i < g.vexnum;i++)//输入节点的值 79 { 80 scanf("%d",&g.xlist[i].data); 81 g.xlist[i].firstin = NULL; 82 g.xlist[i].firstout = NULL; 83 } 84 85 printf("please input the value of arc:\n"); 86 for(int i = 0;i < g.arcnum;i++) 87 { 88 int k,j;//k1和j1是节点的值,需要通过locate函数得到其在xlist中的位置(即数组下标) 89 scanf("%d %d",&j,&k); 90 91 j = Locate(g,j); 92 if(j == -1) 93 { 94 printf("cannot locate the vertex!\n"); 95 return ERROR; 96 } 97 98 k = Locate(g,k); 99 if(k == -1) 100 { 101 printf("cannot locate the vertex!\n"); 102 return ERROR; 103 } 104 105 ArcBox *ar = (ArcBox *)malloc(sizeof(ArcBox)); 106 //这里类似于链表的头插法建立链表,所以越是往后输入的边的端点越是在链表的表头,因此在后面遍历时,会感觉和输入的边的顺序相反,相反才说明正确 107 ar->hlink = g.xlist[k].firstin; 108 ar->tlink = g.xlist[j].firstout; 109 ar->headvex = k; 110 ar->tailvex = j; 111 g.xlist[j].firstout = ar; 112 g.xlist[k].firstin = ar; 113 114 if(incinfo) 115 { 116 char aa; 117 scanf("%c",&aa); 118 ar->info = &aa; 119 } 120 else 121 { 122 ar->info = ""; 123 } 124 } 125 return OK; 126 } 127 128 Status PrintOLGraph(OLGraph g) 129 { 130 printf("the value of the vertex and arcvalue is :\n");//输出的值和内部存储的值不一定相同,内部存储全是存储位置,因此要转化为值输出 131 for(int i = 0;i < g.vexnum;i++) 132 { 133 printf("%d\n",g.xlist[i].data); 134 ArcBox *temp = g.xlist[i].firstout; 135 while(temp) 136 { 137 printf("(%d %d) ",g.xlist[temp->tailvex].data,g.xlist[temp->headvex].data); 138 temp = temp->tlink; 139 } 140 printf("\n"); 141 } 142 return OK; 143 } 144 145 int FirstAdjVex(OLGraph g,int v) 146 { 147 if(g.xlist[v].firstout) 148 { 149 int nu = g.xlist[v].firstout->headvex; 150 if(visited[nu] == 0) 151 { 152 return nu; 153 } 154 } 155 else 156 { 157 return -1; 158 } 159 } 160 161 int NextAdjVex(OLGraph g,int v,int w) 162 { 163 ArcBox *temp = g.xlist[v].firstout; 164 while(temp->headvex != w) 165 { 166 temp = temp->tlink; 167 } 168 169 temp = temp->tlink; 170 if(temp && visited[temp->headvex] == 0) 171 { 172 return temp->headvex; 173 } 174 else 175 { 176 return -1; 177 } 178 } 179 180 Status visit(VexNode ar) 181 { 182 printf("%d\n",ar.data); 183 return OK; 184 } 185 186 void Dfs(OLGraph g,int num) 187 { 188 if(!visited[num]) 189 { 190 VisitFun(g.xlist[num]); 191 visited[num] = 1; 192 } 193 for(int m = FirstAdjVex(g,num);m >= 0;m = NextAdjVex(g,num,m)) 194 { 195 if(!visited[m]) 196 { 197 Dfs(g,m); 198 } 199 } 200 } 201 202 void DFSTraverse(OLGraph g,Status (*visit)(VexNode ar))//深度遍历树 203 { 204 for(int i = 0;i < g.vexnum;i++) 205 { 206 visited[i] = 0;//初始化访问数组 207 } 208 209 VisitFun = visit;//初始化全局变量函数指针,使得Dfs函数中也可以调用访问函数 210 for(int i = 0;i < g.vexnum;i++) 211 { 212 if(!visited[i]) 213 { 214 Dfs(g,i); 215 } 216 } 217 } 218 219 void BFSTraverse(OLGraph g,Status (*visit)(VexNode ar))//广度优先遍历树 220 { 221 for(int i = 0;i < g.vexnum;i++) 222 { 223 visited[i] = 0; 224 } 225 226 std::queue<int> q;//辅助队列,用来存放xlist数组节点的下标而不是节点本身,存放下标方便些 227 228 for(int i = 0;i < g.vexnum;i++) 229 { 230 if(!visited[i]) 231 { 232 visit(g.xlist[i]); 233 q.push(i); 234 visited[i] = 1; 235 int temp; 236 237 while(!q.empty()) 238 { 239 temp = q.front(); 240 q.pop(); 241 for(int w = FirstAdjVex(g,temp);w >= 0;w = NextAdjVex(g,temp,w)) 242 { 243 if(visited[w] == 0) 244 { 245 visited[w] = 1; 246 visit(g.xlist[w]); 247 q.push(w); 248 } 249 } 250 } 251 } 252 } 253 } 254 255 #endif
main.cpp
1 #include "alGraph.h" 2 3 int main() 4 { 5 OLGraph g; 6 7 CreateOLGraph(g); 8 PrintOLGraph(g); 9 10 printf("DFSTraverse:\n"); 11 DFSTraverse(g,visit); 12 13 printf("BFSTraverse:\n"); 14 BFSTraverse(g,visit); 15 16 system("pause"); 17 return 0; 18 }