1 Code LTDT Tuần 5
2 Danh sách cung
3 Ma trận kề
4 Ma trận đỉnh-cung (dạng chuyển đồi)
5 Ma trận đỉnh-đỉnh (dạng chuyển đồi)
6 Đọc đồ thị từ tập tin
7 tuần 4 duyệt chiều rộng thì lấy cái bên phải cùng sang xét
8 duyệt chiều sâu thì xét cái đầu tiên bên trái sang
9 -----------------------------------------------------------------------------------------
--------------------------------------------------------
10 -----------------------------------------------------------------------------------------
--------------------------------------------------------
11 -----------------------------------------------------------------------------------------
--------------------------------------------------------
12 -----------------------------------------------------------------------------------------
--------------------------------------------------------
13 --#############################################THEO DANH SACH
CUNG##################################################################################
14 !!!Cấu trúc khai báo của 1 Ctr Danh sach Cung:
15 $$Code:
16 #include <stdio.h>
17 #define MAX_M 500
18 //Cấu trúc Edge lưu dữ liệu của 1 cung
19 typedef struct {
20 int u, v;
21 } Edge;
22 //Khai báo cấu trúc dữ liệu Graph
23 typedef struct {
24 int n, m;
25 Edge edges[MAX_M];
26 } Graph;
27
28
29
30 !!!!!Đọc dữ liệu trong tập tin dt.txt(Hàm này nằm trong hàm MAIN)
31 //Đọc số đỉnh và số cung & khởi tạo đồ thị
32 FILE* file = fopen("dt.txt", "r");
33 //freopen("dt.txt", "r", stdin);
34
35 !!!!==> sau đó đổi scanf thành fscanf(file,"? %d",&)
36 !!!!==> xong r fclose(file); de dong file xong moi tới hàm để in ra màn hình
37 -----------------------------------------------------------------------------------------
--------------------------------------------------------
38 -----------------------------------------------------------------------------------------
--------------------------------------------------------
39 -----------------------------------------------------------------------------------------
--------------------------------------------------------
40 -----------------------------------------------------------------------------------------
--------------------------------------------------------
41 -----------------------------------------------------------------------------------------
--------------------------------------------------------
42 1. Hàm init_graph có số đỉnh bằng n và số cung bằng 0 ( PP Danh sách cung):
43 $$CODE:
44 void init_graph(Graph *pG, int n){
45 pG->n=n;
46 pG->m=0;
47 }
48 -----------------------------------------------------------------------------------------
--------------------------------------------------------
49 2. Hàm add_edge() (Hàm chung nhớ tùy vào đề bớt các điều kiện):
50 -----------------
51 Cơ bản chỉ cần điều kiện(trùng được , uv và vu phân biệt):
52 $$CODE:
53
54 void add_edge(Graph *pG, int u, int v) {
55 if (u>0 && u<=pG->n && v>0 && v<=pG->n) {
56 // Thêm cung (u, v) vào danh sách cung của đồ thị
57 pG->edges[pG->m].u = u;
58 pG->edges[pG->m].v = v;
59 pG->m++;
60 }
61 }
62 ------------------
63 Nâng cao nếu uv có rồi khơng thêm vào nữa và các tham số đều hợp lệ (nếu không hợp lệ
thêm điều kiện vào if của hàm void) Có hướng:
64 $$CODE:
65
66 void add_edge(Graph *pG, int u, int v) {
67 for (int i = 0; i < pG->m; i++)
68 if (pG->edges[i].u == u && pG->edges[i].v == v)
69 return;
70 pG->edges[pG->m].u = u;
71 pG->edges[pG->m].v = v;
72
73 pG->m++;
74 }
75 -------------------
76 Nâng cao nếu cung (u, v) hoặc cung (v, u) đã có trong đồ thị rồi thì bỏ qua, khơng thêm
vào nữa(không cho (1,1) luôn). Vô hướng:
77 void add_edge(Graph *pG, int u, int v) {
78 if (u == v)
79 return;
80 for (int i = 0; i < pG->m; i++)
81 if ((pG->edges[i].u == u && pG->edges[i].v == v) ||
82 (pG->edges[i].u == v && pG->edges[i].v == u) || u==v)
83 return;
84 pG->edges[pG->m].u = u;
85 pG->edges[pG->m].v = v;
86 pG->m++;
87 }
88 -----------------------------------------------------------------------------------------
--------------------------------------------------------
89 -----------------------------------------------------------------------------------------
--------------------------------------------------------
90 -----------------------------------------------------------------------------------------
--------------------------------------------------------
91
92 3.Hàm adjacent(Graph *pG, int u, int v) để kiểm tra đỉnh u có kề với đỉnh v không theo
mẫu (prototype):
93 $$CODE:
94
95 int adjacent(Graph *pG, int u, int v) {
96 int i;
97 for (i = 0; i < pG->m; i++)
98 if ((pG->edges[i].u == u && pG->edges[i].v == v) ||
99 (pG->edges[i].u == v && pG->edges[i].v == u))
100 return 1;
101 return 0;
102 }
103
104 -----------------------------------------------------------------------------------------
--------------------------------------------------------
105 -----------------------------------------------------------------------------------------
--------------------------------------------------------
106 -----------------------------------------------------------------------------------------
--------------------------------------------------------
107
108 4. Hàm degree(Graph *pG,int u) Đếm bậc của đỉnh u của đồ thị bất kỳ:
109 $$CODE:
110 int degree(Graph *pG, int u) {
111 int e, deg_u = 0;
112 //Duyệt qua từng cung 0, 1, 2, …, m - 1
113 for (e = 0; e < pG->m; e++) {
114 //Nếu cung có dạng (u, -)
115 if (pG->edges[e].u == u)
116 deg_u++;
117 //Nếu cung có dạng (-, u)
118 if (pG->edges[e].v == u)
119 deg_u++;
120 }
121
122 return deg_u;
123 }
124 Trong ham main:
125 for (int u = 1; u <= n; u++){
126 printf("deg(%d) = %d\n", u, degree(&pG, u));
127 }
128 return 0; // nam ngoai ham for
129
130
131 -----------------------------------------------------------------------------------------
--------------------------------------------------------
132 -----------------------------------------------------------------------------------------
--------------------------------------------------------
133 -----------------------------------------------------------------------------------------
--------------------------------------------------------
134 !!!!!!!!5. //Đọc m cung và thêm vào đồ thị( Bo Tro trong ham Main)
135 !!!!!!!!!rong Hàm Main:
136 int e;
137 for (e = 0; e < m; e++) {
138 scanf("%d%d", &u, &v); ||nếu có đọc file nhớ đồi thành fscanf(file,"",&);||
139 add_edge(&G, u, v);
140 }
141
142 -----------------------------------------------------------------------------------------
--------------------------------------------------------
143 -----------------------------------------------------------------------------------------
--------------------------------------------------------
144 -----------------------------------------------------------------------------------------
--------------------------------------------------------
145 ---------####################################################THEO DANH SACH
CUNG############################################################--------
146
---------------------------------------------------------------------------------------
----------------------------------------------------------
147 -----------------------------------------------------------------------------------------
--------------------------------------------------------
148 -----------------------------------------------------------------------------------------
--------------------------------------------------------
149
150
151
152 ---------------------------------------------##đồ thị vô hướng và in các đỉnh kề của các
đỉnh ra màn hình.Biểu diễn đồ thị bằng phương pháp "Danh sách
cung".(neighbours(2))####----------------------------------------------------------------
-----------
153 ##
154 Ham in cac dinh ke cua dinh ra man hinh !!trong main!!! (cho đồ thị vô hướng!!!!!!!!)
155 ###neighbours#####
156 for (int u = 1; u <= n; u++) {
157 printf("neighbours(%d) = ", u);
158 for (int v = 1; v <= n; v++)
159 if (adjacent(&pG, u, v))
160 printf("%d ", v);
161 printf("\n");
162 }
163
164
165 return 0;
166
167 -----------------------------------------------------------------------------------------
-----------------------------------
168 !! cho đồ thị !!!có hướng!!! thì cái hàm adjacent bỏ cái điều kiện u=v && v=u sau || là
done hàm neighbours vẫn giử nguyên
169 int adjacent(Graph *pG,int u, int v){
170 int i;
171 for(i=0;i
m;i++){
172 if((pG->edges[i].u==u && pG->edges[i].v==v)){
173 return 1;
174 }
175 }return 0;
176 }
177
178 --------------------------------------------------MA TRAN
KEEEEEEEEEEEEEE--------------------------------------------------------------------
179
180 khai bao MA TRAN KE
181 #include <stdio.h>
182 #define MAX_N 100
183
184 typedef struct {
185 int n, m;
186 int A[MAX_N][MAX_N];
187 } Graph;
188 #####Hàm init_graph của ma trận kề ( đơn đồ thị vô hướng hoặc đồ thị vơ hướng có thể
chứa đa cung đa khuyên)
189 void init_graph(Graph *pG, int n){
190 pG->n=n;
191 pG->m=0;
192 for(int u=1;u<=n;u++){
193 for(int v=1;v<=n;v++){
194 pG->A[u][v] = 0;
195
196 }
197 }
198 }
199
200 #### Hàm add_edge của ma trận kề ( đơn đồ thị vô hướng hoặc đồ thị vô hướng có thể chứa
đa cung đa khuyên) cứ vô hướng là sử dụng
201
202 void add_edge(Graph *pG,int u,int v){
203 pG->A[u][v] += 1;
204 if(u != v){
205 pG->A[v][u] += 1;
206 }
207 pG->m++;
208 }
209 -----------------------------------------------------------------------------------------
---------
210 -----------------------------------------------------------------------------------------
--------
211 #######MA TRẬN KỀ đồ thị có hướng đa cung đa khuyên
212 #######chỉ cần thay đổi hàm add_edge khơng cần if cứ có hướng là sdung hàm này
213 void add_edge(Graph *pG, int u, int v) {
214 pG->A[u][v] += 1;
215 pG->m++;
216 }
217
218 -----------------------------------------------------------------------------------------
----------
219 ##Hàm In ma trận kề ra man hình
220 printf("Ma tran ke:\n");
221 for (int u = 1; u <= n; u++) {
222 for (int v = 1; v <= n; v++)
223 printf("%d ", pG.A[u][v]);
224 printf("\n");
225 }
226
227 return 0;
228
229 ----------Các hàm tính bậc của đỉnh trong Ma trận kề các loại đồ
thị--------------------------------------------------------------------------------------
----------
230
231 * #####hàm Degree "Ma trận kề" dùng để lưu trữ các đồ thị vơ hướng (có thể chứa đa
cung và chứa khuyên).
232 int degree(Graph *pG,int u){
233 int v, deg_u=0;
234 for(v=1; v<= pG->n ; v++){
235 deg_u += pG->A[u][v];
236 }
237 return deg_u += pG->A[u][u];
238 }
239
240 -----------------------------------------------------------------------------------------
-----------------
241
242 * #####hàm Degree "Ma trận kề" dùng để lưu trữ các đồ thị có hướng (có thể chứa đa
cung và chứa khuyên).
243 int degree(Graph *pG,int u){
244 int v, deg_u=0;
245 for(v=1; v<= pG->n ; v++){
246 deg_u += pG->A[u][v] + pG->A[v][u];
247 }
248 return deg_u;
249 }
250 -----------------------------------------------------------------------------------------
-----------------
251
252
253 * #####Hàm indegree "Ma trận kề" dùng để lưu trữ các đồ thị có hướng (có thể chứa đa
cung và chứa khuyên).
254 int indegree(Graph *pG, int u){
255 int v, deg_u=0;
256 for(v = 1;v<= pG->n; v++){
257 deg_u += pG->A[v][u];
258 }
259 return deg_u;
260 }
261 -----------------------------------------------------------------------------------------
-----------------
262
263 * ####Hàm outdegree "Ma trận kề" dùng để lưu trữ các đồ thị có hướng (có thể chứa đa
cung và chứa khuyên). Giống hàm degree vô hướng but return deg_u
264 int outdegree(Graph *pG,int u){
265 int v, deg_u=0;
266 for(v=1; v<= pG->n ; v++){
267 deg_u += pG->A[u][v];
268 }
269 return deg_u;
270 }
271
272 * ##### Hàm neighbours in ra trong ma trận kề vô hướng giống dsach cung thay đổi ngay
if cịn có hướng thì đổi điều kiện trong add_edge
273 for (int u = 1; u <= n; u++) {
274 printf("neighbours(%d) = ", u);
275 for (int v = 1; v <= n; v++)
276 if (pG.A[u][v])
277 printf("%d ", v);
278 printf("\n");
279 }
280
281
282 return 0;
283 -----------------------------------------------------------------------------------------
---------------------------
284 -----------------------------------------------------------------------------------------
------------------------
285 -----------------------------------------------------------------------------------------
------------------------
286
287 #### Dạng chuyển đổi
288
289 **** Từ Ma trận kề in ra các các cung kề dạng bài này không cần hàm init với hàm add_edge
290
291 **Hàm khai báo:
292 #include <stdio.h>
293 #define MAX_N 100
294
295 typedef struct {
296 int n;
297 int A[MAX_N][MAX_N];
298 } Graph;
299
300 int main() {
301 Graph pG;
302 int n, a;
303
304 //Đọc số đỉnh và gán cho G.n
305 scanf("%d", &n);
306 pG.n = n;
307 **sau đó
308 //Đọc ma trận kề và gán giá trị vào G.A
309 for (int u = 1; u <= n; u++) {
310 for (int v = 1; v <= n; v++) {
311 scanf("%d", &a);
312 pG.A[u][v] = a;
313 }
314 }
315 **### Hàm in ra nè có điều kiện khi u v (U<=v) (Đồ thị có hướng)
316 **//Liệt kê các cung của G theo thứ tự u <= v sài chung cho các dạng chuyển dồi từ
ma trận in ra mỗi cung trên 1 dòng theo mẫu: u v (u≤v)
317 .
318 for (int u = 1; u <= n; u++) {
319 for (int v = u; v <= n; v++) { tùy chỉnh dòng này
320 for (int k = 0; k < pG.A[u][v]; k++)
321 printf("%d %d\n", u, v);
322 }
323 }
324 return 0;
325 **### Hàm in ra nè 0 có điều kiện khi u v chỉ cần sửa dòng for thứ 2 thành v = 1 là ok
vẫn là ma trận kề in ra các cung (Đồ thị vô hướng)
326
327
328 -----------------------------------------------------------------------------------------
------------
329 ### hàm in ra danh sách kề (In ra n dòng, mỗi dòng tương ứng với một danh sách kề.) của
ĐỒ THỊ VÔ HƯỚNG giống hàm in của đồ thị vô hướng for 2 v=1 chỉ sửa dòng for thứ 3 in ra
"v" và dòng for bự in "0\n" nhớ return 0; ngoài hàm
330 (In ra n dòng, mỗi dòng tương ứng với danh sách kề của 1
đỉnh.)
331 //G.A[u][v] cho biết số cung đi từ u đến v
332 for (int u = 1; u <= n; u++) {
333 for (int v = 1; v <= n; v++) {
334 for (int k = 0; k < pG.A[u][v]; k++){
335 printf("%d ", v);
336 }
337 }
338 printf("0\n");
339 }
340 return 0;
341 ### hàm In ra n dòng, mỗi dòng tương ứng với danh sách kề của 1 đỉnh. giống hàm trên
342
343 -----------------------------------------------------------------------------------------
------------------------
344 -----------------------------------------------------------------------------------------
------------------------
345 Viết chương trình bằng ngôn ngữ C cho phép người nhập vào danh sách kề của các đỉnh
trong một đồ thị vô hướng và in ma trận kề của nó màn hình.
346 Dạng nhập dsach kề in ra ma trận( không khai báo a trong hàm main)
347
348 ####Hàm Chung:
349 #include <stdio.h>
350 #define MAX_N 100
351
352 * typedef struct {
353 int n;
354 int A[MAX_N][MAX_N];
355 }Graph;
356
357 * void init_graph(Graph *pG, int n) {
358 pG->n = n;
359
360 for (int u = 1; u <= n; u++)
361 for (int v = 1; v <= n; v++)
362 pG->A[u][v] = 0;
363 }
364 -------------------
365 * void add_edge(Graph *pG, int u, int v) {
366 pG->A[u][v] += 1;
367 }
368 --------------------
369 * int main() {
370 Graph pG;
371 int n;
372 scanf("%d", &n);
373 pG.n = n;
374 **//Đọc các danh sách kề
375 for (int u = 1; u <= n; u++) {
376 int v;
377 while (1) {
378 scanf("%d", &v);
379 if (v == 0)
380 break;
381 add_edge(&pG, u, v);
382 } của hàm while
383 } ngoặc này của hàm for
384 #*# hàm in ra ma trận kề sử dụng cho đồ thị vơ hướng và có hướng luôn sài chung
385 for(int u=1;u<=n;u++){
386 for(int v=1;v<=n;v++){
387 printf("%d ",pG.A[u][v]);
388 }
389 printf("\n");
390 }
391 return 0;
392
393 -----------------------------------------------------------------------------------------
-------------
394 -----------------------------------------------------------------------------------------
-------------
395 Ma Trận Đỉnh-Cung
396 ### Viết hàm add_edge(Graph* pG, int e, int x, int y) để thêm cung e = (x, y) vào đồ thị
pG theo mẫu (prototype) Vô Hướng Không chứa khuyên
397
398 void add_edge(Graph* pG, int e, int x, int y) {
399 if (x >= 0 && x < pG->n && y >= 0 && y < pG->n) {
400 if (pG->A[x][e] == 0 && pG->A[y][e] == 0) {
401 pG->A[x][e] = 1;
402 pG->A[y][e] = 1;
403 }
404 }
405 }
406
407
408 ### Viết hàm List neighbors(Graph* pG, int u) trả về danh sách các đỉnh kề của u theo
mẫu (prototype): Vô Hướng Không chứa khuyên
409
410 List neighbors(Graph* pG, int x) {
411 List L;
412 make_null(&L);
413 int e, y;
414 for (y = 1; y <= pG->n; y++) {
415 if (x == y) continue;
416 for (e = 1; e <= G->m; e++)
417 if (pG->A[x][e] > 0 && pG->A[y][e] > 0) {
418 push_back(&L, y);
419 break;
420 }
421 }
422 return L;
423 }
424 --------------------------------------------------------------------------------
425 "Ma trận đỉnh - đỉnh" dùng để biểu diễn các đơn đồ
thị vô hướng.
426
427 Viết hàm int deg(Graph* G, int x) để tính bậc của đỉnh u theo mẫu (prototype): ( *G chứ
không phải *pG)
428
429 int deg(Graph* pG, int x){
430 int de=0;
431 int i;
432 for(i=1;i<=pG->n;i++)
433 if(pG->A[x][i]==1)
434 de++;
435 return de;
436 }
437
438
439 Bài 4 - Ứng dụng: Tìm đỉnh có bậc lớn nhất
440 Viết chương trình tính và in ra màn hình đỉnh có bậc lớn nhất và bậc tương ứng của
nó.
441 Nếu có nhiều đỉnh có bật bằng nhau thì in ra đỉnh có số thứ tự nhỏ nhất.
442 ------------
443 ** #include <stdio.h>
444 #define MAX_N 100
445
446 * typedef struct {
447 int A[MAX_N][MAX_N];
448 int n;
449 } Graph;
450
451 * void init_graph(Graph *pG, int n) {
452 pG->n = n;
453 for (int i = 0; i < n; ++i) {
454 for (int j = 0; j < n; ++j) {
455 pG->A[i][j] = 0;
456 }
457 }
458 }
459
460 * void add_edge(Graph *pG, int u, int v) {
461 pG->A[u][v] = 1;
462 pG->A[v][u] = 1;
463 }
464
465 * int deg(Graph *pG, int u) {
466 int degree = 0;
467 for (int i = 0; i < pG->n; ++i) {
468 degree += pG->A[u][i];
469 }
470 return degree;
471 }
472
473 * int main() {
474 Graph pG;
475 int n, m;
476 scanf("%d %d", &n, &m);
477 init_graph(&pG, n);
478 * for (int i = 0; i < m; ++i) {
479 int u, v;
480 scanf("%d %d", &u, &v);
481 add_edge(&pG, u - 1, v - 1);
482 }
483 int maxDegree = -1;
484 int maxVertex = -1;
485 * for (int u = 0; u < n; ++u) {
486 int degree = deg(&pG, u);
487 if (degree > maxDegree || (degree == maxDegree && u < maxVertex)) {
488 maxDegree = degree;
489 maxVertex = u;
490 }
491 }
492 *In printf("%d %d\n", maxVertex + 1, maxDegree);
493
494 return 0;
495 }
496
497 --------------------------------------------------------------------
498 Bài 6 - Đọc đồ thị từ tập tin
499 Hãy viết chương trình đọc đồ thị từ tập tin và hiển thị ma trận kề của đồ thị này.
500
501 Giả sử đồ thị được cho là đồ thị vô hướng đơn.
502
503 Đầu vào (Input):
504
505 Dữ liệu đầu vào được nhập từ tập tin dt1.txt với định dạng:
506
507 - Dòng đầu tiên chứa 2 số nguyên n và m, tương ứng là số đỉnh và số cung.
508
509 - m dòng tiếp theo mỗi dòng chứa 2 số nguyên u v mô tả cung (u, v).
510
511 Đầu ra (Output):
512
513 In ra Ma trận kề (0/1) của đồ thị
514
515 #include <stdio.h>
516 #define MAX_N 100
517
518 * typedef struct {
519 int A[MAX_N][MAX_N];
520 int n;
521 } Graph;
522
523 * void init_graph(Graph *pG, int n) {
524 pG->n = n;
525 for (int i = 0; i < n; ++i) {
526 for (int j = 0; j < n; ++j) {
527 pG->A[i][j] = 0;
528 }
529 }
530 }
531
532 * void add_edge(Graph *pG, int u, int v) {
533 pG->A[u][v] = 1;
534 pG->A[v][u] = 1;
535 }
536
537 * void hienthi_matran(Graph *pG) {
538 for (int i = 0; i < pG->n; ++i) {
539 for (int j = 0; j < pG->n; ++j) {
540 printf("%d ", pG->A[i][j]);
541 }
542 printf("\n");
543 }
544 }
545
546 * int main() {
547 Graph pG;
548 int n, m;
549 * // Đọc file
550 FILE *file = fopen("dt1.txt", "r");
551 if (file == NULL) {
552 printf("Cannot open file dt1.txt\n");
553 return 1;
554 }
555 fscanf(file, "%d %d", &n, &m);
556 init_graph(&pG, n);
557 for (int i = 0; i < m; ++i) {
558 int u, v;
559 fscanf(file, "%d %d", &u, &v);
560 add_edge(&pG, u - 1, v - 1);
561 }
562 * // Đóng file
563 fclose(file);
564 * // hien thi ma tran
565 hienthi_matran(&pG);
566 return 0;
567 }
568
569 -----------------------------------------------------------------------------------------
--------------------------
570
571
572