Sắp xếp kiểu trộn (merge sort)

Một phần của tài liệu Cấu trúc dữ liệu giải thuật (Trang 143 - 151)

- Phép hoà nhập 2 đường. Xét bài toán:

Giả sử ta có mảng X chia làm 2 phần đã được sắp xếp: (Xb, Xb+1,....,Xm) và (Xm+1, Xm+2,....,Xn). Viết giải thuật tạo ra mảng Z có chỉ số từ b tới n (Zb, Zb+1,....,Zn) được sắp xếp.

Procedure Tron(X, b, m, n, Z); 1.i:=b; j:=m+1; k:=b;

2.While (i<=m) and (j<=n) do Begin If X[i]<=X[j] then Begin Z[k]:=X[i]; i:=i+1; End Else Begin Z[k]:=X[j]; j:=j+1; End; k:=k+1; End; 3. If i>m then (Z[k], ..., Z[n]):=(X[j], ..., X[n]); Else (Z[k], ..., Z[n]):=(X[i], ..., X[m]); Return;

- Sắp xếp kiểu hòa nhập 2 đường trực tiếp: Sau đây là thủ tục thực hiện một bước sắp xếp kiểu trộn bằng cách trộn từng cặp kế cận nhau có độ dài là L từ mảng X sang mảng Y, với n là số phần tửở trong X. Procedure Chuyen(X, Y, n, L); 1.i:=1; 2.While i<=n-2*L+1 do Begin

Tron(X, i, i+L-1, i+2*L-1, Y); { i+2*L-1 <= n } i:=i+2*l;

End;

3.{Trộn phần còn dư với phần trước}

If i+L-1<n then Tron(X, i, i+L-1, n, Y)

Else (Y[i], ..., Y[n]):=(X[i], ..., X[n]); Return;

=> Từđây ta có thể suy ra thủ tục sắp xếp theo kiểu trộn như sau: Procedure Merge_Sort(X, Y, n); 1.L:=1; 2.While L<n do Begin Chuyen(X, Y, n, L); L:=L*2; X:=Y; End; Return; Lưu ý:

- Người ta chứng minh được rằng độ phức tạp của giải thuật này là O(nlog2n). Tuy nhiên, do phải tạo ra mảng Y nên phương pháp này tốn bộ nhớ trong hơn so với 2 giải thuật trên.

CHƯƠNG 9: TÌM KIM 9.1. Bài toán tìm kiếm:

Tìm kiếm là một yêu cầu rất thường xuyên trong đời sống hàng ngày cũng như trong tin học. Đểđơn giản ta xét bài toán tìm kiếm như sau:

Cho một dãy số gồm các phần tử a1, a2, ..., an. Cho biết trong dãy này có phần tử nào có giá trị bằng X (cho trước) hay không?

9.2. Tìm kiếm tuần tự:

Giải thuật tìm kiếm tuần tự có sử dụng một biến logic, biểu thị một phần tử có tồn tại trong dãy cần tìm hay không. Ởđây ta cũng có thể giải quyết theo cách khác:

Function TimKiemTT(a, n, X); 1.i:=1; a[n+1]:=X;

2.While a[i]<>X do i:=i+1; If i=n+1 then TimKiemTT:=0

Else TimKiemTT:=i; Return;

=> Hàm này sẽ trả về giá trị là một chỉ số i nào đó trong dãy nếu tìm thấy, ngược lại hàm sẽ trả về giá trị 0.

Lưu ý: Giải thuật này có độ phức tạp là O(n).

9.3. Tìm kiếm nhị phân:

Với giả thiết ban đầu dãy đã được sắp theo thứ tự tăng dần. Giải thuật tìm kiếm nhị phân bằng đệ quy ta đã biết trong phần đệ quỵ Tuy nhiên ta có thể khửđệ quy giải thuật này như sau:

Function TKNP(a, n, X); 1.Be:=1; Lon:=n; 2.While Be<=Lon do Begin Giua:=(Be+Lon) div 2; If a[Giua]=X then

Begin

TKNP:=Giua; Exit; End;

If a[Giua]<X then Be:=Giua+1 Else Lon:=Giua-1;

End; 3.TKNP:=0; Return;

9.4. Cây nhị phân tìm kiếm:

Cây nhị phân tìm kiếm là cây được sắp xếp mà ta đã bàn đến. (adsbygoogle = window.adsbygoogle || []).push({});

Bài toán: Giả sử dãy số trên đã được chuyển vào cây nhị phân tìm kiếm mà nút gốc được trỏ bởi T. Vấn đềđặt ra: Viết một hàm CNPTK(T, X) trả về giá trị Nil nếu không có nút nào mà trường Info có giá trị bằng X, ngược lại cho kết quả là con trỏ trỏ vào phần tửđó.

Function CNPTK(T, X); 1.q:=T;

2.While q<>Nil do Case

q^.Info=X: Begin CNPTK:=q; Exit; End; q^.Info<X: q:=q^.Right;

q^.Info>X: q:=q^.Left; End Case;

3.CNPTK:=Nil; Return;

Lưu ý: Khi đã có sẵn cây nhị phân tìm kiếm, giải thuật bổ sung một nút vào cây này thì ta đã xét. Nếu cần loại bỏ một nút trong cây nhị phân tìm kiếm, ta xét các trường hợp sau:

: Chỉ nút cần xoá : Cây con

1. i) Xoá nút lá: ii) Xoá nút na lá: ≥N N <N B A

Trước khi xóa

B A

- Xoá 1 nút không là lá, không là na lá: Gii thut: Giả sử ta đã có hàm bốBo(p): Procedure XoaNut(Q); 1.{Xử lý trong trường hợp nút lá và nửa lá} p:=Q; If p^.Left=Nil then Begin R:=Bo(Q); R^.Left:=p^.Right; Dispose(p); Exit; End; If p^.Right=Nil then Begin R:=Bo(Q); R^.Left:=p^.Left; Trước khi xóa

B A C B A C B A

Sau khi xóa C hoặc A B D C E F Q, P T S

Trước khi xóa

A

B

D

C

F

Dispose(p); Exit; End;

{Trường hợp Q là con phải của bố Q thì xử lý tương tự} 2.T:=p^.Left; If T^.Right=Nil then Begin R:=Bo(Q); R^.Left:=T; T^.Right:=p^.Right; Dispose(p); Exit; End; S:=T^.Right; While S^.Right<>Nil do Begin T:=S; S:=S^.Right; End; S^.Right:=p^.Right; T^.Right:=S^.Left; S^.Left:=p^.Left; R:=Bo(Q); R^.Left=S; Dispose(p);

TÀI LIU THAM KHO

[1] Cấu trúc dữ liệu và giải thuật (Đỗ Xuân Lôi)

[2] Lập trình nâng cao bằng PASCAL với các cấu trúc dữ liệu (Larry Hoff - Lê Minh Trung dịch) - Tập 2

[3] Cẩm nang thuật toán ( Robert Sedgewick) - 2 tập [4] The Art of Computer Programming (Donald Knuth) [5] Algorithm + Data Structure = Program (Niklaus Wirth)

Một phần của tài liệu Cấu trúc dữ liệu giải thuật (Trang 143 - 151)