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

Tìm đường đi ngắn nhất dijkstra

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 (846.8 KB, 15 trang )

TRƯỜNG ĐẠI HỌC THƯƠNG MẠI
KHOA HTTTKT & TMĐT
-----🙞🙜🕮🙞🙜-----

BÀI THẢO LUẬN
HỌC PHẦN: CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT
ĐỀ TÀI: TÌM ĐƯỜNG ĐI NGẮN NHẤT – DIJKSTRA

Giảng viên: Cù Nguyên Giáp
Nhóm thực hiện: 7
Mã lớp học phần: 2231INFO1311

Hà Nội – 2022
1


DANH SÁCH THÀNH VIÊN NHÓM 7
Họ tên

Mã sinh viên

Phạm Thị Uyên

20D190113

Nguyễn Thị Phương Vy

20D190054

Hồ Hải Yến


20D190114

2


MỤC LỤC
LỜI MỞ ĐẦU ...........................................................................................................1
I. Một số khái niệm liên quan ...............................................................................2
1.1. Đồ thị.............................................................................................................2
1.2. Đường đi .......................................................................................................2
1.3. Đường đi ngắn nhất .....................................................................................2
II.

Ý tưởng và các bước của thuật toán .............................................................3

III. Đánh giá độ phức tạp của thuật toán ...........................................................4
IV. Chương trình minh họa .................................................................................4
KẾT LUẬN .............................................................................................................11
TÀI LIỆU THAM KHẢO .....................................................................................12

3


LỜI MỞ ĐẦU
Lý thuyết đồ thị là ngành học được phát triển từ lâu nhưng lại có nhiều ứng dụng
hiện đại. Những ý tưởng cơ bản của nó đã được nhà toán học Thụy sĩ vĩ đại Leonhard Euler
đưa ra từ thế kỷ 18.
Đồ thị là một cấu trúc rời rạc gồm các đỉnh và các cạnh nối các đỉnh đó. Đây là cơng
cụ hữu hiệu để mơ hình hóa và giải quyết các bài toán trong nhiều lĩnh vực khoa học, kỹ
thuật, kinh tế, xã hội,...

Môn cấu trúc dữ liệu và giải thuật là môn học hấp dẫn, mang tính thực tế cao. Những
vấn đề trong mơn học như: các bài toán về đường đi, cây, mạng đã và đang được nhiều
người quan tâm, nghiên cứu. Bài tốn tìm đường đi ngắn nhất là bài toán quan trọng trong
lý thuyết đồ thị, nó được áp dụng để giải quyết rất nhiều bài toán trong thực tế như điều
khiển tối ưu, giao thơng vận tải, mạng viễn thơng ....
Vì vậy, nghiên cứu vấn đề này là hết sức cần thiết vì nó có thể giải quyết được nhiều
khó khăn, phức tạp nảy sinh từ thực tế cuộc sống. Do đó, nhóm 7 chúng em chọn đề tài:
''Tìm đường đi ngắn nhất – Dijkstra''.

1


I.

Một số khái niệm liên quan
1.1.

Đồ thị

Một đổ thị (graph) G (V, E) bao gồm một tập hợp hữu hạn V các nút, hay đỉnh
(vertices) và một tập hợp hữu hạn E các cặp đỉnh mà ta gọi là cung.
Nếu (v1, v2) là cặp đỉnh thuộc E thì ta nói: có một cung nối v1 và v2. Nếu cung v1, v2
(khác với cung ( v2, v1) thì ta có một đồ thị định hướng (dirccied graph hay digraph). Lúc
đó (v1, v2) được gọi là cung định hướng v1, v2. Nếu thứ tự các nút trên cung khơng được coi
trọng thì ta gọi đồ thị khơng định hướng (undirected graph)
Bảng hình vẽ có thể biểu diễn bằng thị như hình sau:

Mạch điện, mạng lưới giao thơng, mạng lưới máy tính…là các ví dụ thực tế của đồ thị.
Nếu (v1, v2) là một cung trong tập E(G) thì v1 và v2 gọi là lân cận của nhau (adjacent).
1.2.


Đường đi

Đường đi (walk/path): là một chuỗi luân phiên giữa đỉnh và cạnh, bắt đầu và kết
thúc bởi một đỉnh. Trong đó, mỗi đỉnh là đỉnh đầu cuối của hai cạnh đứng liền trước và
liền sau trong chuỗi, các đỉnh đứng liền trước và liền sau một cạnh là các đỉnh đầu cuối của
cạnh đó. Khi có hai cạnh giống nhau trên chuỗi có thể loại bỏ bớt các cạnh trùng nhau, sao
cho khơng có cạnh nào của đồ thị có mặt quá một lần trên đường đi. Một đường đi đơn
(simple path) là đường đi mà mọi đỉnh trên đó, trừ đỉnh đầu và đỉnh cuối, đều khác nhau.
Một chu trình (cycle) là một đường đi đơn mà đỉnh đầu và đỉnh cuối trùng nhau.
1.3.

Đường đi ngắn nhất

Trong lý thuyết đồ thị, bài toán đường đi ngắn nhất là bài tốn tìm một đường đi
giữa hai đỉnh sao cho tổng các trọng số của các cạnh tạo nên đường đi đó là nhỏ nhất. Định
nghĩa một cách hình thức, cho trước một đồ thị có trọng số (nghĩa là một tập đỉnh V, một
tập cạnh E, và một hàm trong số có giá trị thực f : E → R), cho trước một đỉnh v thuộc V,
tìm một đường đi P v tới mỗi đỉnh v' thuộc V sao cho :
∑ 𝑓(𝑝)
𝑝∈𝑃

2


là nhỏ nhất trong tất cả các đường nối từ v tới v'
II.

Ý tưởng và các bước của thuật toán


Thuật tốn Dijkstra cũng tối ưu hóa đường đi bằng cách xét các cạnh (w, 𝑣), so sánh
hai đường đi 𝑆→𝑣 sẵn có với đường đi 𝑆→w→𝑣. Thuật tốn hoạt động bằng cách duy trì
một tập hợp các đỉnh trong đó ta đã biết chắc chắn đường đi ngắn nhất. Mỗi bước, thuật
toán sẽ chọn ra một đỉnh w mà chắc chắn sẽ khơng thể tối ưu hơn nữa, sau đó tiến hành tối
ưu các đỉnh 𝑣 khác dựa trên các cạnh (w,𝑣) đi ra từ đỉnh w. Sau N bước, tất cả các đỉnh đều
sẽ được chọn, và mọi dường đi tìm được sẽ là ngắn nhất.
Cụ thể hơn, thuật tốn sẽ duy trì đường đi ngắn nhất đến tất cả các đỉnh. Ở mỗi
bước, chọn đường đi 𝑆→w có tổng trọng số nhỏ nhất trong tất cả các đường đi đang được
duy trì. Sau đó tiến hành tối ưu các đường đi 𝑆→𝑣 bằng cách thử kéo thành 𝑆→w→𝑣 như
đã mơ tả trên.
Cho đồ thị có hướng (hoặc vơ hướng) với các cạnh có trọng số G=(V,E). Trọng số
của một cạnh có thể xem là khoảng cách giữa 2 đỉnh. Cho trước một đỉnh v0, gọi là đỉnh
nguồn. Tìm đường đi ngắn ngắn nhất từ v0 đến các đỉnh cịn lại của G.
Các bước của thuật tốn:
Tập các đỉnh của đồ thị là V, gọi S là tập các đỉnh lấy từ V.
Bước 1: Khởi đầu ta cho S bao gồm 1 đỉnh nguồn v0 S = {v0}. Sau mỗi bước dần
dần đưa các đỉnh của V vào trong tập hợp S sao cho tập hợp S bằng tập hợp V.
Bước 2: Chọn một đỉnh w thuộc tập hợp V-S (nằm ngoài tập hợp S) sao cho độ dài
đường đi từ v0 đến w là ngắn nhất và ta thêm w vào tập hợp S.
Bước 3: Lặp lại bước 2 n-1 lần và như vậy tập hợp S sẽ bao gồm các đỉnh của tập
hợp V và có thể tìm được một đường đi ngắn nhất từ v0 mà đường đi đó chỉ đi qua các
đỉnh đã tồn tại trong S.
Thiết kế thuật toán Dijkstra để xác minh đường đi ngắn nhất
- Ma trận A để lưu độ dài các cạnh, tức là A[i,j] là độ dài của cạnh (i,j), nếu khơng
có cạnh (i,j) thì A[i,j]= vơ cùng.
- Mảng S[n] lưu các số 0 và 1, biểu diễn tập hợp S: S[v]==1 => v thuộc S và S[v]
== 0 => v thuộc V-S.
- Khởi đầu S[v0]=1, các S[v]=0. Tại mỗi bước nếu w được đưa vào S => đặt
S[w]=1.
- Mảng D[n] để lựu độ dài của đường đi ngắn nhất từ v0 đến mỗi đỉnh của đồ thị.

- Khởi đầu D[V]= A[v0, v].
- Tại mỗi bước, sẽ cập nhật lại D[v] để lưu độ dài đường đi ngằn nhất từ đỉnh v0
tới đỉnh v, đường đi này chỉ đi qua các đỉnh đã có trong S.
- Đê lưu lại các đỉnh trên đường đi ngắn nhất, ta dùng một mảng P[n].
3


-

P[V]= w với w là đỉnh "trước" đỉnh v trong đường đi.
Khởi đầu P[v]= v0 với mọi đỉnh v.
Tại mỗi bước lặp, cập nhật lại P[V].
Từ đỉnh đích, sử dụng mảng P, lần ngược lại đỉnh nguồn v0 để xác định đường
đi ngắn nhất từ v0 đến đích.

void Dijkstra(){
for (v=0;vS[v] = 0;
D[v] = A[v0,v]; // Khởi đầu gán các giá trị cho D
P[v] = v0;}// đứng trước v là v0 với mọi v
S[v0] = 1; // S chỉ chứa một đỉnh nguồn v0
for (i=1;i// Chọn đỉnh w trong V-S sao cho D[w] nhỏ nhất
S[w]=1;//thêm w vào S
for(mỗi đỉnh u thuộc V-S) do {
if (D[v]>D[w])+A[w,v]){
D[v]=D[w]+A[w,v];
P[v]=w;}
}}}
III.


Đánh giá độ phức tạp của thuật tốn

Độ phức tạp thuật tốn: Ta có N lần lặp:
 Bước đầu tiên có độ phức tạp O(N) mỗi lần lặp
 Bước thứ hai có tổng độ phức tạp O(M) qua tất cả các lần lặp
Như vậy độ phức tạp của thuật toán cơ bản sẽ là O(N2 + M).
IV.

Chương trình minh họa

/*
Thuat toan Dijkstra tim duong di ngan nhat tu mot dinh den cac dinh con lai
Bai toan:
Cho do thi co huong (hoac vo huong) voi cac canh co trong so G = (V,E)
Cho truoc mot dinh v0, goi la dinh nguon
4


Tim duong di ngan nhat tu v0 den cac dinh con lai

Ma tran trong so: (file "dothi.txt")
5
0.00

10.00

3.40282e+38

30.00


3.40282e+38
0.00
3.40282e+38

50.00

3.40282e+38

3.40282e+38
10.00

3.40282e+38

0.00

3.40282e+38

3.40282e+38
60.00

3.40282e+38

10.00

0.00

3.40282e+38
0.00


3.40282e+38

3.40282e+38

3.40282e+38

100.00

*/

#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
#define size 30
#define duongVC 3.40282e+38

//So float 32 bit lon nhat

void read_file(char file_name[], float A[][size], int *n){
int i,j;
FILE *f;
f=fopen(file_name,"r");

if (f==NULL){
5


printf("Mo file co loi!!!");
return;
}


fscanf(f,"%d", n);

//Doc so dinh cua do thi n

for (i=0; i<*n; i++)
for (j=0; j<*n; j++)
fscanf(f, "%f", &A[i][j]);

fclose(f);
}

void in_ma_tran(float A[][size], int n){
int i,j;

printf("Ma tran trong so ban dau\n");
for (i=0; ifor (j=0; jif ( A[i][j] < duongVC) printf("%8.2f", A[i][j]);
else printf ("%8c", 236);
hieu vo cung
printf("\n");
}
}

6

//236 la ma ki ASCCII cua ky



void init(float dong_v0[], int v0, int S[], float D[], int P[], int n){
int v;
for (v=0; vS[v]= 0;

//tat ca cac dinh v khac v0 deu thuoc V-S

D[v]= dong_v0[v]; //do dai duong di tu dinh v0 toi v la A[v0][v] tuc la
dong_v0[v]
P[v]= v0;

//dung truoc v la v0

}
S[v0]=1; //Dua v0 vao tap S

}
int chon_dinh(int S[], float D[], int n){
int w, wmin;
float emin=duongVC;

for (w=0; wif(!S[w] && D[w] < emin){
emin= D[w];
wmin= w;
}
w= wmin; //dinh w chon duoc
D[w]= emin; //do dai duong di tu v0 toi dinh chon duoc w la do dai nho nhat
return w;
}


void update (float A[][size], int S[], float D[], int P[], int w, int n){
7


int v;
S[w]=1; //them w vao S

for (v=0; vif (!S[v] && D[v]> D[w] + A[w][v]){
D[v]= D[w] + A[w][v];
P[v] = w;
}
}

void Dijkstra(float A[][size], int v0, int n, int P[]){
int w,i;
int S[n]; // S[u] ==1 dinh u thuoc S, S[u]==0 dinh u thuoc V-S
float D[n]; //D[v] la do dai duong di tu dinh v0 den dinh v

init (A[v0], v0, S, D, P, n); //A[v0] do dai cac canh xuat phat tu dinh v0

for (i=1; iw= chon_dinh(S,D,n);
update(A,S,D,P,w,n);

}
}

void in_PA (float A[][size], int P[], int v0, int dich, float tong){

//neu khong co mot duong di tu dinh v0 toi dich
8


// do phan khoi tao ta dat P[v]= v0 voi moi v
// se khong co update nen P[dich]=v0 do dai canh (v0, dich) = duong VC
// chi in ra nhung canh co do dai < duong VC

if (A[P[dich]][dich] < duongVC && dich != v0){
int truoc_dich = P[dich];
in_PA(A, P, v0, truoc_dich, tong + A[truoc_dich][dich]);
printf("((%d,%d) = %5.2f\n", truoc_dich, dich, A[truoc_dich][dich]);
}else
if (tong==0)
printf("khong co duong di tu %d den %d\n", v0, dich);
else
printf("tong do dai cac canh= %8.2f\n", tong);
}

int main(){
float A[size][size]; // ma tran trong so cua do thi
int n, v0=0, dich=0;
read_file("D://slide/SLIDE CTDLGT/dothi.txt", A, &n);
in_ma_tran(A,n);
int P[n]; // P[u] luu tru dinh dung truoc u trong duong di tu v0 den u

while (v0!=-1){
printf("\nNhap dinh NGUON v0 (tu 0 den %d; nhap -1 de ket thuc):", n-1);
scanf("%d", &v0);
if (v0>=0 && v0<= n-1){

9


Dijkstra(A, v0,n, P);
dich=0;
while (dich!=-1) {
printf("\nNhap dinh DICH v0 (tu 0 den %d; nhap -1 de chon
v0 khac):", n-1);
scanf ("%d", &dich);
if (dich>=0 && dich <= n-1){
printf("\nDuong di ngan nhat tu %d den %d la: \n", v0,
dich);
in_PA (A, P, v0, dich, 0.00);
}
}
in_ma_tran(A,n);
}
}
return 0;
}

10


KẾT LUẬN
Trong q trình nghiên cứu và hồn thiện bài thảo luận, nhóm chúng em đã làm rõ
các khái niệm chung về đồ thị, đường đi, đường đi ngắn nhất, cũng như ý tưởng và các
bước thực hiện thuật toán tìm đường đi ngắn nhất – Dijkstra, đưa ra chương trình minh họa
cho thuật tốn.
Qua bài thảo luận, nhóm chúng em đã hiểu rõ hơn về bài tốn tìm đường đi ngắn

nhất và ứng dụng của nó để giải quyết những khó khăn trong các vấn đề thực tế như tìm
khoảng cách đường đi ngắn nhất giữa hai địa điểm khác nhau, thiết kế mạng điện, mạng
lưới viễn thông,…
Tuy nhiên do chưa có nhiều kinh nghiệm cũng như những hạn chế về kiến thức nên
chắc chắn bài thảo luận sẽ khơng tránh khỏi những thiếu sót. Nhóm 7 chúng em rất mong
nhận được sự nhận xét, ý kiến đóng góp, phê bình từ phía thầy để bài thảo luận được hoàn
thiện hơn.

11


TÀI LIỆU THAM KHẢO
[1] Đỗ Xuân Lôi, Cấu trúc dữ liệu và giải thuật, Đại học Bách Khoa Hà Nội, xuất bản -1976
[2] Bài tốn tìm đường đi ngắn nhất với giải thuật Dijkstra (2022)
[3] Đồ thị (Lý thuyết đồ thị) – Wikipedia Tiếng Việt (2022)
[4] Các thuật toán về tìm đường đi ngắn nhất (2022)

12



×