1. Trang chủ
  2. » Luận Văn - Báo Cáo

CẤU TRÚC HEAP và ỨNG DỤNG

25 1,8K 3

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

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 25
Dung lượng 172,5 KB

Nội dung

Mục đích của heap trong các bài các bài toán tin là ta có thể truy xuất phần tử lớn nhất hay nhỏ nhất có trong một mảng lưu trữ hiện tại.. Đống có vai trò quan trọng trong nhiều thuật t

Trang 1

CẤU TRÚC HEAP VÀ ỨNG DỤNG

I LỜI NÓI ĐẦU

Có thể nói Heap là 1 cấu trúc hữu dụng vào bậc nhất trong giải toán Trong khoa học máy tính, đống (tiếng Anh: heap) là một cấu trúc dữ liệu dựa trên cây thỏa mãn tính chất đống: nếu B là nút con của A thì khóa(A)≥khóa(B) (HEAP MAX) Một hệ quả của tính chất này là khóa lớn nhất luôn nằm ở nút gốc Do đó một đống như vậy thường được gọi là đống-max Nếu mọi phép so sánh bị đảo ngược khiến cho khóa nhỏ nhất luôn nằm ở nút gốc thì đống đó gọi là đống-min Thông thường mỗi nút có không quá hai nút con Mục đích của heap trong các bài các bài toán tin là

ta có thể truy xuất phần tử lớn nhất hay nhỏ nhất có trong một mảng lưu trữ hiện tại

Do đó có 2 loại là heap_max và heap_min Đống là một cách thực hiện kiểu dữ liệu trừu tượng mang tên hàng đợi ưu tiên Đống có vai trò quan trọng trong nhiều thuật toán

Một số ứng dụng của Heap:

+ Heapsort: Một trong những phương pháp sắp xếp tại chỗ tốt nhất

+ Thuật toán lựa chọn: có thể sử dụng đống để tìm phần tử lớn nhất, nhỏ nhất, trung

vị, phần tử lớn thứ k, trong thời gian tuyến tính.

+ Thuật toán cho đồ thị: nhiều thuật toán cho đồ thị sử dụng cấu trúc dữ liệu đống chẳng hạn như thuật toán Dijkstra, hay thuật toán Prim.

Các thao tác thường gặp trên đống là:

+ Tìm-max (tìm-min): tìm khóa lớn nhất trong đống-max (tìm khóa nhỏ nhất trong đống-min).

+ Xóa-max (xóa-min): xóa nút gốc của đống-max (đống-min)

+ tăng-khóa (giảm-khóa): thay đổi giá trị một khóa trong đống-max (đống-min)

+ chèn: chèn thêm một khóa mới vào đống

+ hợp: hợp hai đống lại thành một đống mới chứa tất cả các khóa của cả hai

II CẤU TRÚC HEAP

Trang 2

Heap được biểu diễn bằng cây nhị phân, nút k trên cây sẽ có hai nút con là 2*k

và 2*k+1, có cha là k div 2 Heap[k] tùy theo loại heap mà nó lớn hơn con nó hay cha

nó Mỗi khi ta thay đổi một phần tử bất kì trong heap thì ta sẽ cập nhật lại heap trong khoảng thời gian log n Có hai thao tác đối với heap là upheap và downheap

Heap sẽ cần biến nh để quản lí số lượng phần tử của heap.

Ví dụ với HEAP MAX

Các thao tác thường dùng trong xử lý HEAP:

- Up_heap: nếu 1 nút lớn hơn cha của nó thì di chuyển nó lên trên

- Down_heap: nếu 1 phần tử nhỏ hơn 1 con của nó thì di chuyển nó xuống dưới

- Push: đưa 1 phần tử vào HEAP bằng cách thêm 1 nút vào cây và up_heap nút đó

- Del: loại 1 phần tử khỏi HEAP bằng cách chuyển nó xuống cuối heap và loại bỏ, sau đó chỉnh sửa lại heap sao cho thoả mãn các điều kiện của HEAP.

Trong code x là vị trí, a là giá trị, nh là số phần tử, pa là cha của x, c là con của

if(c > nh)return; // không có con thì thoát

if(c < nh and heap[c+1] > heap[c]) c++;

// n u nó còn con 2 thì ch n con l n ế ọ ớ để khi kéo nó

// lên đảm b o th ng này lúc làm cha s l n h nả ằ ẽ ớ ơ

Trang 3

// th ng con không ằ được làm cha

if(heap[x] < heap[c]){ // n u kéo ế được thì kéo

Heap được sử dụng trong thuật toán Dijkstra, Kruskal, Heap Sort nhằm giảm

độ phức tạp thuật toán Heap còn có thể sử dụng trong các bài toán dãy số, QHĐ, đồ thị Với những ví dụ sau ta sẽ thấy phần nào sự đa dạng và linh hoạt trong sử dụng Heap

III BÀI TẬP ỨNG DỤNG CẤU TRÚC HEAP

1 KMIN http://vn.spoj.com/problems/KMIN

Ý tưởng: Ban đầu sort không giảm hai dãy a,b Cho a[1] + b[i] với i = 1 -> n vào 1 heap_min Duyệt k lần , mỗi lần lấy gốc ra rồi cho a[i+1] + b[j] vào với i, j là vị trí của nút vừa lấy ra, nếu i = n thì thôi.

1 const fi='';

2 fo='';

3 type mang=array[ 50000] of longint;

4 sum=record i, j: longint; end;

16 for i:=1 to m do readln(f, a[ ]);

17 for i:=1 to n do readln(f, b[ ]);

18 close( )

19 end;

20 }

Trang 4

{ -21 function cmp(x, y: sum): boolean;

23 exit( [x.i +b[x.j >=a[y.i +b[y.j]);

24 end;

25 -}

{ -26 procedure swap(i, j: longint)

45 if j>top then exit;

46 if j<top) and cmp(heap[ ], heap[j+1]) then inc( )

47 if not cmp(heap[ ], heap[ ]) then swap(i, j)

48 downheap( )

49 end;

50 }

{ -51 procedure push(x: longint)

65 procedure sort(var x: mang; L, H: longint)

66 var i, j, key, tg: longint;

73 while x[ ]<key do inc( )

74 while x[ ]>key do dec( )

75 if i<=j then

76 begin

Trang 6

2 HEAP1 http://vn.spoj.com/problems/HEAP1

Ý tưởng: Đẩy vào heap_min , lặp n-1 lần, mỗi lần lấy hai thằng gốc và đẩy tổng hai

thằng này vào, tăng res lên hai thằng này, tức là lấy thằng gốc rồi del(1) rồi lại lấy thằng gốc rồi lại del(1), xong rồi push(x+y) vào.

28 if j>top then exit;

29 if j<top) and ( [ ]>a[j+1]) then inc( )

30 if a[ ]>a[ ] then swap(i, j)

31 downheap( )

32 end;

33 }

{ -34 procedure push(x: longint)

Trang 7

Ý tưởng: Mỗi lần “+”V thì đẩy phần tử V vào heap bằng thủ tục Push Thao tác

“-” : Nếu danh sách đang không rỗng thì thao tác này loại bỏ tất cả các phần tử lớn

nhất của danh sách bằng thủ tục Del đến khi nào đầu heap nhỏ hơn Max hiện tại.

Trang 8

26 if j>top then exit;

27 if j<top) and ( [ ]<a[j+1]) then inc( )

28 if a[ ]<a[ ] then swap(i, j)

29 downheap( )

30 end;

31 }

{ -32 procedure push(x: longint)

Trang 9

96 for i:=n-1 downto do

97 if a[ ]<>a[i+1 then write(f, a[ ], ' ')

Ý tưởng: Dùng 2 heap, 1 heap (HA) lưu các phần tử từ thứ 1 tới N div 2 và heap còn

lại (HB) lưu các phần tử từ N div 2 +1 tới N sau khi đã sort lại tập thành tăng dần

HA là Heap-max còn HB là Heap-min Như vậy phần tử trung vị luôn là gốc HB (N lẻ) hoặc gốc của cả HA và HB (n chẵn) Thao tác MEDIAN do đó chỉ có độ phức tạp O(1) Còn thao tác PUSH sẽ được làm trong O(logN)

- Nếu gtr đưa vào nhỏ hơn hoặc bằng HA[1] đưa vào HA ngược lại đưa vào HB Số phần tử N của tập tăng lên 1.

- Nếu HA có lớn hơn (/nhỏ hơn N) div 2 phần tử thì POP 1 phần tử từ HA (/HB) đưa vào heap còn lại Sau quá trình trên thì HA và HB vẫn đảm bảo đúng theo định nghĩa ban đầu Bài toán được giải quyết với độ phức tạp O(MlogM).

1 //uses sysutils;

Trang 10

10 heapa, heapb: heap;

11 n, k, seed, add, topa, topb: longint;

36 if j>topa then exit;

37 if j<topa) and (heapa[ ] gt<heapa[j+1 gt) then inc( )

38 if heapa[ ] gt>=heapa[ ] gt then exit;

39 swapa(i, j)

40 downheapa( )

41 end;

42 }

{ -43 procedure pusha(i: longint)

53 heapa[ ]:=heapa[topa]

54 pos[heapa[ ] vt]:=i;

Trang 11

60 procedure swapb(i, j: longint)

66 pos[heapb[ ] vt]:=i+(k+1 div ;

67 pos[heapb[ ] vt]:=j+(k+1 div ;

81 if j>topb then exit;

82 if j<topb) and (heapb[ ] gt>heapb[j+1 gt) then inc( )

83 if heapb[ ] gt<=heapb[ ] gt then exit;

84 swapb(i, j)

85 downheapb( )

86 end;

87 }

{ -88 procedure pushb(i: longint)

90 inc(topb)

91 heapb[topb]:=a[ ]

92 pos[ [ ] vt]:=topb+(k+1 div ;

98 heapb[ ]:=heapb[topb]

99 pos[heapb[ ] vt]:=i+(k+1 div ;

115 while a[ ] gt<key do inc( )

116 while a[ ] gt>key do dec( )

117 if i<=j then

Trang 12

155 heapa[ ]:=a[(k+1 div + -i]

156 pos[ [(k+1 div + -i] vt]:=i;

168 if pos[ ]<=(k+1 div then popa(pos[ ])

169 else popb(pos[ ] (k+1 div )

170 if i=n-k+1 then break;

171 {a[i+k].vt:=i+k;

172 a[i+k].gt:=(a[i+k-1].gt*mul+add) mod 6 55 36; }

173 if a[i+k] gt<=heapa[ ] gt then pusha(i+k)

174 else pushb(i+k)

175 if topb>k-(k+1 div then

176 begin

Trang 13

177 inc(topa)

178 heapa[topa]:=heapb[ ]

179 pos[heapa[topa] vt]:=topa;

186 heapb[topb]:=heapa[ ]

187 pos[heapb[topb] vt]:=topb+(k+1 div ;

Ý tưởng: Đầu tiên ta sắp xếp lại thứ tự thời gian của các cuộc ném bóng Bài này

ta dùng 3 heap với các ý nghĩa như sau: 1 heap min, 1 heap max lưu chỉ sô các lỗ còn trống, 1 heap quản lí các ô đang có bóng xoáy ở trên, heap này là 1 heap min với giá trị khóa là thời gian quả bong rơi xống lỗ Đầu tiên 2 heap min và max đầy (tât cả các ô còn trông) Cho 1 vòng for qua các thứ tự ném, đến 1 lượt ta phải làm

2 việc sau:

1: Loại bỏ từ Heap quản lí các ô có bóng những ô nào có thời gian rơi xuống lỗ ≤ thời gian ném bóng của lượt này, sau đó thêm vào heap min và heap max những ô tìm được những ô này lần lượt lấy ra từ heap quản lý.

Trang 14

2: Thực hiện ném: nếu từ bên trái thì dựa vào heap min để tìm ô trống có chỉ số nhỏ nhất, nếu ném bên phải thì ngược lại Khi tìm được thì loại bỏ khỏi 2 heap này phần tử tìm được, thêm phần tử vào heap quản lý gồm 2 thông tin chỉ số của lỗ và thời gian rơi xuống lỗ Cứ làm như thế cho đến khi hết bóng hoặc không còn lỗ nào trống thì dừng lại Chú ý cần phải lưu số hiệu các ô trong hai heap để tiện cho việc loại bỏ.

16 a : array [1 mmax] of lannem;

17 hmi, hma: array [1 mmax] of longint;

18 hql : array [1 mmax] of longint;

19 vti, vta: array [1 mmax] of longint;

20 vthql : array [1 mmax] of longint;

21 d : array [1 mmax] of longint;

22 bb : array [1 mmax] of longint;

Trang 15

46 procedure readf; inline;

Trang 19

330 a_nem(a[i] time, a[i] xoay, i);

331 if not hoa then

Trang 20

341 inc(slB);

342 b_nem(a[i] time, a[i] xoay, i);

343 if not hoa then

370 if a[i] ten= 'A' then

371 writeln(g, 'Alice takes the hole: ', bb[i]);

372 if a[i] ten= 'B' then

373 writeln(g, 'Bob takes the hole: ', bb[i]);

381 writeln(g, 'Alice loses at her turn: ', slA);

382 writeln(g, 'Game lasts: ', tc,' minute(s)');

Ý tưởng: Dùng thuật toán MORE: Sắp xếp các công việc theo thời điểm cuối thực

hiện công việc Thực hiện vòng lặp Xét các công việc cho đến khi gặp công việc

Trang 21

quá hạn: i Tìm trong dãy các việc đã sắp xếp thì dùng heap lấy ra công việc có thời thực hiện lớn nhất trong các công việc trước đó và pop ra khỏi heap, loại bỏ công việc j có thời gian làm lâu nhất Nếu ko có i thì dừng vòng lặp Kết hợp dùng cấu trúc HEAP độ phức tạp của bài toán là O(n log n)

12 d, p, cs: array [1 mmax ] of longint;

13 h : array [1 mmax ] of key;

14 dau : array [1 mmax ] of boolean;

22 assign(f, fi); reset(f);

23 assign(g, fo); rewrite(g);

Trang 24

+ Lấy ra nhanh chóng các phần tử lớn nhất (hoặc nhỏ nhất) của một dãy.

+ Khá tốt để sắp xếp những dãy có số lượng phần tử lớn trong mộtthời gian ngắn + Cho phép tích lũy các thông tin dần dần trong quá trình sắp xếp.

Chuyên đề chỉ dừng lại giới thiệu được một số ít các bài tập với Heap, còn rất nhiều bài tập khác ứng dụng heap mà chuyên đề này chưa nhắc tới Thời gian viết chuyên đê có hạn, không tránh khỏi sai sót, rất mong được sự góp ý của thầy cô và các em học sinh

Trang 25

V TÀI LIỆU THAM KHẢO

1 Giải thuật và lập trình – T.S Lê Minh Hoàng – ĐHSP Hà Nội

2 Website: www vnoi.info

3 Một số vấn đề đáng chú ý trong môn tin học – Phan Công Minh

4 Cấu trúc heap – doraemonvodanh

Ngày đăng: 14/10/2015, 14:01

TỪ KHÓA LIÊN QUAN

TÀI LIỆU CÙNG NGƯỜI DÙNG

TÀI LIỆU LIÊN QUAN

w