Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống
1
/ 38 trang
THÔNG TIN TÀI LIỆU
Thông tin cơ bản
Định dạng
Số trang
38
Dung lượng
643,5 KB
Nội dung
MỤC LỤC 2.1 Sơ đồ thuật toán Dijkstra kết hợp với Fibonacci Heap 20 MỞ ĐẦU Trong những năm gần các kỳ thi học sinh giỏi Quốc Gia, Quốc tế môn Tin học, có rất nhiều bài toán đòi hỏi học sinh phải ứng dụng các cấu trúc dữ liệu trừu tượng lập trình thì mới có thể giải quyết triệt để được các bài toán đó Heap là một những cấu trúc dữ liệu trừu tượng thế, nhiên có nhiều loại heap khác và độ phức tạp một số thao tác đối với chúng cũng có thể khác Trong tài liệu giáo khoa chuyên tin của các tác giả Đỗ Đức Đông, Nguyễn Thanh Hùng, Lê Minh Hoàng đã trình bày kỹ về binary heap, là tài liệu quý giúp ích rất nhiều cho các học sinh chuyên Tin của Việt Nam ta Qua nghiên cứu, tìm hiểu các tài liệu chúng nhận thấy còn một số loại heap nữa chưa có tài liệu nào nước đề cập đến một cách hoàn chỉnh Vì vậy đề tài này chúng sẽ trình bày về Fibonacci heap nhằm cung cấp thêm một sự lựa chọn cho các em học sinh chuyên Tin lập trình Chắc chắn đề tài không tránh khỏi những thiếu sót nhất định, rất mong nhận được những ý kiến đóng góp quý báu của các thầy cô, các em học sinh và các bạn độc giả • Ý nghĩa khoa học đề tài: Fibonacci heap ứng dụng để giải toán nghiên cứu lý thuyết thực tiễn Hiện cấu trúc dữ liệu chưa phổ biến Việt Nam, đề tài là một tài liệu có ích cho các em học sinh và người quan tâm có thêm công cụ mạnh để giải số toán có liên quan lập trình • Đề tài gồm có hai chương: - Chương trình bày về Fibonacci heap - Chương là phần ứng dụng Fibonacci heap vào việc cải tiến thuật toán Dijkstra giải bài toán tìm đường ngắn nhất đồ thị CHƯƠNG FIBONACCI HEAP 1.1 Tổng quan về cấu trúc liệu heap Ta dùng mảng danh sách móc nối để biểu diễn hàng đợi ưu tiên, thao tác Insert Update thực với độ phức tạp O(1), nhiên thao tác Find (Find max) Extract lại có độ phức tạp O(n) Vì vậy, thực tế người ta hay dùng cấu trúc liệu trừu tượng heap (đống) để biểu diễn hàng đợi ưu tiên Heap cấu trúc liệu trừu tượng, bao gồm tập n phần tử, phần tử có giá trị khóa xác định Các phép toán heap mô tả bảng : Make_ heap Trả heap rỗng Insert (x,h) Chèn giá phần tử x mới,có khóa xác định vào heap Find_ Trả phần tử có khóa nhỏ nhất, không làm thay đổi heap Extract_ Trả phần tử có khóa nhỏ xóa khỏi heap Trong số toán có thêm phép toán sau : Union(h1,h2) Hợp hai heap h1, h2 thành heap mới, đồng thời xóa h1, h2 Decrease(∆,x,h) Giảm khóa phần tử x lượng ∆ heap Delete(xh) Xóa phần tử X khỏi heap Heap gọi hàng đợi có độ ưu tiên (priority queue) hay đống khả trộn (mergeable heaps) Một số loại heaps, thời gian thao tác phép toán trình bày bảng [2]: Heaps Thao tác Linked Binary Bionimal Fibonacci Relax list make heap O(1) O(1) O(1) O(1) O(1) Insert (x,h) O(1) O(logN) O(logN) O(1) O(1) Find O(N) O(1) O(logN) O(1) O(1) extract O(N) O(logN) O(logN) O(logN) O(logN) Union(h1,h2) O(1) O(N) O(logN) O(1) O(1) O(1) O(logN) O(logN) O(1) O(1) O(N) O(logN) O(logN) O(logN) O(logN) Decrease(∆,x,h ) Delete(x,h) Trong phần nghiên cứu kỹ Fibonacci heap 1.2 Fibonacci heap 1.2.1 Giới thiệu Fibonacci heap (Đống Fibonacci) Cấu trúc liệu Fibonacci heap (Đống Fibonacci) hai giáo sư Fredman Tarjan đưa vào năm 1986, nhằm áp dụng vào toán tối ưu đồ thị, độ phức tạp thuật toán giải số toán điển hình sử dụng Fibonacci heap thống kê [2]: O(nlogn + m): Cho toán tìm đường tối ưu xuất phát từ đỉnh O(n2logn + nm): Cho toán tìm đường tối ưu cặp đỉnh O(n2logn + nm): Cho toán so khớp hai nhánh có trọng số Trước định nghĩa Fibonacci heap, ta đưa số khái niệm: Cây có gốc: Là tự mà có đỉnh phân biệt với đỉnh lại gọi gốc Cây có thứ tự: Là có gốc, mà nút trực thuộc nút cha xếp theo thứ tự xác định Cây xếp theo đống: Là có gốc, nút x nút có giá trị khóa lớn (nhỏ bằng) khóa cha Từ nút gốc nút có khóa nhỏ (lớn nhất) Định nghĩa : Fibonacci heap tập hợp xếp theo đống Các Fibonacci heap không bị ràng buộc thứ tự[2] Hình1.1: Fibonacci heap gồm xếp theo đống với 14 nút 1.2.2 Cấu trúc Fibonacci heap Hình 1.2 mô tả cách biểu diễn cấu trúc heap Mỗi nút x chứa biến trỏ p[x] trỏ đến cha biến trỏ child[x] trỏ đến Các x nối kết theo danh sách nối kết đôi theo vòng tròn mà ta gọi danh sách x Mỗi nút y danh sách có biến trỏ left[y] right[y] trỏ đến anh em ruột trái phải Nếu nút y left[y] = right[y] = y Thứ tự xuất nút danh sách tùy ý Việc thể danh sách danh sách nối đôi vòng tròn có ưu điểm: Thứ nhất, gỡ bỏ nút khỏi danh sách với độ phức tạp O(1) Thứ hai, ghép nối danh sách với độ phức tạp tính toán O(1) Ngoài nút x có : degree[x]: Lưu số nút danh sách x bool mark[x]: Kiểm tra x hay chưa kể từ lần cuối x trở thành nút khác Các gốc tất Fibonacci heap nối kết với biến trỏ left, right chúng tạo thành danh sách nối kết đôi vòng tròn gọi danh sách gốc Biến trỏ min[H] trỏ đến nút có khóa nhỏ danh sách gốc, từ ta coi min[H] đại diện H nói cách khác minH quản lý H Số lượng nút H lưu biến nH Hình 1.2: Mô cấu trúc Fibonacci heap Cấu trúc liệu miêu tả nút Fibonacci heap[1]: node = record key : integer; degree : integer; parent : ^node; child : ^node; left : ^node; right : ^node ; mark : boolean; end; Hàm tiềm Để phân tích đánh giá độ phức tạp phép toán Fibonacci heap ta sử dụng phương pháp phân tích tiềm năng, hao phí khấu trừ thuật toán xem độ phức tạp thuật toán [1] Đối với Fibonacci heap, ta sử dụng hàm tiềm Φ(H) = t(H) + 2m(H), đó: t(H) số lượng nút danh sách gốc, m(H) số lượng nút đánh dấu Ta mặc nhận trạng thái ban đầu Φ(H) = Ở ví dụ : Φ(H) = + × = 11 1.2.3 Các thao tác Fibonacci heap Ý tưởng thao tác Fibonacci heap trì hoãn công việc chưa cần thiết có thể, chờ đến lúc buộc phải thực thực lúc nhiều công việc, điều giúp giảm bớt phép tính toán Nếu số lượng Fibonacci heap không lớn, ta nhanh chóng xác định nút cực tiểu thủ tục EXTRACT_ MIN Ta không gắng thống Fibonacci heap chèn nút hợp hai đống Việc thống đống phải làm gặp thủ tục EXTRACT_MIN, thủ tục tìm nút cực tiểu xóa khỏi đống (1) Tạo Fibonacci heap Để tạo Fibonacci heap rỗng ta dùng thủ tục FIB_HEAP_ MAKE, thủ tục phân bổ trả đối tượng Fibonacci heap, n[H] = 0, min[H] = NIL, sau lời gọi thủ tục chưa có H Vì t(H) = 0, m(H) = 0, nên Φ(H) = Như vậy, mức hao phí khấu trừ (độ phức tạp tính toán) FIB_HEAP_MAKE với mức hao phí thực tế O(1) (2) Chèn nút Thủ tục chèn nút x với khóa key[x] vào Fibonacci heap H quản lý biến trỏ min[H]: Procedure FIB_HEAP_INSERT (var x, min[H] : tro); [1] // tro kiểu trỏ, trỏ vào node: tro = ^node; begin degree[x] := 0; p[x] := NIL; child[x] := NIL; left[x] := x; right[x] := x; mark[x] := false; ghép nối danh sách gốc chứa x với danh sách gốc H; if min[H] = NIL x^.key < minH^.key then minH := x; 10 n[H] = n[H]+1; end; Các lệnh từ dòng 1- 6, khởi tạo cấu trúc nút x, khiến trở thành danh sách nối đôi theo vòng tròn, dòng bổ sung nút x vào danh sách gốc H Như nút x trở thành nút đơn xếp theo đống Fibonacci heap Nó không đánh dấu Các dòng cập nhật min[H] Dòng 10 tăng số lượng nút H Có thể nhận FIB_HEAP_INSERT(c,min[H]) không gắng thống đống Nếu k phép toán FIB_HEAP_INSERT thực có k bổ sung vào danh sách gốc Hình 1.3: Minh họa chèn thêm nút có key 21 vào Fibonacci heap Để xác định mức hao phí khấu trừ FIB_HEAP_INSERT, gọi H Fibonacci heap ban đầu H’ Fibonacci heap kết quả, t(H’) = t(H)+1, m(H’) = m(H), gia tăng hàm tiềm : Φ(H’) - Φ(H) = Bởi mức hao phí thực tế O(1), nên mức hao phí khấu trừ O(1) + = O(1) Mã nguồn thao tác FIB_HEAP_INSERT: procedure FIB_HEAP_INSERT(var x, minH: tro); [1] begin degree[x] := 0; p[x] := NIL; child[x] := NIL; left[x] := x; right[x] := x; mark[x] := false; if minH nil // bắt đầu ghép nối danh sách gốc chứa x với danh sách gốc H; then begin x^.left := minH.left; minH^.left^.right := x; x^.right := minH; minH^.left := x; if minH^.key > x^.key then minH := x; end else minH := x; // kết thúc ghép nối danh sách gốc chứa x với danh sách gốc H; n[H] = n[H]+1; end; Ở nút x chèn vào bên trái minH, thực tế lập trình ta chèn x vào bên phải minH kết giống (3) Tìm nút cực tiểu Nút cực tiểu Fibonacci heap trỏ min[H], ta tìm nút cực tiểu với độ phức tạp tính toán thực tế (hao phí thực tế) O(1) Do tiềm H không thay đổi, nên mức hao phí khấu trừ phép toán với mức hao phí thực tế O(1) (4) Hợp hai Fibonacci heap [2] Thủ tục hợp Fibonacci heap H1 H2 thành H, đồng thời hủy H1, H2 procedure FIB_HEAP_UNION(var min[H1], min[H2], minH : tro); begin n[H] := 0; min[H] := min[H1]; ghép nối danh sách gốc H2 với danh sách gốc H; if (min[H1] = NIL) (min[H2]^.key < min[H1]^.key) then min[H] := min[H2]; n[H] := n[H1] + n[H2]; giải phóng đối tượng H1 H2; end; Các dòng 1-3 ghép nối danh sách gốc H1 H2 thành danh sách gốc H Các dòng 2, 4, ấn định nút cực tiểu H, dòng cập nhật lại số nút H Ta thấy thủ tục FIB-HEAP-UNION(H1, H2) không cần thực thống Sự thay đổi tiềm : Φ(H) – (Φ(H1) + Φ(H2)) = Do mức hao phí khấu trừ FIB_HEAP_UNION với mức hao phí thực tế O(1) (5) Trích nút cực tiểu[1] Đây thủ tục phức tạp Fibonacci heap Thủ tục thực xóa nút cực tiểu khỏi H, đồng thời thực việc thống bị trì hoãn phép toán khác 23 minH tham số hình thức (khi gọi thủ tục tham số hình thức phải thay biến tương ứng) Thủ tục FIB_HEAP_LINK(var y, x:tro): Biến gốc y (được trỏ trỏ y) làm gốc x (y x tham số hình thức) Thủ tục CUT(var minH, x, y : tro): Đưa nút x khỏi danh sách nút y, biến x thành gốc MinH, x, y tham số hình thức Thủ tục CASCADING_CUT(var minH, y : tro): Thủ tục cắt liên hoàn trình bày chương Thủ tục FIB_HEAP_DECREASE_KEY(var minH, x: tro; k: longint): Thủ tục thay x^.key giá trị nhỏ k, k nhỏ khóa nút y cha x cắt nhánh gốc x thủ tục CUT(x, y) Thủ tục Consolidate(var minH : tro): Thủ tục thống danh sách gốc, nghĩa ghép hai gốc có số thành gốc, việc lặp không tồn hai gốc có số nút Trong thủ tục này chúng đã chọn D(H) = log 2N +1 thay vì D(H) = log2N, lý là nếu chọn D(H) = log2N thì việc thống nhất các gốc heap của thủ tục này một số trường hợp sẽ bỏ sót mất một gốc (phải việc chứng minh degree[y] 3000 Test10 20000 400000 0.269 2.148 Tên test cột bảng thực chất tên thư mục chứa test đó, điều cần quan tâm thời gian chạy hai chương trình cột cột Số liệu bảng chứng minh tính ưu việt thuật toán Dijkstra Fibonacci heap so với thuật toán Dijkstra nguyên thủy Nhìn chung đồ thị thưa số đỉnh lớn thuật toán Dijkstra Fibonacci heap tỏ ưu việt so với thuật toán Dijkstra nguyên thủy Tuy nhiên số đỉnh có thuật toán Dijkstra nguyên thủy chạy lại nhanh (test01) Sở dĩ có tượng vì: Độ phức tạp thuật toán Dijkstra nguyên thủy O(N2) suy số phép tính toán thuật toán cỡ C1N2, độ phức tạp thuật toán Dijkstra Fibonacci heap O(Nlog N + M) 27 suy số phép tính toán thực tế thuật toán cỡ C2(Nlog N + M) với C1, C2 số Do Dijkstra Fibonacci heap phải thao tác với Fibonacci heap tương đối phức tạp nên thực tế C2 > C1 N nhỏ xảy trường hợp C1N2 < C2(Nlog N + M), điều xảy thuật toán Dijkstra nguyên thủy chạy nhanh 2.5 Kết luận chương Chương đề tài ứng dụng Fibonacci heap để cải tiến thuật toán Dijkstra giải toán tìm đường ngắn đồ thị, áp dụng Dijkstra Fibonacci heap hiệu nhiều so với áp dụng thuật toán Dijkstra nguyên thủy Trong trường hợp số đỉnh lớn đồ thị thưa chương trình áp dụng Dijkstra Fibonacci heap chạy nhanh hàng trăm lần 28 KẾT LUẬN Fibonacci heap là một cấu trúc dữ liệu trừu tượng tương đối mạnh, ứng dụng để cải tiến một số thuật toán Dijkstra, Kruskal, sắp xếp vun đống vv Điểm mấu chốt Fibonacci heap trì hoãn số thao tác chưa cần thực có thể, mục đích việc nhằm chờ đến lúc buộc phải thực công việc trì hoãn thực lúc nhiều công việc, điều giúp giảm bớt phép tính toán Mặt khác, số lượng Fibonacci heap không lớn nhanh chóng xác định nút cực tiểu thủ tục EXTRACT_MIN Đề tài ứng dụng Fibonacci heap vào việc cải tiến thuật toán Dijkstra tìm đường ngắn đồ thị, hiệu trình bày ở phần trên, chương trình chi tiết xin xem ở phần phụ lục Còn những ứng dụng khác của Fibonacci heap đã nêu ở chương xin dành để các em học sinh tự giải quyết là những bài tập Một lần nữa chúng rất mong nhận được những ý kiến đóng góp quý báu của các thầy cô giáo, các em học sinh và các độc giả Chúng xin chân thành cảm ơn 29 TÀI LIỆU THAM KHẢO Tiếng Anh [1] Thomas H Cormen, Charles E Leiserson, and Ronald L Rivest (1990), Introduction to Algorithms, Cambridge, Massachusetts [2] MIHAEL L FREDMAN, ROBERT ENDRE TARJAN (1987), Fibonacci Heaps and Their Uses in Improved Network Optimization Algorithms 30 PHỤ LỤC program Dijkstra_fiboHeap; uses crt; const maxN = 1000000; maxM=6000000; maxW=100000000; maxD = 1000000000; fi = 'dong.inp'; fo = 'dong.out'; type tro =^node; node = record sohieu,degree:longint;key:int64; parent,child,left,right:tro; mark:boolean; end; TAdjNode = record v:longint; w:int64; link:longint; end; //********************************************************************** var adj:array[1 maxM] of TAdjNode; a,d:array[0 maxN] of tro; head:array[1 maxN] of longint; trace: array[1 maxN] of longint; kq : array[1 maxn ] of longint; i,nH,n,m,s,t,dh,dem:longint; minH,u: tro; f : text; //************************************************************************ procedure Enter; var i,u:longint; begin assign(f,fi); reset(f); readln(f,n,m,s,t); FillChar(head,sizeOf(head),0); for i:= to m begin ReadLn(f,u,adj[i].v,adj[i].w); adj[i].link := head[u]; head[u]:= i; end; close(f); end; //************************************************************************ 31 procedure makeheap(var minH:tro;var nH:longint); //tạo đống rỗng quản lý bởi trỏ minH begin nH:= 0; minH := nil; end; //************************************************************************ procedure INSERT(var x,minH:tro); begin x^.degree := 0; x^.parent := NIL; x^.child := NIL; x^.left := x; x^.right := x; x^.mark := false; if minH nil then begin x^.right :=minH^.right; minH^.right^.left := x; minH^.right := x; x^.left := minH; end; if (minH = NIL ) or (x^.key < minH^.key) then minH := x; nH := nH+1; end; //************************************************************************ procedure Init; var v: longint; begin for v := to n begin new(d[v]); d[v]^.key := maxD; d[v]^.sohieu := v; end; d[s]^.key := 0; makeheap(minH, nH); for v:= to n insert(d[v], minH); //Tạo một heap gồm n gốc, các gốc đều chưa có dh := trunc(ln(n)/ln(2)) +1; end; //************************************************************************ procedure FIB_HEAP_LINK(var y,x:tro); var t:tro;dem,d: longint; 32 begin y^.right^.left := y^.left; y^.left^.right := y^.right; //sửa lại danh sách nối đôi kết nối các anh em của y y^.parent := x; // biến y thành của x if x^.child nil then begin if x^.child x^.child^.right then begin y^.right := x^.child^.right; x^.child^.right^.left := y; y^.left := x^.child; x^.child^.right := y; end else begin x^.child^.right := y; y^.left := x^.child; x^.child^.left := y; y^.right := x^.child; end; end else begin x^.child := y; y^.left := y; y^.right := y; end; x^.degree := x^.degree + 1; end; //*********************************************************************** procedure CUT(var minH,x,y:tro); var t: tro; begin X^.right^.left := x^.left; x^.left^.right := x^.right; y^.degree := y^.degree -1; if y^.degree = then y^.child := nil else y^.child := x^.right; if minH nil then begin x^.right := minH^.right; minH^.right^.left := x; minH^.right := x; x^.left := minH; 33 end else begin minH := x; minH^.right := minH; minH^.left := minH; end; x^.parent := NiL; x^.mark := FALSE; end; //************************************************************************ procedure CASCADING_CUT(var minH,y:tro); var z:tro; begin z := y^.parent; if z nil then begin if y^.mark = FALSE then y^.mark := TRUE else begin CUT(minH,y,z); CASCADING_CUT(minH,z); end; end; end; //************************************************************************ procedure FIB_HEAP_DECREASE_KEY(var minH,x:tro;k: longint); var y: tro; begin x^.key := k; y := x^.parent; if (y nil) and (x^.key < y^.key) then begin CUT(minH,x,y); CASCADING_CUT(minH,y); end; if (minH nil) and (x^.key < minH^.key) then minH := x; end; //************************************************************************ procedure consolidate(var minH:tro); var i,d: longint; 34 t1, w,x,y,tam: tro; begin for i := to dh A[i] := NIL; t1 := minH^.left; w:= minH; repeat x := w; d := x^.degree; w := w^.right; While A[d] NIL Begin Y := A[d]; if x^.key > y^.key then begin tam := x; x:= y; y:= tam; end; FIB_HEAP_LINK(y,x); A[d] := NIL; d := d+1; End; A[d] := x; until ( w = t1) ; // đến còn nhất gốc w = t1 chưa được xét để ghép với các //gốc khác cùng số nên phải xét tiếp để ghép gốc t1 nếu có thể x := w; d := x^.degree; While A[d] NIL Begin Y := A[d]; if x^.key > y^.key then begin tam := x; x:= y; y:= tam; end; FIB_HEAP_LINK(y,x); A[d] := NIL; d := d+1; end; a[d] := x; // xong việc xét ghép gốc t1 MinH := nil; // sau thống nhất các gốc thì MinH có thể không trỏ vào nút cực //tiểu nữa Vòng for dưới là nhằm để MinH trỏ vào nút cực tiểu For i := to DH If (A[i] NIL) then Begin if minH nil 35 then begin a[i]^.right := minH^.right; minH^.right^.left := a[i]; minH^.right := a[i]; a[i]^.left := minH; if (a[i]^.key < minH^.key) then minH := a[i]; end else begin MinH := a[i]; minH^.right := minH; minH^.left := minH; end; end; end; //************************************************************************ procedure FIB_HEAP_EXTRACT_MIN(var z : tro); var x,tam,tt,tam2: tro; tam1 :tro; i: longint; begin z := minH; nH := nH - 1; x:= z^.child; if x nil then begin tam := x;tam^.parent := nil; while(tam^.right x) begin tam := tam^.right; tam^.parent := nil; end; x^.left^.right := minH^.right; minH^.right^.left := x^.left; minH^.right := x; x^.left := minH; end; z^.right^.left := z^.left; z^.left^.right := Z^.right; if z = z^.right then minH := NIL else minH := z^.right; if (minH nil) and (minH minH^.right) then Consolidate(minH); end; 36 //********************************************************************** function Relax(u, v: longint; w: longint): Boolean; var result:boolean; begin Result := d[v]^.key > (d[u]^.key + w); if Result then trace[v] := u; exit(result); end; //************************************************************************ procedure Dijkstra; var j,i: longint;tt,tam, ta:tro; begin repeat FIB_HEAP_EXTRACT_MIN(u); if (u^.sohieu = t) then Break; i := head[u^.sohieu]; while i begin if Relax(u^.sohieu, adj[i].v, adj[i].w) then FIB_HEAP_DECREASE_KEY(minH,d[adj[i].v],d[u^.sohieu]^.key+adj[i].w); i := adj[i].link; end; until (nh = 1); end; ************************************************************************* procedure PrintResult; var i : longint; begin assign(f,fo); rewrite(f); if d[t]^.key = maxD then WriteLn(f,'There is no path from ', s, ' to ', t) else begin WriteLn(f,d[t]^.key); dem := 0; while t s begin inc(dem); kq[dem] := t; t := trace[t]; end; 37 inc(dem); kq[dem] := s; end; for i:= dem downto write(f,kq[i],' '); close(f); end; ************************************************************************* BEGIN Enter; Init; dijkstra; PrintResult; END ************************************************************** [...]... đề tài đã ứng dụng Fibonacci heap để cải tiến thuật toán Dijkstra giải bài toán tìm đường đi ngắn nhất trên đồ thị, khi áp dụng Dijkstra Fibonacci heap thì hiệu quả hơn rất nhiều so với khi áp dụng thuật toán Dijkstra nguyên thủy Trong trường hợp số đỉnh lớn và đồ thị thưa chương trình áp dụng Dijkstra Fibonacci heap có thể chạy nhanh hơn hàng trăm lần 28 KẾT LUẬN Fibonacci heap là một cấu... khóa nào là -∞ trong Fibonacci heap 19 procedure FIB _HEAP_ DELETE(var minH, x : tro); begin 1 FIB _HEAP_ DECREASE_KEY(minH, x, - ∞); 2 FIB _HEAP_ EXTRACT_MIN(minH); end; FIB _HEAP_ DELETE(H, x) biến nút x thành nút cực tiểu bằng cách gán cho nó khóa - ∞ thông qua thủ tục FIB _HEAP_ DECREASE_KEY, sau đó loại nó ra khỏi Fibonacci heap bằng thủ tục FIB _HEAP_ EXTRACT_MIN Chi phí khấu trừ của FIB _HEAP_ DELETE là tổng... với heap nhưng Fibonacci heap vẫn chưa được nhiều người lập trình sử dụng, lý do là vì để cài đặt Fibonacci heap chúng ta phải dùng danh sách móc nối và nói chung là việc cài đặt phức tạp hơn Tuy nhiên trong trường hợp không bị giới hạn về thời gian lập trình và cần xử lý những đồ thị thưa, ta có thể dùng Fibonacci heap để tăng thêm hiệu quả của thuật toán Chương 2 của đề tài sẽ ứng dụng Fibonacci. .. lượng các cây trong một Fibonacci heap không lớn thì có thể nhanh chóng xác định nút cực tiểu mới bằng thủ tục EXTRACT_MIN Đề tài đã ứng dụng Fibonacci heap vào việc cải tiến thuật toán Dijkstra tìm đường đi ngắn nhất trên đồ thị, hiệu quả của nó đã được trình bày ở phần trên, chương trình chi tiết xin xem ở phần phụ lục Còn những ứng dụng khác của Fibonacci heap như đã nêu ở chương... Công việc còn lại chỉ là thực hiện cập nhật nút minH được thực hiện trong các dòng từ 16 – 23 Hình 1.4 dưới đây mô tả hoạt động của FIB _HEAP_ EXTRACT_MIN, quá trình biến đổi của Fibonacci heap được giải thích như sau: (a) Một Fibonacci heap (b) Trạng thái Fibonacci heap khi gỡ bỏ nút cực tiểu z ra khỏi danh sách gốc và bổ sung con của nó vào danh sách gốc (c) - (e) Mảng A và các cây trong 3 lần lặp... heap để tăng thêm hiệu quả của thuật toán Chương 2 của đề tài sẽ ứng dụng Fibonacci heap vào việc cải tiến thuật toán Dijkstra giải bài toán tìm đường đi ngắn nhất trên đồ thị 20 CHƯƠNG 2 ỨNG DỤNG FIBONACCI HEAP CẢI TIẾN THUẬT TOÁN DIJKSTRA 2.1 Sơ đồ thuật toán Dijkstra kết hợp với Fibonacci Heap Sơ đồ thuật toán Dijkstra nguyên thủy với độ phức tạp O(n2) như sau: procedure dijkstra;... minH:tro): Thủ tục này chèn một nút mới được trỏ bởi con trỏ x vào Fibonacci heap được trỏ bởi minH Trong thủ tục này x 23 và minH đều là các tham số hình thức (khi gọi thủ tục thì tham số hình thức phải thay bằng các biến tương ứng) Thủ tục FIB _HEAP_ LINK(var y, x:tro): Biến gốc y (được trỏ bởi con trỏ y) làm con của gốc x (y và x đều là các tham số hình thức) Thủ tục CUT(var minH, x, y : tro): Đưa... nguyên thủy là O(N2) suy ra số phép tính toán của thuật toán này cỡ C1N2, độ phức tạp của thuật toán Dijkstra Fibonacci heap là O(Nlog N + M) 27 suy ra số phép tính toán thực tế của thuật toán là cỡ C2(Nlog N + M) với C1, C2 là các hằng số Do Dijkstra Fibonacci heap phải thao tác với Fibonacci heap tương đối phức tạp nên thực tế C2 > C1 vì thế khi N nhỏ có thể xảy ra trường hợp C1N2 < C2(Nlog N + M),... rút gọn các cây trong Fibonacci heap gọi là thống nhất Fibonacci heap Điều này được thực hiện bằng thủ tục CONSOLIDATE Nguyên tắc làm việc của thủ tục CONSOLIDATE: (1) Tìm hai gốc x, y có cùng số nút con trong danh sách con, và key[x] ≤ key[y] 11 (2) Gỡ bỏ y ra khỏi danh sách gốc, cho y làm con của x Việc này sẽ được thực hiện bởi thủ tục FIB _HEAP_ LINK Thủ tục CONSOLIDATE sử dụng thêm một mảng phụ... Bây giờ chúng ta sẽ tổ chức mảng nhãn d theo cấu trúc Fibonacci heap, khi đó mô hình thuật toán Dijkstra có thể viết lại như sau: procedure dijkstra_fibo _heap; // input: Đồ thị G, đống H S, t là các biến toàn cục // output: Khoảng cách từ s đến t begin Repeat P := FIB _HEAP_ EXTRACT_MIN(H); u := p^ u; // u là một trường mới của các nút trong Fibonacci heap để lưu nhãn //của đinh (tên đỉnh) mà nút đại diện ... cứu kỹ Fibonacci heap 1.2 Fibonacci heap 1.2.1 Giới thiệu Fibonacci heap (Đống Fibonacci) Cấu trúc liệu Fibonacci heap (Đống Fibonacci) hai giáo sư Fredman Tarjan đưa vào năm 1986, nhằm áp dụng. .. nhất) Định nghĩa : Fibonacci heap tập hợp xếp theo đống Các Fibonacci heap không bị ràng buộc thứ tự[2] Hình1.1: Fibonacci heap gồm xếp theo đống với 14 nút 1.2.2 Cấu trúc Fibonacci heap Hình 1.2... tìm nút cực tiểu xóa khỏi đống (1) Tạo Fibonacci heap Để tạo Fibonacci heap rỗng ta dùng thủ tục FIB _HEAP_ MAKE, thủ tục phân bổ trả đối tượng Fibonacci heap, n[H] = 0, min[H] = NIL, sau lời gọi