1 注意InsertVertex(插入点函数)返回的是插入后,该点的指针。所以当你的图是空的时候(即Graph==NULL)时,你应该这样子调用该函数:Graph = InsertVertex(x, Graph).否则只有当图非空时,才可以调用。或者你可以为图添加一个表头,或者将Graph定义为全局变量,做一个小小的修改即可。解决方法有很多,不多列举。
2
3 像求最短路径,只要用到插入边函数, 这样就不需做修改。因为插入边函数返回插入边之后的新的图。这样子调用插入边函数:Graph = InsertEdge(x, y, Graph).
4
5 应用例程,可见算法中的《最短路径:广度优先搜索(C语言实现)》
6
7 [cpp] view plaincopyprint?
8 邻接表:C语言实现
9
10 源代码如下:
11 #include <stdio.h>
12 #include <stdlib.h>
13
14 typedef struct Ind_Node_tag
15 {
16 struct Ind_Node_tag *Next ;
17 int Number ;
18 }*Ind_Node ;
19 /*这是入度结点结构。Number记录该入度点的序号。*/
20 typedef struct Vertex_tag
21 {
22 int Number ;
23 Ind_Node Indegree ;
24 struct Vertex_tag *Next ;
25 }*Vertex ;
26 /* Number是指该点的序号。如点1,点2.
27 Indegree 是该点的入度数组
28 Next 指向下一个点*/
29
30 /*FindVertex:
31 if x in graph
32 return x
33 else
34 return NULL*/
35 Vertex FindVertex(int x, Vertex Graph)
36 {
37 while(Graph != NULL && Graph->Number != x)
38 Graph = Graph->Next ;
39 return Graph ;
40 }
41
42 /* InsertVertex:
43 if x not in graph
44 insert x into graph
45 return x
46 else
47 return x
48 */
49 Vertex InsertVertex(int x, Vertex Graph)
50 {
51 Vertex G ;
52 if(!(G = FindVertex(x, Graph))) //如果找到了X不做修改,直接返回它,
53 { //否则:
54 G = calloc(1, sizeof(struct Vertex_tag)) ; //分配内存
55 if(!G) { fprintf(stderr, "Out of memory!\n") ; exit(1) ; } //错误检测
56 G->Number = x ;
57 /*如果Graph是NULL的,那么就把G返回。
58 这就是为什么第一次不能插入点。因为插入点函数返回插入点的指针
59 如果Graph是全局的,那么可以使用Graph = G解决。使用表头的不解释*/
60 if(Graph == NULL)
61 return G ;
62 /* Graph不为空,那么将点插入到邻接图的最后面*/
63 while(Graph->Next != NULL)
64 Graph = Graph->Next ;
65 Graph->Next = G ;
66 }
67 return G ;
68 /*因此每一次调用该函数后,能够保证该点一定存在于表。
69 因为如果找到就返回它,不在就插入它 */
70 }
71 /* insert x
72 insert y
73 update indegree of x */
74 Vertex InsertEdge(int x, int y, Vertex Graph)
75 {
76 Vertex V ;
77 Ind_Node Ind ;
78 //Ind将要插入点x的入度结点
79 Ind = calloc(1, sizeof(struct Ind_Node_tag)) ;
80 if(!Ind){ fprintf(stderr, "Out of space!\n"); exit(1) ; }
81 Ind->Number = y ;
82 //首先,保证x在graph中。
83 //见InsertVertex注释。调用完插入点函数后,x一定存在于Graph
84 V = InsertVertex(x, Graph) ;
85 //如果图是空的即Graph == NULL,时,更新Graph.
86 //调用这个函数的正确调用方法是Graph = InsertEdge(x, y, Graph)
87 //这样子如果图是空的,那么就能够更新Graph了。
88 if(Graph == NULL)
89 Graph = V ;
90 //保证y在图中
91 InsertVertex(y, Graph) ;
92 //把入度点y插入到x的入度表中。
93 Ind->Next = V->Indegree ;
94 V->Indegree = Ind ;
95 //把Graph返回。
96 return Graph ;
97 }
98 //free memory
99 //释放内存
100 void GraphDestory(Vertex Graph)
101 {
102 Ind_Node Ind, ITmp ;
103 Vertex Tmp ;
104 while(Graph != NULL)
105 {
106 Ind = Graph->Indegree ;
107 while(Ind != NULL)
108 {
109 ITmp = Ind ;
110 Ind = Ind->Next ;
111 free(ITmp) ;
112 }
113 Tmp = Graph ;
114 Graph = Graph->Next ;
115 free(Tmp ) ;
116 }
117 }
118 //return how many vertex of graph
119 //计算图中有多少个点
120 int SizeOfGraph(Vertex Graph)
121 {
122 int Result = 0 ;
123 while(Graph != NULL)
124 {
125 Result ++ ;
126 Graph = Graph->Next ;
127 }
128 return Result ;
129 }
130 邻接表:C语言实现
131
132 源代码如下:
133 #include <stdio.h>
134 #include <stdlib.h>
135
136 typedef struct Ind_Node_tag
137 {
138 struct Ind_Node_tag *Next ;
139 int Number ;
140 }*Ind_Node ;
141 /*这是入度结点结构。Number记录该入度点的序号。*/
142 typedef struct Vertex_tag
143 {
144 int Number ;
145 Ind_Node Indegree ;
146 struct Vertex_tag *Next ;
147 }*Vertex ;
148 /* Number是指该点的序号。如点1,点2.
149 Indegree 是该点的入度数组
150 Next 指向下一个点*/
151
152 /*FindVertex:
153 if x in graph
154 return x
155 else
156 return NULL*/
157 Vertex FindVertex(int x, Vertex Graph)
158 {
159 while(Graph != NULL && Graph->Number != x)
160 Graph = Graph->Next ;
161 return Graph ;
162 }
163
164 /* InsertVertex:
165 if x not in graph
166 insert x into graph
167 return x
168 else
169 return x
170 */
171 Vertex InsertVertex(int x, Vertex Graph)
172 {
173 Vertex G ;
174 if(!(G = FindVertex(x, Graph))) //如果找到了X不做修改,直接返回它,
175 { //否则:
176 G = calloc(1, sizeof(struct Vertex_tag)) ; //分配内存
177 if(!G) { fprintf(stderr, "Out of memory!\n") ; exit(1) ; } //错误检测
178 G->Number = x ;
179 /*如果Graph是NULL的,那么就把G返回。
180 这就是为什么第一次不能插入点。因为插入点函数返回插入点的指针
181 如果Graph是全局的,那么可以使用Graph = G解决。使用表头的不解释*/
182 if(Graph == NULL)
183 return G ;
184 /* Graph不为空,那么将点插入到邻接图的最后面*/
185 while(Graph->Next != NULL)
186 Graph = Graph->Next ;
187 Graph->Next = G ;
188 }
189 return G ;
190 /*因此每一次调用该函数后,能够保证该点一定存在于表。
191 因为如果找到就返回它,不在就插入它 */
192 }
193 /* insert x
194 insert y
195 update indegree of x */
196 Vertex InsertEdge(int x, int y, Vertex Graph)
197 {
198 Vertex V ;
199 Ind_Node Ind ;
200 //Ind将要插入点x的入度结点
201 Ind = calloc(1, sizeof(struct Ind_Node_tag)) ;
202 if(!Ind){ fprintf(stderr, "Out of space!\n"); exit(1) ; }
203 Ind->Number = y ;
204 //首先,保证x在graph中。
205 //见InsertVertex注释。调用完插入点函数后,x一定存在于Graph
206 V = InsertVertex(x, Graph) ;
207 //如果图是空的即Graph == NULL,时,更新Graph.
208 //调用这个函数的正确调用方法是Graph = InsertEdge(x, y, Graph)
209 //这样子如果图是空的,那么就能够更新Graph了。
210 if(Graph == NULL)
211 Graph = V ;
212 //保证y在图中
213 InsertVertex(y, Graph) ;
214 //把入度点y插入到x的入度表中。
215 Ind->Next = V->Indegree ;
216 V->Indegree = Ind ;
217 //把Graph返回。
218 return Graph ;
219 }
220 //free memory
221 //释放内存
222 void GraphDestory(Vertex Graph)
223 {
224 Ind_Node Ind, ITmp ;
225 Vertex Tmp ;
226 while(Graph != NULL)
227 {
228 Ind = Graph->Indegree ;
229 while(Ind != NULL)
230 {
231 ITmp = Ind ;
232 Ind = Ind->Next ;
233 free(ITmp) ;
234 }
235 Tmp = Graph ;
236 Graph = Graph->Next ;
237 free(Tmp ) ;
238 }
239 }
240 //return how many vertex of graph
241 //计算图中有多少个点
242 int SizeOfGraph(Vertex Graph)
243 {
244 int Result = 0 ;
245 while(Graph != NULL)
246 {
247 Result ++ ;
248 Graph = Graph->Next ;
249 }
250 return Result ;
251 }