• Trang chủ
  • Hỏi Đáp
  • Liên Hệ

HLink - Kênh Thông Tin Tổng Hợp Chính Thống

Bạn đang ở:Trang chủ / Hỏi Đáp / Thuật toán Prim tìm cây khung nhỏ nhất

Thuật toán Prim tìm cây khung nhỏ nhất

Tháng Chín 9, 2022 Tháng Chín 9, 2022 Chi Mỹ 0 Bình luận

Bài viết Thuật toán Prim tìm cây khung nhỏ nhất thuộc chủ đề về Hỏi & Đáp thời gian này đang được rất nhiều bạn quan tâm đúng không nào !! Hôm nay, Hãy cùng Hlink.Vn tìm hiểu Thuật toán Prim tìm cây khung nhỏ nhất trong bài viết hôm nay nhé ! Các bạn đang xem bài viết : “Thuật toán Prim tìm cây khung nhỏ nhất”

Đánh giá về Thuật toán Prim tìm cây khung nhỏ nhất


Xem nhanh
Đây là video chỉ mang tính chất tham khảo, nó chỉ là kinh nghiệm mình đúc kết được trong quá trình học tập và dĩ nhiên nó sẽ không chính xác tuyệt đối.
Mã giả thuật toán PRIM tại: https://dadv98.blogspot.com/2022/07/li-thuyet-o-thi.html
Đăng kí theo dõi kênh tại đây: https://bitly.com.vn/kd4Qz
Xem đầy đủ Playlist về Lí thuyết đồ thị tại: https://bitly.com.vn/iXzQ3

This entry is part 13 of 16 in the seriesCấu trúc dữ liệu

92 / 100

Thuật toán Prim (tiếng anh: Prim’s algorithm) là một thuật toán tham lam được sử dụng để tìm cây khung nhỏ nhất (Minimum Spanning Tree – MST) của một đồ thị liên thông có trọng số. Thuật toán được tìm ra vào năm 1975 và được đặt tên theo nhà nghiên cứu khoa học máy tính Robert C. Prim.

một vài thuật ngữ liên quan:

  • Spanning Tree : là cây khung của đồ thị liên thông và vô hướng, (Cho nên thuật toán này chỉ dùng cho đồ thị vô hướng).
  • Minimum Spanning Tree : là cây khung nhỏ nhất, (Có tổng trọng số của các cạnh là nhỏ nhất).

NỘI DUNG BÀI VIẾT

Ý tưởng thuật toán Prim

Thuật toán Prim sẽ bắt đầu bằng việc chọn ngẫu nhiên một đỉnh bất kì  và tiếp tục thêm các cạnh có trọng số nhỏ nhất cho đến khi có đủ tập hợp các đỉnh. Các bước để thực hiện:

  • Bước 1. Khởi tạo tập hợp đỉnh V rỗng, tập hợp cạnh E rỗng.
  • Bước 2. Chọn ngẫu nhiên 1 đỉnh và thêm vào tập hợp các đỉnh V.
  • Bước 3. Chọn 1 đỉnh chưa có trong tập V mà có liên kết với 1 đỉnh trong V, cạnh tạo từ 2 đỉnh đó phải là cạnh có trọng số nhỏ nhất và thêm vào tập hợp các cạnh E.
  • Bước 4. Lặp lại bước 3 cho đến khi cây khung hoàn thành (Cách nhận biết cây khung hoàn thành là tất cả các đỉnh của cây khung đều đặn đã xuất hiện trong V), cây khung nhỏ nhất là cây khung được tạo từ tập các cạnh trong E.

✅ Mọi người cũng xem : tình thương tiếng anh là gì

Ví dụ của thuật toán Prim

Nếu bạn cảm thấy chưa hiểu rõ thì đừng lo chúng ta sẽ đi vào phần ví dụ và hình ảnh chắc chắn bạn sẽ cảm thấy dễ hiểu hơn đấy.

Hãy quan sát ví dụ với cây khung đầy đủ dưới đây.

Thuật toán Prim(Prim’s Algorithm)

  • Có đồ thị G=(V, E) Có V đỉnh và E cạnh.
  • Tập hợp các đỉnh của đồ thị V = 1, 2, 3, 4, 5, 6 (Viết tắt của vertex nghĩa là đỉnh).
  • Tập hợp các cạnh của E = (1, 2), (1, 3), (1, 4), (2, 3), (2, 5), (3, 4), (3, 5), (3, 6), (4, 6), (5, 6) (Viết tắt của edge nghĩa là cạnh).
  • Ta tạo ra 2 tập hợp U và T, U là tập hợp các đỉnh và T là tập hợp các cạnh tạo ra cây khung nhỏ nhất.
  • Ban đầu U=Ø (rỗng) và T=Ø.

Bước 1. Khởi tạo

  • Ta tạo ra 2 tập hợp U và T, U là tập hợp các đỉnh và T là tập hợp các cạnh tạo ra cây khung nhỏ nhất.
  • Ban đầu U=Ø (rỗng) và T=Ø.

Bước 2. Chọn 1 đỉnh ngẫu nhiên từ cây khung trên, ví dụ chúng ta chọn đỉnh 1. Sau bước này, ta có U=1 và T=Ø.

Thuật toán Prim(Prim’s Algorithm)

Bước 3. Tìm tất cả các cạnh có 1 đỉnh ở trong U. Ở đây, ta sẽ tìm được cạnh (1, 3) do khoảng cách nhỏ nhất với tổng giá trị là 1. Sau bước này ta có U=1, 3 và T=(1, 3).

Thuật toán Prim(Prim’s Algorithm)

Bước 4. Tương tự bước 3, ta đi tìm cạnh nhỏ nhất có 1 đỉnh trong U mà cạnh đó chưa có trong V. Kết quả là ta tìm ra cạnh (3, 6) với giá trị 4. Sau bước này ta có U=1, 3, 6 và T=(1, 3), (3, 6).

Thuật toán Prim(Prim’s Algorithm)

Bước 5. Do tập U mới chỉ có 3/6 đỉnh, ta tiếp tục đi tìm cạnh nhỏ nhất chưa khám phá mà 1 đỉnh của nó trong U. Kết quả là ta tìm được cạnh (6, 4). Bây giờ U=1, 3, 6, 4 và T=(1, 3), (3, 6), (6, 4).

Thuật toán Prim(Prim’s Algorithm)

Bước 6. Do tập U mới chỉ có 4/6 đỉnh, tiếp tục tìm cạnh nhỏ nhất chưa xuất hiện trong T mà 1 đỉnh của nó trong U. Ta tìm được cạnh (3,2) với tổng giá trị 5. Sau buớc này U=1, 3, 6, 4, 2 và T=(1, 3), (3, 6), (6, 4), (3, 2).

Thuật toán Prim(Prim’s Algorithm)

Bước 7. Do tập U mới chỉ có 5/6 đỉnh, tiếp tục tìm cạnh nhỏ nhất chưa có trong T mà 1 đỉnh của nó trong U. Ta tìm được cạnh (2, 5) với giá trị 3. Lúc này tập U đã có 6/6 đỉnh nên thuật toán kết thúc.

Thuật toán Prim(Prim’s Algorithm) Cây khung nhỏ nhất mà chúng ta tìm được bằng thuật toán Prim.

Hình ảnh động dưới đây mô phỏng lại quy trình tìm kiếm cây khung nhỏ nhất cho ví dụ từng bước ở trên:

Thuật toán Prim(Prim’s Algorithm)

Sau khi áp dụng xong thuật toán Prim, ta có U=1, 3, 6, 4, 2, 5 và T=(1, 3), (3, 6), (6, 4), (3, 2), (2, 5).

  • Tập hợp các cạnh T=(1, 3), (3, 6), (6, 4), (3, 2), (2, 5) tạo thành cây khung có tổng trọng số nhỏ nhất. Tổng trọng số của cây khung nhỏ nhất là:1 + 4 + 2 + 5 + 3 = 15
Thuật toán Prim(Prim’s Algorithm) So sánh 2 cây khung (ban đầu, bên trái) và cây khung nhỏ nhất tìm được bằng thuật toán Prim (bên phải).

Code giải thuật Prim

Dưới đây là hàm chính thực thi giải thuật Prim biểu diễn đồ thi bằng ma trận kề, đi kèm với hướng dẫn bằng comment.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

intprims()

intcost[MAX][MAX];

intu,v,min_distance,distance[MAX],from[MAX];

intvisited[MAX],no_of_edges,i,min_cost,j;

//Tạo cost[][](giá trị) của ma trận

for(i=0;i<n;i++)

for(j=0;j<n;j++)

if(G[i][j]==0)

//Nếu trong cây khung không có cạnh nối giữa 2 điểm i, j(Là G[i][j]==0)

cost[i][j]=infinity;

//Thì gán tổng giá trị của cạnh i, j =infinity(Là 1 số cực lớn ở đây là 9999)

else

cost[i][j]=G[i][j];

//Nếu có cạnh nối giữa 2 điểm i, j thì gán giá trị của cạnh =G[i][j]

spanning[i][j]=0;

//Khởi tạo visited[],distance[] and from[]

distance[0]=0;

visited[0]=1;

for(i=1;i<n;i++)

distance[i]=cost[0][i];

from[i]=0;

visited[i]=0;

min_cost=0;//giá trị của cây khung

no_of_edges=n-1;//Số cạnh được thêm vào.

while(no_of_edges>0)

//Tìm đỉnh có khoảng cách nhỏ nhất đến cây

min_distance=infinity;

//Gán min_distance=infinity

for(i=1;i<n;i++)

if(visited[i]==0&&distance[i]<min_distance)

//Mục đích của việc gán min_distance=infinity là để xác nhận distance[i] khác 0

            

                v=i;

min_distance=distance[i];

u=from[v];

//Chèn cạnh vào cây khung

spanning[u][v]=distance[v];

spanning[v][u]=distance[v];

no_of_edges–;

visited[v]=1;

//Cập nhật distance[](khoảng cách) vào mảng

for(i=1;i<n;i++)

if(visited[i]==0&&cost[i][v]<distance[i])

            

                distance[i]=cost[i][v];

from[i]=v;

min_cost=min_cost+cost[u][v];

return(min_cost);

Full code thuật toán Prim

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

#include<stdio.h>

#define infinity 9999

#define MAX 20

intG[MAX][MAX],spanning[MAX][MAX],n;

intprims();

intReadMatrix(charfilepath[]);

voidOutputMatrix();

intReadMatrix(charfilepath[])

FILE*f=fopen(filepath,”r”);

if(f==NULL)

printf(“nCant open file”);

return0;

fscanf(f,”%d”,&n);

for(inti=0;i<n;i++)

for(intj=0;j<n;j++)

fscanf(f,”%d”,&G[i][j]);

fclose(f);

return1;

voidOutputMatrix()

printf(“Number of Vertices: %dn”,n);

for(inti=0;i<n;i++)

printf(“n”);

for(intj=0;j<n;j++)

printf(“%dt”,G[i][j]);

intmain()

inti,j,total_cost;

ReadMatrix(“Prim.txt”);

total_cost=prims();

printf(“nSpanning Tree Matrix:n”);

OutputMatrix();

printf(“nnTotal cost of spanning tree=%d”,total_cost);

return0;

intprims()

intcost[MAX][MAX];

intu,v,min_distance,distance[MAX],from[MAX];

intvisited[MAX],no_of_edges,i,min_cost,j;

for(i=0;i<n;i++)

for(j=0;j<n;j++)

if(G[i][j]==0)

cost[i][j]=infinity;

else

cost[i][j]=G[i][j];

spanning[i][j]=0;

distance[0]=0;

visited[0]=1;

for(i=1;i<n;i++)

distance[i]=cost[0][i];

from[i]=0;

visited[i]=0;

min_cost=0;//cost of spanning tree

no_of_edges=n-1;//no. of edges to be added

while(no_of_edges>0)

min_distance=infinity;

for(i=1;i<n;i++)

if(visited[i]==0&&distance[i]<min_distance)

            

                v=i;

min_distance=distance[i];

u=from[v];

spanning[u][v]=distance[v];

spanning[v][u]=distance[v];

no_of_edges–;

visited[v]=1;

for(i=1;i<n;i++)

if(visited[i]==0&&cost[i][v]<distance[i])

            

                distance[i]=cost[i][v];

from[i]=v;

min_cost=min_cost+cost[u][v];

return(min_cost);

Dữ liệu vào:

60 6 1 5 0 06 0 5 0 3 01 5 0 5 6 45 0 5 0 0 20 3 6 0 0 60 0 4 2 6 0

Lưu ý:

  • một số giáo trình hay một vài nơi sẽ ghi số 0 thành kí hiệu vô cùng.
  • Khi tạo file .txt thì nên bỏ chung cùng thư mục với bài làm để tránh sai sót không đáng có.

Kết quả thực thi của code theo ví dụ đầu vào phía trên:

1

2

3

4

5

6

7

8

9

10

11

12

Spanning Tree Matrix:

Number of Vertices:6

061500

605030

150564

505002

036006

004260

Total cost of spanning tree=15

✅ Mọi người cũng xem : học tập hiệu quả là gì

Độ phức tạp thuật toán

Cấu trúc dữ liệu tìm cạnh có trọng số nhỏ nhất Độ phức tạp
Tìm kiếm trên ma trận kề O(V2)
Đống nhị phân và danh sách kề O((V + E) log V) = O(E log V)
Đống Fibonacci và danh sách kề O(E + V log V)

Code cài đặt phía trên đang sử dụng tìm kiếm trên ma trận kề có độ phức tạp là O(V2). Bạn cũng có khả năng cài đặt lại thuật toán Prim sử dụng danh sách kề.

✅ Mọi người cũng xem : các bài tập kháng lực là gì

Ứng dụng của cây khung nhỏ nhất

Với bài toán tìm cây khung nhỏ nhất, chúng ta có khả năng áp dụng để giải quyết & tối ưu rất nhiều bài toán trong thực tế. Ví dụ với bài toán lắp đặt hệ thống mạng cho 1 trường học:

  • Tất cả các phòng cần có liên kết internet.
  • Biết trước khoảng cách giữa 2 phòng bất kỳ
  • Bài toán: Làm sao lắp đặt hệ thống mạng cho trường học này với chi phí tối thiếu (giả sử chi phí tỉ lệ thuận với khoảng cách).

Trên đây là nội dung bài viết về thuật toán Prim đi kèm code sử dụng ngôn ngữ C. Trong quy trình viết khó tránh khỏi sai sót , nếu có thắc mắc hay góp ý thì hãy bình luận bên dưới hoặc qua nhóm Lập Trình Không Khó để giải đáp thêm các thắc mắc các bạn vướng phải trong quá trình tìm hiểu.



Các câu hỏi về thuật toán prim là gì


Nếu có bắt kỳ câu hỏi thắc mắt nào vê thuật toán prim là gì hãy cho chúng mình biết nhé, mõi thắt mắt hay góp ý của các bạn sẽ giúp mình cải thiện hơn trong các bài sau nhé

Bài viết liên quan

Quá trình liền vết thương diễn ra thế nào?
Tiểu Thương Là Gì? Tầm ảnh Hưởng Của Tiểu Thương đến Nền Kinh Tế
Thương lục có độc, đừng nhầm lẫn với Nhân sâm – YouMed

Chuyên mục: Hỏi Đáp

Bài viết trước « Hướng dẫn kỹ thuật phông cầu (lốp cầu) trong cầu lông
Bài viết sau GDP là gì ? Viết tắt của từ nào? Cách tính GDP đầu người »

Reader Interactions

Trả lời Hủy

Email của bạn sẽ không được hiển thị công khai. Các trường bắt buộc được đánh dấu *

Sidebar chính

Sự thật về yêu quái khiến Tôn Ngộ Không “bó tay”, Phật Tổ “dè chừng”

12 tác dụng của tinh trùng cho sức khỏe, làn da và mái tóc – MarryBaby

Cùng học tiếng LaTinh với uTalk

13 sự thật về tinh dịch và tinh trùng: Thành phần, khối lượng

Hồ Tinh Bột Là Gì – Hồ Tinh Bột Gồm Những Gì

Kinh nghiệm dùng dầu dưỡng tóc hiệu quả và top 14 sản phẩm tốt

Tinh dầu hồi: Công dụng tuyệt vời đối với sức khỏe và đời sống

Recent Posts

  • Quá trình liền vết thương diễn ra thế nào?
  • Tiểu Thương Là Gì? Tầm ảnh Hưởng Của Tiểu Thương đến Nền Kinh Tế
  • Thương lục có độc, đừng nhầm lẫn với Nhân sâm – YouMed
  • Đặt câu với từ yêu nước thương nòi
  • Khi con tim bị tổn thương

Recent Comments

Không có bình luận nào để hiển thị.

Bản quyền © 2023 thuộc về HLink.Vn * Kênh Thông Tin Tổng Hợp Chính Thống