Thuật toán Prim

4 2.3K 37
Tài liệu đã được kiểm tra trùng lặp
Thuật toán Prim

Đang tải... (xem toàn văn)

Thông tin tài liệu

Thuật toán Prim

Một cách cài đặt tốt cho thuật toán PrimĐỗ Đức ĐôngTrongmục Algorithm+Data = Program ( Số 7/2003 ),bạnĐào Minh Đức có bài viết về tìm cây bao trùm ngắn nhất xung quanhhai thuật toán nổi tiếng Prim và Kruscal. Bạn có nói là hai thuật toántrên là không tối ưu, tôi không tán thành ý kiến của bạn. Theo tôi,từ thuật toán đến chương trình vẫn còn một khoảng cách, ta có côngthức nổi tiếng là Algorithm +Data = Program. Một thuật toán có nhiều cách cài đặt khác nhau tùy thuộc vào cách tổ chức dữ liệu. Thành công của thuật toán được đánh giá trên sự thành công của chương trình mô tả thuật toán. Tôi có một cách cài đặt thuật thuật toán Prim với độ phức tạp chỉ O(N2), và theo tôi thuật toán Prim là rất tốt. Tôi xin được nhắc lại thuật toánPrim cho đồ thị G trọng số vô hướng N đỉnh để bạn đọc tiện theodõi.Ta ký hiệu X là tập các đỉnh thuộccây, Y là các đỉnh của đồ thị chưa thuộc cây. S là tập cạnh thuộccây. C[u,v] là trọng số cạnh (u,v)Bước 1: Khởi tạo1.1. X={1}1.2. Y={2, ,N}1.3. S=ΦBước 2: Xây dựng câykhungWhile Y<>Φ doBegin2.1.Chọn u thuộc X, v thuộc Y sao cho C[u,v] là nhỏ nhất;2.2. X=X v {v};2.3. Y=Y {v};2.4. S=S v { (u,v) };End;Theothuật toán, ta nhận thấy rằng vòng lặp while sẽ lặp (N-1) lần, các lệnh2.2, 2.3, 2.4 chỉ cần mất O(1), còn 2.1 nếu làm ″thô″ thì sẽ phảimất O(N2) dẫn đến độ phức tạp là O(N3). ý đồ củatôi là nhằm giảm bước 2.1 này còn O(N) do đó độ phức tạp thuật toánchỉ còn O(N2). Để có được ý tưởng này là dựa vào tư tưởngcủa gán nhãn tìm đường đi ngắn nhất. ý tưởng này được thực hiệnbằng cách tổ chức thêm một mảng nhãn L và mảng ghi lại vết Pre. Haimảng này chỉ có ý nghĩa đối với các đỉnh thuộc Y, L[v] với v thuộcY cho biết nếu tại bước hiện hành muốn thêm đỉnh v vào X ta phải mấtít nhất L[v] bằng cách chọn cạnh (Pre[v], v). Do đó tại bước này(2.1) thay vì phải chọn 2 đỉnh u,v (u thuộc X, v thuộc Y) sao cho C[u,v]nhỏ nhất ta chỉ phải chọn 1 đỉnh v sao cho L[v] là nhỏ nhất. Như vậyý tưởng chính vẫn là chọn (u,v) nhưng độ phức tạp chỉ còn O(N) màthôi!Mộtvấn đề ta cần quan tâm là xây dựng mảng L, Pre:1. Khởi trị: Với X={1}, Y={2, ,N} thì L[k]=C[1,k]và Pre[k]=1 với k=2, ,N2. Sau mỗi bước thêm 1đỉnh vào X ta phải cập nhật lại 2 mảng này, bằng cách gán nhãn từđỉnh này tới các đỉnh thuộc YCôngviệc trên chỉ mất O(N). Như vậy độ phức tạp của chương trình chỉlà O(N2)Sauđây tôi xin viết chương trình hoàn chỉnh. {PRIM.PAS - Tim cay khung ngan nhat bang giaithuat PrimAuthor : Do Duc DongDate: 25-7-2003 }constMAX =100;fi ='input.txt';fo ='output.txt';typecanh =recordu,v:integer;end;varC :array[1 MAX,1 MAX]ofinteger;L,Pre :array[1 MAX]ofinteger;S :array[1 MAX-1]ofcanh;X,Y :array[1 MAX]ofbyte;N :integer;dem :integer;procedure docFile;var f:text;i,j:integer;beginassign(f,fi);reset(f);read(f,N);for i:=1 to N dofor j:=1 to N do read(f,C[i,j]);close(f);end;procedure khoiTri;var k:integer;begin{ X[u]=1 thi u thuoc X, X[u]=0 thi u khong thuoc X}fillchar(X,Sizeof(X),0);X[1]:=1;{Y[v]=1 thi v thuoc Y, Y[v]=0 thi v khong thuoc Y}fillchar(Y,Sizeof(Y),1);Y[1]:=0;dem:=0; { So canh thuoc S bang 0}{ khoi tri cho 2 mang L,Pre}for k:=2 to N dobeginL[k]:=C[1,k]; Pre[k]:=1;end;end;procedure lam;var u,v,k :integer;min:integer;beginwhile dembegin{ Chon canh u,v}min:=MAXINT;for k:=1 to N doif (Y[k]=1)and(min>L[k]) thenbeginv:=k;min:=L[v];end;u:=Pre[v];{ Loai v ra khoi Y}Y[v]:=0;{ Them v vao X}X[v]:=1;{Them canh (u,v) vao S}inc(dem);S[dem].u:=u;S[dem].v:=v;{Cap nhat lai mang L, Pre}for k:=1 to N doif (Y[k]=1)and(L[k]>C[v,k]) thenbeginL[k]:=C[v,k];Pre[k]:=v;end;end;end;procedure ghiFileKetQua;var f:text;k:integer;beginassign(f,fo);rewrite(f); for k:=1 to dem do writeln(f,S[k].u, #32, S[k].v);close(f);end;BEGINdocFile;khoiTri;lam;ghiFileKetQua;END.Cácbạn có thể thấy rằng 2 mảng X,Y có thể bỏ đi một vì ỹ nghĩa củachúng, song tôi vẫn cho vào với mục đích để cho rõ ràng. Bạn nàomuốn trao đổi thêm về vấn đề này, hãy liên hệ với tôi qua Email. . tả thuật toán. Tôi có một cách cài đặt thuật thuật toán Prim với độ phức tạp chỉ O(N2), và theo tôi thuật toán Prim là rất tốt. Tôi xin được nhắc lại thuật. quanhhai thuật toán nổi tiếng Prim và Kruscal. Bạn có nói là hai thuật toántrên là không tối ưu, tôi không tán thành ý kiến của bạn. Theo tôi,từ thuật toán đến

Ngày đăng: 11/09/2012, 15:24

Tài liệu cùng người dùng

Tài liệu liên quan