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

Chuyên đề cấu trúc dữ liệu nâng cao

34 440 0

Đ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 34
Dung lượng 296,5 KB

Các công cụ chuyển đổi và chỉnh sửa cho tài liệu này

Nội dung

NỘI DUNG * Các thao tác với danh sách: - Chèn phần tử vào danh sách: Nếu muốn chèn một phần tử V vào danh sách tại vị trí P, ta dồn tất cả các vị trí từ P đến vị trí N về sau một vị trí,

Trang 1

I ĐẶT VẤN ĐỀ

Khi giải một bài toán, ta cần định nghĩa tập hợp dữ liệu để biểu diễn dữ liệu vào và kết quả ra.Việc lựa chọn này tùy thuộc vào vấn đề cần giải quyết và những thao tác sẽ tiến hành trên dữ liệu

Có những thuật toán chỉ thích ứng với một cách tổ chức dữ liệu nhất định, nếu sử dụng những cách

tổ chức dữ liệu khác sẽ kém hiệu quả hoặc không thể thực hiện được Chính vì vậy khi tìm kiếm

thuật toán giải quyết vấn đề không tách rời bước xây dựng cấu trúc dữ liệu Chuyên đề “Cấu trúc

dữ liệu nâng cao ” sẽ trình bày một số kiểu dữ liệu nâng cao thường được sử dụng.

II NỘI DUNG

* Các thao tác với danh sách:

- Chèn phần tử vào danh sách: Nếu muốn chèn một phần tử V vào danh sách tại vị trí P, ta

dồn tất cả các vị trí từ P đến vị trí N về sau một vị trí, sau đó đặt V vào vị trí P, tăng số lượngphần tử lên một đơn vị

- Xóa phần tử khỏi danh sách: Nếu muốn xóa phần tử P vẫn giữ nguyên thứ tự, ta dồn tất cả

các phần tử từ vị trí P+1 tới vị trí N lên trước một vị trí, giảm số lượng phần tử đi một đơn vị

1.1.2 Tổ chức danh sách bằng liên kết nối đơn

Danh sách liên kết nối đơn gồm các nút được nối với nhau theo một chiều Mỗi nút là một bảnghi gồm hai trường: một trường chứa giá trị và một trường chứa liên kết tới nút kế tiếp

Nút đầu tiên được gọi là chốt của danh sách, để duyệt danh sách ta bắt đầu từ chốt, dựa vàotrường liên kết để đi tiếp cho tới khi gặp giá trị đặc biệt thì dừng lại

* Các thao tác với danh sách:

- Chèn phần tử vào danh sách: Nếu muốn chèn một nút chứa giá trị V vào danh sách tại vị trí

nút P, ta tạo ra một nút mới chứa giá trị V, sau đó tìm nút q đứng trước nút p, nếu thấy thìchỉnh lại liên kết: q liên kết đến nút mới, nút mới liên kết tới p, nếu không tìm thấy thì P là chốt,

ta chỉnh lại liên kết nút mới liên kết tới chốt (cũ) và chốt được đặt lại bằng nút mới

- Xóa phần tử khỏi danh sách: Nếu muốn xóa nút P khỏi danh sách liên kết, ta tìm nút q đứng

trước nút p trong danh sách, nếu thấy thì chỉnh lại liên kết: q liên kết đến nút liền sau p; nếukhông thấy thì có nghĩa p là nút chốt, ta chỉ cần đặt lại chốt bằng nút đứng kế tiếp chốt (cũ) trongdanh sách; Sau đó giải phóng bọ nhớ cấp phát cho nút p

Trang 2

1.1.3 Tổ chức danh sách bằng liên kết nối kép

Danh sách liên kết nối kép gồm các nút được nối với nhau theo hai chiều Mỗi nút là một bản ghigồm ba trường: trường thứ nhất chứa giá trị, trường thứ hai chứa liên kết tới nút kế tiếp (Next),trường thứ ba chứa liên kết tới nút liền trước (Prev)

Danh sách nối kép có hai chốt: Nút đầu tiên được gọi là First, nút cuối cùng được gọi là Last Đểduyệt danh sách ta có hai cách: Hoặc là bắt đầu từ First, cách duyệt như danh sách liên kết nối đơn;Hoặc bắt đầu từ Last, dựa vào liên kết Prev để đi sang nút liền trước, đến khi duyệt đến giá trị đặc biệt(duyệt qua nút đầu) thì dừng lại

Các thao tác với danh sách tương tự như danh sách liên kết nối đơn

- Ngăn xếp bị tràn khi bổ sung vào mà số phần tử vượt quá số lượng tối đa của mảng (mảng đầy)

- Ngăn xếp rỗng khi số lượng phần tử thực sự trong mảng bằng không

- Việc bổ sung phần tử vào ngăn xếp tương đương với thêm phần tử vào cuối mảng

- Việc loại bỏ một phàn tử khỏi ngăn xếp tương đương với việc loại bỏ phần tử ở cuối mảng 2.1.1.2 Tổ chức ngăn xếp bằng danh sách liên kết nối đơn kiểu LIFO

Khi cài đặt ngăn xếp bằng danh sách liên kết nối đơn kiểu LIFO, thì ngăn xếp bị tràn vùngkhông gian nhớ dùng cho các biến động không còn đủ để thêm một phần tử mới Tuy nhiên, việc kiểmtra này sẽ rất khó vì nó phụ thuộc vào máy tính và ngôn ngữ lập trình, vì vậy khi tổ chức ngăn xếpbằng liên kết nối đơn kiểu LIFO

2.2 Hàng đợi (Queue)

Là danh sách được tổ chức theo kiểu FIFO (“vào trước, ra trước”) Phần tử được nạp vào (đẩy

vào) ở vị trí cuối hàng đợi (biến rear hoặc last quản lý vị trí này), phần tử được lấy ra tại vị trí đầu hàng đợi (biến front hoặc first quản lý vị trí này).

Trang 3

- Để loại phần tử khỏi hàng đợi, ta tăng rear lên 1 và đưa giá trị đó vào phần tử thứ rear

- Để loại một phần tử khỏi hàng đợi, ta lấy giá trị ở vị trí front và tăng front lên 1

- Hàng đợi đầy khi rear tăng lên hết khoảng chỉ số của mảng

- Hàng đợi rỗng khi front > rear

2.2.1.2 Tổ chức hàng đợi bằng danh sách liên kết nối đơn kiểu FIFO

Tương tự như tổ chức ngăn xếp bằng danh sách liên kết nối đơn kiểu LIFO, ta cũng không kiểmtra hàng đợi tràn khi tổ chức bằng danh sách liên kết nối đơn kiểu FIFO [1]

3 Cây (Tree)

Cây là tập hợp các nút, giữa các nút có quan hệ phân cấp (thường gọi là quan hệ “cha, con”)

Có thể cài đặt cây bằng mảng hoặc bằng cấu trúc liên kết Một dạng quan trọng của cây là câynhị phân Biểu diễn danh sách bằng cây nhị phân là cách tổ chức dữ liệu thường xuyên cập nhật cóhiệu quả của bài toán thống kê động

Cây nhị phân (Binary Tree) Mỗi nút trên cây có tối đa 2 nhánh con gọi là cây con trái và cây

con phải của nút đó

Cây nhị phân đầy đủ là cây nhị phân mà mọi nút nhánh đều có đúng 2 nhánh con

Cây nhị phân hoàn chỉnh là cây nhị phân đầy đủ mà các lá ở cùng độ sâu

Từ cây nhị phân hoàn chỉnh bỏ đi một số lá thì gọi là gần hoàn chỉnh

Cây nhị phân tìm kiếm (BST) Cây nhị phân tìm kiếm là cây nhị phân mà mỗi nút chứa một

khóa Khóa của mỗi nút không nhỏ hơn mọi khóa trong nhánh con trái và không lớn hơn mọi khóatrong nhánh con phải [2]

4 Hàng đợi ưu tiên (Priority queue)

Hàng đợi ưu tiên là một kiểu danh sách mà mỗi phần tử được gán với một mức độ ưu tiên giúpquá trình xử lý chúng theo quan hệ nào đó giữa chúng Hàng đợi ưu tiên thuận tiện cho việc lấy raphần tử được ưu tiên nhất khi dữ liệu luôn luôn cập nhật

Heap (hay là Binary Heap) là một hàng đợi ưu tiên thông dụng nhất Heap thường có dạng một

cây nhị phân gần hoàn chỉnh Có hai loại: MaxHeap và MinHeap Trong MaxHeap, mỗi nút lưu mộtphần tử của danh sách có độ ưu tiên không nhỏ hơn độ ưu tiên của các phần tử nằm ở hai nhánh concủa nó Ngược lại, trong MinHeap, mỗi nút lưu một phần tử của danh sách có độ ưu tiên không lớnhơn độ ưu tiên của các phần tử nằm ở hai nhánh con của nó

Trang 4

5 Cây khoảng (Interval Tree)

Cây khoảng là cây có quan hệ thứ tự bộ phận dùng lưu trữ các khoảng cơ sở Cây khoảng chophép cập nhật, tìm kiếm các khoảng rất hiệu quả Có thể cài đặt cây khoảng như một Heap

Ví dụ trong bài toán quản lí một dãy số nguyên A={a0, a2, …, an-1} mà dãy số này thường xuyênđược cập nhật, chúng ta có thể tổ chức cây khoảng (interval tree) như sau: Trên cây nhị phân mỗi nútgán cho một đoạn chứa một số phần tử của dãy

Nút gốc là đoạn [a0; an-1] chứa mọi phần tử của dãy, tiếp theo là hai nút con của gốc tương ứngvới hai đoạn liên tiếp: nút con trái của gốc được gán cho đoạn [a0; (a0+an-1) div 2], nút con phải đượcgán cho đoạn [1+(a0+an-1) div 2; an-1]….Cuối cùng tại các nút lá, mỗi lá quản lý một đoạn có điểm đầu

và điểm cuối trùng nhau, nghĩa là chứa đúng một số nguyên của dãy Cây khoảng thường dùng để xử

lý dữ liệu trên các khoảng mà các khoảng luôn luôn cập nhật thay đổi Một số bài toán như: tìm cáckhoảng chứa một số k cho trước hoặc tìm số lớn nhất, nhỏ nhất chứa trong một khoảng nào đó trongquá trình cập nhật các khoảng

6 Cây chỉ mục (BIT - Binary indexed tree)

Binary Indexed Trees hiện nay thường dùng lưu trữ các tần số và tích luỹ tần số (cộng dồn tầnsố) của dữ liệu thường xuyên cập nhật trong các bảng Nó đáp ứng được các yêu cầu sau của n đốitượng:

(1) Yêu cầu 1: cập nhật (lấy ra, nạp vào, sửa đổi giá trị…) đối tượng i?

(2) Yêu cầu 2: Tính tổng giá trị (hoặc tần số) các đối tượng từ i tới k [2]

7 Bài tập minh họa

Bài 1 Sắp tô pô

Cho N công việc, mỗi công việc i phải làm trước một số công việc nào đó trong N công việcnày Hãy xếp lịch thực hiện đủ N công việc

Dữ liệu vào từ file XL.IN: Dòng đầu là số nguyên dương N Các dòng sau thể hiện quan hệ thứ

tự bộ phận: đầu dòng là số i, các số tiếp theo là ji1, ji2, , jis thể hiện công việc i phải làm trước các côngviệc ji1, ji2, , jis

Trang 5

Kết quả ghi ra file XL.OUT một dòng N số hiệu công việc được lần lượt làm Ví dụ

phụ thuộc công việc nào) Sau đó tiến hành các bước sau:

+ Tìm một đỉnh bậc 0 nạp vào Stack

+ Thực hiện vòng lặp: Trong khi Stack chưa rỗng thì:

- Lấy một phần tử i ở đỉnh Stack, đánh dấu đã xét i, xác nhận mảng một chiều T có thêm phần

tử mới là i.

- Xoá các cung đi ra từ i

- Nạp đỉnh 0 mới vào Stack

+ Nếu số lượng phần tử trong mảng T bằng N thì dãy T[1], T[2], , T[N] là một cách sắp N phần

begin {Lấy giá trị cho biến N và mảng A(N,N)} end;

function bac_0(i: byte): boolean;

begin {Xác định đỉnh i có là đỉnh bậc 0 hay không} end;

function dinhbac0: byte;

begin {Dựa vào hàm bac_0, tìm một đỉnh bậc 0 chưa đánh dấu end;

procedure nap(i: byte);

begin {Nạp phần tử i vào stack} end;

function lay: byte;

begin {Lấy một phần tử ở đỉnh stack ra khỏi stack} end;

procedure hien;

var i: byte;

begin

Trang 6

if sl<n then write(g,0)

else

for i:=1 to sl do write(g,t[i]:4);

end;

procedure xoa(i: byte);

begin {Xoá các cung xuất phát từ i} end;

Bài 2 Biểu thức hậu tố

Các biểu thức toán học chứa các phép tính cộng (+), trừ (-), nhân (*), chia (/), dấu ngoặc trái: '('

và dấu ngoặc phải: ')' cùng các toán hạng được viết dưới dạng biểu thức trung tố Ví dụ : (2+3.4)" Biểu thức trung tố khi tính toán phải tuân theo các quy tắc ưu tiên phép tính và ưu tiên thứ tựthực hiện phép tính :

T="7.2*8.5-+ thực hiện trong ngoặc trước, ngoài ngoặc sau

+ cùng trong ngoặc thì thực hiện nhân chia trước, cộng trừ sau

Những quy tắc này khó xử lý khi biểu thức có nhiều ngoặc, vì vậy người ta xây dựng một cáchbiểu diễn khác để máy tính dễ thực hiện tính biểu thức hơn: đó là cách viết biểu thức dưới dạng hậu tố(trong nó không có dấu ngoặc)

H="7.2 8.5 * 2 3.4 + - "

Việc tính biểu thức này rất dễ dàng bằng sử dụng ngăn xếp (Stack)

Hãy viết chương trình chuyển biểu thức trung tố thành biểu thức hậu tố, sau đó tính giá trị củabiểu thức Dữ liệu vào từ tệp “BL4.INP” gồm một số dòng, mỗi dòng là một biểu thức trung tố Kết

Trang 7

quả ra ghi vào tệp “BL4.OUT”, mỗi dòng là một kết quả tương ứng với một dòng của tệp dữ liệu vào

và có dạng sau:

Biểu thức trung tố  Biểu thức hậu tố = Giá trị biểu thức Ví dụ:

7.2*8.5-(2+3.4)  7.2 8.5 * 2 3.4 + - = 54.4

Gợi ý.

Quy tắc chuyển từ biểu thức trung tố thành biểu thức hậu tố:

• Gán biểu thức hậu tố bằng xâu rỗng H :=””(xâu rỗng)

• Đọc biểu thức trung tố T từ trái qua phải:

+ Nếu gặp dấu mở ngoặc '(' thì nạp nó vào ngăn xếp

+ Nếu gặp dấu đóng ngoặc ')' thì lần lượt lấy các phần tử ở đỉnh ngăn xếp nối vào đuôi biểu thứchậu tố cho đến khi gặp dấu mở ngoặc nằm trong ngăn xếp thì lấy dấu mở ngoặc này khỏi ngăn xếp bỏ

đi ( không nối vào H )

+Nếu gặp dấu phép toán thì so phép toán này với phép toán ở đỉnh ngăn xếp (nếu có); nếu phéptoán này ưu tiên ít hơn phép toán ở đỉnh ngăn xếp thì lấy phép toán ở đỉnh ngăn xếp nối vào đuôi H,đồng thời nạp phép toán này vào đỉnh ngăn xếp Trong trường hợp ngược lại hoặc trong trường hợpđỉnh ngăn xếp không có phép toán thì nạp phép toán này vào ngăn xếp

+ Nếu gặp toán hạng thì nối toán hạng vào đuôi H

• Sau khi đọc xong biểu thức trung tố T, lần lượt lấy nốt các phần tử ở đỉnh ngăn xếp nối vàođuôi H cho đến khi ngăn xếp rỗng hoặc chỉ còn 1 dấu đóng ngoặc '('

Tính biểu thức hậu tố

Máy tính có thể dễ dàng tính biểu thức hậu tố theo quy tắc sau :

Đọc biểu thức hậu tố từ đầu về cuối (từ trái sang phải):

• Nếu gặp toán hạng thì cho toán hạng vào ngăn xếp

• Nếu gặp dấu phép toán thì lấy khỏi ngăn xếp toán hạng thứ nhất và toán hạng thứ hai, sau đóđem toán hạng thứ hai thực hiện phép toán với toán hạng thứ nhất, kết quả thu được lại cho vào ngănxếp

• Số cuối cùng còn lại trong ngăn xếp chính là giá trị biểu thức cần tính

Trang 8

procedure nap(ch : char);

Trang 10

while i<= length(h) do begin

if h[i] in ['0' '9'] then nap(so)

Bài 3 Bài toán ”Trung vị của dãy” (ACM[POJ] 2623)

Cho dãy N số nguyên không âm Hãy xác định số trung vị của dãy Nếu N lẻ thì số trung vị là sốchính giữa dãy đã sắp, đó là vị trí (N+1)/2 Nếu N chẵn thì số trung vị là trung bình cộng hai số “chínhgiữa” dãy đã sắp, đó là các số ở vị trí N/2 và (N/2)+1 Dãy cho ban đầu là chưa sắp

Input

Dòng đầu tiên chứa đúng một số N là độ dài của dãy Dãy cho trong các dòng tiếp theo, mỗidòng một số Độ dài của dãy trong giới hạn từ 1 đến 250000 Mỗi phần tử của dãy là số nguyên dươngkhông vượt quá 232-1

3 6 4

4.5

Trang 11

Gợi ý Tạo 2 Heap: A là MaxHeap (Heap có gốc mang khoá ưu tiên lớn nhất), B là MinHeap

(Heap có gốc mang khoá ưu tiên nhỏ nhất) Đọc tệp input, mỗi lần được một số thì so sánh với gốc của

A, nếu không výợt quá gốc của A thì nạp vào A, ngược lại thì nạp vào B

Sau khi có 2 Heap sẽ điều chỉnh (tháo Heap này chuyển sang Heap kia) sao cho số nút của Ađúng bằng (N+1) div 2

Nếu N chẵn thì số trung vị là trung bình cộng của hai số ở hai gốc A và B Nếu N lẻ thì số trung

vị ở gốc của heap có số nút lớn hơn

Chương trình.

fi = 'median.in';

fo = 'median.out';

type rec = record w : integer; end;

heap = array[0 maxn] of rec;

var hmin,hmax : heap;

procedure upheapmax(vt: integer);

var key: rec;

begin

key := hmax[vt];

while (vt div 2>0) and (key.w > hmax[vt div 2].w) do begin

hmax[vt]:= hmax[vt div 2];

procedure downheapmax(vt: integer);

var key : rec; j : integer;

Trang 12

Key := hmax[vt] ; j:=2*vt;

while j <=sizehmax do begin

if(hmax[j].w < hmax[j+1].w) then j:= j+1;

if key.w > hmax[j].w then begin

hmax[j div 2]:= key;

procedure upheapmin(vt: integer);

var key: rec;

procedure downheapmin(vt: integer);

var key : rec; j : integer;

begin

Key := hmin[vt] ; j:=2*vt;

while j <=sizehmin do begin

if(hmin[j].w > hmin[j+1].w) then j:= j+1;

if key.w < hmin[j].w then begin

hmin[j div 2]:= key;

Trang 13

procedure removehmin(var node: rec);

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

while sizehmax>sizehmin do begin

Trang 14

Bài 4 Path k (Chạy tiếp sức)

Vựng đất X cú N thành phố (4≤N≤800) được đỏnh số từ 1 đến N Giữa hai thành phố cú thể cúđường nối trực tiếp hoặc khụng Cỏc con đường này được đỏnh số từ 1 đến M (1≤M≤4000) Ban lónhđạo thể dục thể thao vựng X tổ chức cuộc chạy đua tiếp sức “thụng minh” theo quy luật sau :

+ Đường chạy của cỏc đội viờn khụng được giống nhau hoàn toàn

+ Cú thể chạy lại đoạn đường đó chạy

Hóy viết chương trỡnh tớnh thời gian nhỏ nhất để một đội hoàn thành cuộc chạy đua tiếp sức nờu trờnnếu cỏc vận động viờn cú tốc độ chạy như nhau

Dữ liệu vào từ file văn bản PATHK.IN

 Dũng đầu tiờn ghi ba số nguyờn K, N, M;

 M dũng tiếp theo, mỗi dũng chứa 3 số nguyờn i, j, w thể hiện một đường đi trực tiếp giữa hai thànhphố i và j mất thời gian chạy là w (đơn vị thời gian) 1≤w≤9500)

Kết quả ra file văn bản PATHK.OUT :

 Dũng thứ nhất chứa một số nguyờn duy nhất là thời gian chạy nhỏ nhất của một đội

 K dũng tiếp theo, mỗi dũng thể hiện hành trỡnh chạy của một vận động viờn trong đội là dóy sốhiệu cỏc thành phố liờn tiếp trờn hành trỡnh đú

5 Vận động viên 4 : 1 2 5

Trang 15

Gợi ý Tổ chức danh sách liên kết để quản lý các đỉnh kề nhau trên đồ thị vô hướng có trọng số.

Dùng thuật toán sửa dần nhãn tìm đường đi tối ưu trên đồ thị Nk đỉnh (mỗi đỉnh là một cặp i, j thểhiện có i thành phố và j vận động viên) Xây dựng mảng nhãn: L[1 N, 1 K] với ý nghĩa: L[i, j] là thờigian ngắn nhất của vận động viên j tới thành phố i Trong quá trình sửa nhãn dùng hai mảng Tr1 vàTr2 lưu vết hành trình

Lưu ý Do các vận động viên chạy tốc độ như nhau nên L[i, j] không phụ thuộc vào j

Trang 16

procedure findmin(var ii,jj : integer);

var i, j : integer; min : longint;

begin

ii := 0; jj := 0; min := vc;

for i:=1 to n do

for j:=1 to k do begin

if d[i,j] then continue;

if min>l[i]^[j] then begin

if d[i,j] then continue;

if l[i]^[j] >= l[ii]^[jj] + nodệw then begin move(l[i]^[j],l[i]^[j+1],4*(k-j+1));

l[i]^[j] := l[ii]^[jj] + nodệw;

repeat

findmin(ii,jj);

ok := (ii=0) or (d[n,k]);

if d[n,k] then break;

Trang 17

if not ok then begin

Ngày đăng: 03/01/2016, 21:33

TỪ KHÓA LIÊN QUAN

🧩 Sản phẩm bạn có thể quan tâm

w