1. Trang chủ
  2. » Công Nghệ Thông Tin

Các giải thuật sắp xếp

16 757 5
Tài liệu đã được kiểm tra trùng lặp

Đ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

Tiêu đề Các giải thuật sắp xếp
Tác giả Nguyễn Xuân Huy
Trường học Trường Đại Học
Thể loại bài luận
Định dạng
Số trang 16
Dung lượng 103,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

Các giải thuật sắp xếp

Trang 1

Chọn giải thuật sắp xếp

Nguyễn Xuân Huy Các giải thuật sắp xếp trong

Bài toán sắp xếp mảng thường được phát biểu như sau:Cho một mảng a gồm n phần tử thuộc kiểu sắp được T, nghĩa là giữa hai phần tử xvà y bất kỳ thuộc kiểu T chỉ cóthể xảy ra một trong ba trường hợp loại trừ nhau sau đây: Hoặc x = y,hoặc x > y hoặc x < y Yêu cầu: sắp lại mảng a theo một trật tự cho trước, thí dụ,sắp tăng Trong trường hợp này, kết quả thu được sẽ thoả tính chất sau: a[1]<= a[2]<= <= a[n] Việc sắp xếp phải được thực hiện

tại chỗ,tức là không được dùng thêm mảng phụ, ngoại trừ trường hợp sắp theo chỉ

dẫn.Trong trường hợp cần sắp theo chỉ dẫn, ta phải dùng mảng cd[1 n] đóng vai trò chỉdẫn tới các phần tử của mảng a Saukhi sắp theo chỉ dẫn, trật tự của các phần tử trong mảng a không thay đổi, còn các chỉ dẫn trong mảng cd lần lượt trỏ tới các phần tử của a theo trật

tự tăng dẫn

Thí dụ, nếu ta cho a[1 6] = (4, 3, 4, 8, 3, 1) Thì sau khi sắp trực tiếp mảng a tasẽ thu được: a[1 6]= (1, 3, 3, 4, 4, 8)

Nếu sắp theo chỉ dẫn ta sẽ thu được mảng chỉ dẫn nhưsau:

cd[1 6]= (6, 2, 5, 1,3, 4)

Như vậy các chỉ dẫn cho biết phần tử thứ 6 trong a là nhỏ nhất, tiếp đến là các phầntử thứ

2, thứ 5, thứ 1 thứ 3 và cuốicùng, phần tử thứ 4 trong a là lớnnhất.

Có nhiều giải thuật sắp xếp nhanh chậm khác nhau,trong số đó đứng đầu bảng là các giải

thuật sắp nhanh đòi hỏi độ phức tạp n*log(n), bao gồm Quick Sort và HeapSort, trong đó logarit được lấy theo cơ số 2 Giải thuật Shell Sort có độ phứctạp cỡ n1.2 Các giảithuật

khác như nổi bọt, xen trực tiếp có độ phức tạp cỡ n2 Số người sử dụng giảithuật Quick Sort do Hoare đề xuất có lẽ nhiều nhất, vì giải thuật này nhanh, dễcài đặt và ẩn chứa nhiều

vẻ đẹp

Tuy nhiên, có một số trường hợp dùng các giải thuậtsắp nhanh lại không đem lại kết quảmong muốn

Trang 2

Giả thử trong một cuộc thi tài có 6 bạn tham gia làAn, Bình, Chính Điền, Thanh và Vân Trước khi bắt đầu cuộc thi, Ban giám khảodùng giải thuật nhanh, Quick Sort chẳng hạn, để sắp danh sách 6 bạn theo trậttự từ điển như đã cho trong mảnh trái của bảng trên Sau khi thi, tức là sau khi đã biết điểm của mỗi bạn, Ban giámkhảo lại dùng Quick Sort sắp lại danh sách các bạn theo chiều giảm dần của điểmthi Kết quả được ghi trong mảnh phải của bảng Bạn hãy quan sát bảng trên xemcó điều gì không bình thường? Có đấy, trước khi tham gia thi, bạn Bình đứngtrước bạn Điền theo trật tự từ điển Sau khi thi, hai bạn cùng có

số điểm nhưnhau, tức là 10 điểm, vậy mà kết quả sắp xếp lại đặt bạn Điền trên bạn Bình

Như vậy có vô lý không?Giả sử cuộc thi chỉ lấy một bạn và hệthống xét chọn được thực

hiện tự động bằng cách lấy người đầu tiên trong danhsách kết quả Việc chọn bạn Điền có thể dẫn đến những tranh luận nhất định Tạisao lại có hiện tượng trên Số là một số giải

thuật sắp xếp đã thực hiện việcđổi chỗ các phần tử trong mảng Bạn có thể hỏi: Không đổi chỗ các phần tử thì làm sao có thể đặt lại được phần tử theogiá trị lớn nhỏ của chúng?

Đúngvậy, ta lưu ý rằng, nói chung mỗi lần đổi chỗ hai phần tử ta chỉ có thể đặtđược một trong hai phần tử đó vào đúng vị trí cần sắp Phần tử bị chiếm chỗ cóthể rơi vào vị trí nào

đó Chính vì đến chỗ mới nên phần tử bị chiếm chỗ có thểlàm đảo lộn thứ tự tự nhiên ban

đầu Để khắc phục điều này ta chỉ đổi chỗ mỗilần hai phần tử liên tiếp nhau a[i]và a[i+1]

nếu chúng có giá trị khácnhau Phương pháp này được gọi là tịnh tiến hay đẩy dần: ta đẩy dần mỗi phần tửvào vị trí thích hợp Các giải thuật sắp xếp như sắp theo phép chèn theo

mộttrật tự duyệt thích hợp và nổi bọt thực hiện việc tịnh tiến do đó chúng đảm bảo được trật tự tự nhiên ban đầu.

Dĩ nhiên, với thí dụ trên, nếu chúng ta gọi thủ tụcQuick Sort đồng thời trên hai trường, chẳng hạn, sắp tăng theo trật tự từ điểnvà sắp giảm theo điểm thì trật tự tự nhiên ban đầu vẫn được tôn trọng Tuynhiên, trong trường hợp này chúng ta phải trả giá không ít

Kẻ yếu lênngôi

Trong số các giải thuật sắp xếp thì các giải thuậtnhư sắp theo phép chèn và giải thuật nổi bọt đảm bảo được trật tự tự nhiên banđầu Sau đây là một bài toán minh hoạ

Bài toán(Mã Burrows Wheeler)

Trang 3

Cho xâu ký tựs[1 n] và gọi là xâu rõ Ta mã hoá s theo các bước sau:

Bước 1 Lần lượt quay xâu s theo chiều kim đồng hồ, mỗi lần một vị trí để thuđược n xâu thứ cấp kể cả xâu s ban đầu (xem bài Quay quay trong Tin học và nhàtrường số 4/2000) Bước 2.Sắp tăng các xâu thu được ở bước 1 theo trật tự từ điển.

Bước 3.Tạo xâu w bằng cách ghép lần lượt các ký tự cuối của các xâu đã sắp.

Bước 4.Xác định vị trí của xâu rõ s trong dãy đã sắp, giả sử đó là d.

Cặp (w, d)được gọi là mã Burrows Wheeler của xâu rõ s Ký hiệu BW là thủ tục mã hoá theophương pháp trên, ta có:

BW(s) = (w,d).

a)Hãy viết thủ tục lập mãBW(s) = (w,d)

b)Hãy viết thủ tục giải mãEBW(w,d) = s

Thí dụ, với xâu s = 'btamara, thuật toán BW đực thực hiện cụ thể như sau:

Bước 1 Quay xâu Dễ thấy rằng vì sau n lầnquay xâu ta sẽ thu lại được xâu s banđầu cho

nên ta có thể chọn chiều quay tuỳ ý Hơn thế nữa, tổng cộng ta sẽ thuđược n xâu thứ cấp, mỗi xâu có đúng n ký tự và có ký tự đầu tiên chính là s[i],i</I>=1 6 Ta [k] là xâu thứ cấp thu được bằng cách lấyvòng tròn theo chiều kim đồng hồ n kýtự liên tiếp trong xâu s,

kể từ vịtrí thứ k trở đi, thí dụ, [2]= amarat.Vậy các xâu nhận được sẽ là:

1.[1] = 'tamará, 2.[6] = 'atamar',3.[5] = 'ratamá, 4.[4] = 'aratam', 5.[3]= 'maratá, 6.[2]

= 'amarat'.

Ký hiệu i.[k] cho ta biết, trước khi sắp, xâu [k] đứng thứ i trong dãy các xâu thứcấp

Bước 2 Sắp

1.[2]='amarat', 2.[4]='aratam',3.[6]='atamar',, 4.[3]='maratá, 5.[5]= 'ratamá, 6.

[1]='tamará

Ký hiệu i.[k] cho ta biết, sau khi sắp, xâu [k] đứng thứ i trong dãy các xâu thứ cấp

Bước 3 Tạo w

w = tmraaa

Bước 4 Xác định d

Trang 4

d = 6

Ta có:

BW( 'tamará ) = ( 'tmraaá , 6)

Bài giải

Để mã hoá ta sử dụng thuậttoán sắp các xâu thứ cấp đã nêu trong bài Quay quay Ta có thể dùng giải thuậtsắp nhanh Quick Sort theo chỉ dẫn Cụ thể với thí dụ đã nêu, trước khi sắp takhởi trị cho mảng chỉ dẫn là cd[1 6]= (1, 2, 3, 4, 5, 6) Sau khi sắp tathu được cd[1 6] = ( 2, 4,6, 3, 5, 1) Nói cách khác, sau khi sắp các xâu thứcấp cd[i]= k sẽ cho biết xâu thứcấp [k] đứng thứ i trong dãy sắp tăng của các xâu thứ cấp.

(* dat chi dan va sap nhanh cac xau thu cap*)

procedure SapS;

vari: integer;

begin

fori := 1 to n do cd[i] := i;

Qsort(1,n);

end;

(* Sap nhanh cac xau thu cap theo chi dan*)

procedure Qsort(l, r: integer);

vari, j, t, m: integer;

begin

i:= l; j := r;

m:= cd[(i+j) div 2];

while i <= j do

begin

while Sanh(cd[i], m) = -1 do inc(i);

Trang 5

while Sanh(cd[j], m) = 1 do dec(j);

if (i <= j) then

begin

t := cd[i];

cd[i] := cd[j];

cd[j] := t;

inc(i); dec(j);

end;

end;

ifl < j then Qsort(l,j);

ifi < r then Qsort(i,r);

end;

Saukhi sắp tăng các xâu thứ cấp để tạo xâu mã wta chỉ việc ghép các từ cuối của các xâu thứ cấp theo trật tự đã sắp Vì xâuthứ cấp [i] có ký tự đầu tiên là s[i] thì ký tự cuối cùng của nó trên vòngtròn sẽ là phần tử sát trước của s[i].ta dùng hàm Pre(i) để xác định vị trínày Nói chung, khi duyệt các giá trị 1 ntheo vòng tròn bạn luôn nhớ cài đặt hai hàm Next(i)cho gía trị sát sau giá trị itrên vòng tròn 1 n và hàm Pre(i) cho giá trị sát trươvs giá trị i trên vòng tròn 1 n Hai hàm đó như sau:

(*Cho gia tri sat sau i tren vong tron 1 n *)

function Next(i: integer): integer;

begin

ifi = n then Next := 1

else Next := i+1;

end;

(* Cho gia tri sat truoc i tren vong tron1 n *)

function Pre(i: integer): integer;

Trang 6

ifi = 1 then Pre := n

else Pre := i-1;

end;

Bước cuối cùng của quá trìnhmã hoá là xác định vị trí d của xâu rõ strong trật tự đã sắp của các xâu thứ cấp Để làm việc này ta chỉ cần duyệt mảngchỉ dẫn để tìm vị trí d sao cho cd[d]=1, vì [1] chính là xâu rõ ban đầu.

Thủtục mã hoá BW(s)=(w,d) khi đó sẽ như sau:

(* Ma hoa BW(s) = (w,d) *)

procedure BW;

vari: integer;

begin

n:= length(s);

Saps;

w:= '';

fori := 1 to n do

w:= w + s[Pre(cd[i])];

fori := 1 to n do

if cd[i] = 1 then

begin

d := i;

exit;

end;

end;

Trang 7

Với xâu rõ ban đầu s = tamara ta thu được BW(s) = ( tmraaa ,6).

Chọn giải thuật sắp xếp

Nguyễn Xuân Huy

Bây giờ ta chuyển qua thủ tục giải mã EBW(w, d)=s Dễ thấy thủ tục này đối xứng với thủ tục mã hoá BW(s)=(w, d) và bao gồm các bước sauđây:

Bước 1 Sắp tăng xâu mã w theo chỉ dẫn cd, ta đượccd[1 6]=(4,5, 6, 2, 3, 1)

Bước 2 Duyệt kiểu liên hoàntheo chỉ dẫn trênxâu w= 'tmraaá kể từ vị trí d =6 trở đi ta

lần lượt thu được:

d1=cd[d]=cd[6]=1 do đó s[1]=w[1]= 't'

d2 = cd[d1] = cd[1] = 4 do đó s[2]=w[4]= 'á

d3 = cd[d2] = cd[4] = 2 do đó s[3]=w[2]= 'm'

d4 = cd[d3] = cd[2] = 5 do đó s[4] = w[5]= 'á

d5 = cd[d4] = cd[5]=3 do đó s[5]=w[3]= 'r'

d6=cd[d5]=cd[3]=6; s[6]=w[6]=</i> 'á

Thủ tục giải mã khi đó sẽ như sau:

(* Giai ma EBW(w,d) = s *)

procedure EBW;

var i : integer;

begin

n := length(w);

Sapw;

s := '';

for i := 1 to n do

Trang 8

d := cd[d];

s := s + w[d];

end;

end;

Vì xâu w có chứa 3 ký tự a giống nhau nên khi sắptheo chỉ dẫn bằng các giải thuật nhanh

có thể cho ta, chẳng hạn, cd[1 6] = (5, 4, 6, 2,3, 1) và ta có thể thu được kết quả giải mã

sai s = tarata.

Tóm lại ở bước 1 của thủ tục giải mã ta phai dùng một giải thuậtsắp tịnh tiến, chẳng hạn sắp theo phương pháp chèn trực tiếp như sau.

(* Sap chen truc tiep w theo chi dan*)

procedure Sapw;

var x, i, j, k: integer;

begin

for i := 1 to n do cd[i] :=i;

for i := 2 to n do

begin

x := cd[i]; k := 1;

for j := i-1 downto 1do

begin

if (w[cd[j]] <=w[x]) then

begin

k := j+1;

break;

end;

Trang 9

cd[j+1] := cd[j];

end;

cd[k] := x;

end;

end;

Trong chương trình dưới đây thủ tục RunBW sẽ mã hoá từng dòng củachính tệp chương trình hiện hành BW PAS rồi ghi vào tệp văn bản BW.COD Mỗixâu ký tự s của tệp f sẽ được mã hóa thành cặp (w, d) và được ghi thành 2 dòng trong tệpg/ Một dòng chứa xâu w,dòng tiếp theo chứa trị d Thủ tụcRunEBW giải mã, tưcá là chuyển tệp BW.COD về tệp NEWBW.PAS Chương trình chỉdùng 3 mảng: hai xâu s , w và một mảng chỉ dẫn cd.

Chương trình Pascal

(* Ma hoa Burrows Wheeler *)

uses crt;

var s, w: string;

cd: array[0 255] ofinteger;

d, n: integer;

f,g: text;

function Next(i: integer): integer;

begin

if i = n then Next := 1

else Next := i+1;

end;

function Pre(i: integer): integer;

begin

if i = 1 then Pre := n

Trang 10

else Pre := i-1;

end;

Function Sanh(i,j: integer): integer;

var k: integer;

begin

for k := 1 to n do

begin

if s[i] <> s[j] then

begin

if s[i] < s[j] thenSanh := -1

else Sanh := 1;

exit;

end;

i := Next(i); j := Next(j);

end;

Sanh := 0;

end;

(* Sap noi bot cac xau trong s theo chi dan*) procedure Saps;

var i,j,t: integer;

begin

for i := 1 to n do cd[i] := i;

for i := 1 to n-1 do

Trang 11

for j := n downto i + 1 do

if (Sanh(cd[j],cd[j-1])=-1)then

begin

t := cd[j];

cd[j] := cd[j-1];

cd[j-1] := t;

end;

end;

(* Sap chen truc tiep w theo chi dan*) procedure Sapw;

var x, i, j, k: integer;

begin

for i := 1 to n do cd[i] :=i;

for i := 2 to n do

begin

x := cd[i]; k := 1;

for j := i-1 downto 1do

begin

if (w[cd[j]] <=w[x]) then

begin

k := j+1;

break;

end;

Trang 12

cd[j+1] := cd[j];

end;

cd[k] := x;

end;

end;

(* Sap nhanh xau s *)

procedure Qsort(l, r: integer); var i, j, t, m: integer;

begin

i := l; j := r;

m := cd[(i+j) div 2];

while i <= j do

begin

while Sanh(cd[i], m) = -1do inc(i); while Sanh(cd[j], m) = 1 do dec(j);

if (i <= j) then

begin

t := cd[i];

cd[i] := cd[j];

cd[j] := t;

inc(i); dec(j);

end;

end;

Trang 13

if l < j then Qsort(l,j);

if i < r then Qsort(i,r);

end;

(* Sap nhanh xau s theo chi dan*) procedure SapChiDan;

var i: integer;

begin

for i := 1 to n do cd[i] := i;

Qsort(1,n);

end;

procedure BW;

var i: integer;

begin

n := length(s);

Saps;

w := '';

for i := 1 to n do

w := w + s[Pre(cd[i])];

for i := 1 to n do

if cd[i] = 1 then

begin

d := i;

exit;

Trang 14

end;

procedure EBW;

var i : integer;

begin

n := length(w);

Sapw;

s := '';

for i := 1 to n do

begin

d := cd[d];

s := s + w[d];

end;

end;

procedure RunBW(fn: string;gn: string); var f,g: text;

begin

clrscr;

assign(f,fn); reset(f);

assign(g,gn); rewrite(g);

while not eof(f) do

begin

readln(f,s);

Trang 15

writeln(g,w);

writeln(g,d);

end;

close(f); close(g);

end;

procedure RunEBW(fn: string;gn: string); var f,g: text;

begin

clrscr;

assign(f,fn); reset(f);

assign(g,gn); rewrite(g);

while not eof(f) do

begin

readln(f,w);

readln(f,d);

EBW;

writeln(g,s);

end;

close(f); close(g);

end;

BEGIN

RunBW('BW.PAS','BW.COD');

Trang 16

END.

Bài tập (Mã nhị phân - Đề dự tuyển Olimpic Quốc tế năm2001, Phần Lan) Cho xâu nhị

phân Việc quay và sắp theo trật tự từ điển đượcthực hiện như mô tả trong bài toán trên Biết cột cuối cùng của dãy đã sắp Hãytìm dòng đầu tiên của dãy.

Thí dụ, với xâu s = (10100).Sau khi quay và sắp ta thu được:

BC.OUT

00101

BC.INP

5

11000

00101

01001

01010

10010

10100

Biết cột cuối cùng là (11000)Chương trình của bạn phải xác định được dòng đầu tiên

là (00101)

Ngày đăng: 07/09/2012, 11:12

TỪ KHÓA LIÊN QUAN

w