Tải bản đầy đủ (.pdf) (10 trang)

Code Lý thuyết Đồ Thị (Danh sách cung Ma trận)

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (126.91 KB, 10 trang )

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;im;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


×