Thông tin tài liệu
MỤC LỤC I Khái niệm II Các thao tác thường dùng Heap Max Khai báo 2 UpHeap DownHeap Push Pop Dijkstra Heap .5 III Một số tập ứng dụng Bài tập 1: Heapuri Bài tập 2: Thả xốp Bài tập 3: PILOT 10 Bài tập 4: Tiểu thuyết trinh thám 13 Bài tập 5: Cezar 18 Bài tập 6: Toy Cars .22 Bài tập 7: BASE3 .26 IV Một số tập vận dụng 30 Bài tập 1: BOCSOI13 30 Bài tập 2: Kế hoạch làm .30 10 Bài tập 3: CATUN 31 11 Bài tập 3: Barbar 32 12 Bài tập 4: Cầu cảng 32 13 Bài tập 5: K TỔNG BÉ NHẤT 33 14 Bài tập 6: BINLADEN .34 BINLADEN.INP 34 BINLADEN.OUT 34 V Tài liệu tham khảo 34 CHUYÊN ĐỀ: CẤU TRÚC DỮ LIỆU HEAP I Khái niệm Heap cấu trúc liệu đặc biệt quan trọng, giúp ta giải nhiều tốn thời gian cho phép Độ phức tạp thông thường làm việc với Heap là O(logN) Heap thực chất cân thỏa mãn điều kiện sau: Một nút có khơng q nút Với Heap Max nút gốc nút lớn nhất, nút không lớn nút cha Với Heap Min ngược lại Mặc dù mơ tả Heap biểu diễn mảng Nút nút i là 2*i và 2*i+1 Do Heap cân nên độ cao nút luôn nHeap then exit; // Nếu i khơng có nút khơng làm việc if (j < nHeap) and (Heap[j] < Heap[j+1]) then Inc(j); // Nếu i có nút chọn nút ưu tiên if Heap[i] < Heap[j] then // Nếu nút cha nhỏ nút begin swap(Heap[i] , Heap[j]); // Đổi chỗ phần tử Heap DownHeap(j); // Tiếp tục di chuyển xuống end; end; Push Đưa phần tử vào Heap: Thêm nút vào cuối Heap tiến hành UpHeap từ đây: Procedure Push(x : LongInt); Begin Inc(nHeap); // Tăng số phần tử Heap Heap[nHeap] := x; // Thêm x vào Heap UpHeap(nHeap); End; Pop Rút phần tử vị trí v trong Heap: Gán Heap[v] := Heap[nHeap] rồi tiến hành chỉnh lại Heap: Function Pop(v : LongInt) : LongInt; Begin Pop := Heap[v]; // Lấy phần tử vị trí v khỏi Heap Heap[v] := Heap[nHeap]; // Đưa phần tử cuối Heap vào vị trí v Dec(nHeap); // Giảm số phần tử Heap {Chỉnh lại Heap} UpHeap(v); DownHeap(v); End; Ngồi ra, sử dụng thuật tốn Dijkstra/Prim kết hợp cấu trúc Heap, bạn cịn sử dụng cách Push Pop khác thuận lợi so với cách trình bày trên: Dijkstra Heap 1/ Update – Dijkstra: Procedure Update(v : LongInt); // Đỉnh v vừa sửa nhãn, cần chỉnh lại Heap var child , parent : LongInt; begin child := pos[v]; // child vị trí đỉnh v Heap if child = then // Nếu đỉnh v chưa có Heap begin Inc(nHeap); // Tăng số phần tử Heap child := nHeap; // Đưa v vào cuối Heap end; parent := child div 2; // parent nút cha child while (parent > 0) and (d[Heap[parent]] > d[v]) do // Nếu đỉnh nút parent ưu tiên v bị “kéo xuống” nút child begin Heap[child] := Heap[parent]; // Đẩy đỉnh lưu nút cha xuống nút pos[Heap[child]] := child; // Ghi nhận lại vị trí đỉnh child := parent; // Tiếp tục di chuyển lên parent := child div 2; end; Heap[child] := v; // Thao tác “kéo xuống” tạo ô trống nút child để đặt v vào pos[v] := child; // Ghi nhận vị trí đỉnh v Heap end; 2/ Pop – Dijkstra: Function Pop : LongInt; // Lấy từ Heap đỉnh có nhãn tự nhỏ var r , v , c : LongInt; begin Pop := Heap[1]; // Nút gốc nút có nhãn tự nhỏ v := Heap[nHeap]; // v đỉnh nút cuối Heap, đảo lên đầu vun đống Dec(nHeap); // Giảm số phần tử Heap r := 1; // Bắt đầu từ nút gốc while r*2 = d[v] then break; // Nếu v ưu tiên khơng làm việc Heap[r] := Heap[c]; // Chuyển đỉnh lưu nút lên nút cha pos[Heap[r]] := r; // Cập nhật lại vị trí Heap đỉnh r := c; // Tiếp tục di chuyển xuống III end; Heap[r] := v; // Đỉnh v đặt vào vị trí r để đảm bảo cấu trúc Heap pos[v] := r; // Ghi nhận vị trí đỉnh v Heap end; Một số tập ứng dụng Bài tập 1: Heapuri Cho danh sách gồm N phần tử Chúng ta thực số thao tác danh sách Có loại thao tác sau : - Thao tác 1 : Cho phần tử x vào danh sách - Thao tác 2 : Xóa phần tử thứ t (theo thứ tự nhập vào) - Thao tác 3: Lấy phần tử nhỏ danh sách Yêu cầu: Hãy cho biết kết thao tác 3 ? INPUT: HEAPURI.INP - Dòng 1: N - Các dòng dãy thao tác cần xử lý theo định dạng x, x tương ứng thao tác 1, OUTPUT : HEAPURI.OUT - Ghi nhiều dòng, dòng kết thao tác theo thứ tự file input Ví dụ : HEAPURI.INP HEAPURI.OUT 1 3 Dễ thấy danh sách động (số lượng phần tử thay đổi), ta xây dựng heapmin để lấy giá trị nhỏ thao tác Để xóa phần tử thứ t theo thứ tự nhập vào ta lưu thêm mảng Pos #include #include #define maxn 200010 int N, L, NR; int A[maxn], Heap[maxn], Pos[maxn]; void push(int x) { int aux; while (x/2 && A[Heap[x]]
Ngày đăng: 14/01/2022, 20:31
Xem thêm: