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

Thuật toán sắp xếp

4 3,9K 27
Tài liệu đã được kiểm tra trùng lặp

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

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Tiêu đề Thuật Toán Sắp Xếp
Tác giả Tạ Tiến Đạt
Người hướng dẫn Thầy Nguyễn Xuân Huy
Trường học Standard format not all caps
Chuyên ngành Computer Science
Thể loại Essay
Năm xuất bản 2001
Thành phố Standard format not all caps
Định dạng
Số trang 4
Dung lượng 30 KB

Nội dung

Thuật toán sắp xếp

Trang 1

Lại bàn về giải thuật sắp xếp

Tạ Tiến Đạt

Các bạn thân mến!

Hôm nay qua bài viết này tôimuốn đề cập tới một thuật toán sắp xếp ổn định để giải bài

toán mã hóa Burrows (mà hẳn nhiều bạn đã quen thuộc).Nếu bạn nào chưa rõ về bài toán này có thể tìm đọc số báo tháng11 năm 2001, bài "Lựa chọn giải thuật sắp xếp " của thầy Nguyễn XuânHuy để rõ hơn

Sau đây tôisẽ đi ngay vào phân tích thuật toán sắp xếp mà tôi định nói đếnlà Sắp xếp bằng

phép đếm phân phối(Distribution Counting)

Yêu cầu bàitoán là cho một dãy khóa k1, k2 kn (nguyênkhông âm) và đưa ra dãy đã sắp tăng (hoặc giảm tùy ý)

Giả sử tađã xây dựng được dãy c1, c2 c(n+1) vớiý nghĩa ci là số lần xuất hiện của giá trị i trong dãy sốban đầu Dựa vào dãy biến đếm trên ta hoàn toàn có thể suy ra giátrị kj sẽ thuộc vào đoạn nào trong dãy sau khi sắp xếp Cụthể sau khi có dãy c ta xây dựng lại nó như sau:

c0= 0

c1= c0 + c1

c2= c0 + c1 + c2

cn= c0 + c1 + c2 + + cn

khi đó giátrị i trong dãy ban đầu khi được sắp tăng thì nó sẽ nằm ở đoạn ci-1 + 1 tới ci

và ta dễ dàngsuy ra dãy khóa sau khi sắp tăng dựa vào dãy c này

Ta có cách cài đặt củathuật toán như sau:

procedureDistributionCounting;

begin

fillchar(c, sizeof(c), 0);

for i := 1 to n do inc(c[k[i]]);

for i := 2 to n do c[i] := c[i-1] + c[i];

for i := n downto 1 do

begin

x[c[k[i]] := k[i]; {x là dãy khóa phụ chứa các giá trị của dãyk sau khi sắp}

dec(c[k[i]]);

end;

end;

Đánhgiá:

- Thuật toáncó độ phức tạp O(Max(M, n)) trong đó M là giá trị lớn nhất trong dãysố ban đầu, hơn hẳn thuật toán sắp xếp chèn và nổi bọt có độ phứctạp O(n2)

Trang 2

- Nhược điểmcủa thuật toán là với M quá lớn thì không thể biểu diễn được dãykhóa c, tuy nhiên với bài toán của chúng ta thì các kí tự chỉ có vịtrí trong bảng mã ≤ 255 mà thôi nên việc áp dụng thuật toán nàylà hoàn toàn có thể (ta sắp xếp dựa vào hàm Ord(ch: Char) trả

về vịtrí của kí tự ch trong bảng mã ANSI)

Dưới đâylà cách cài đặt của tôi với bài toán mã hóa BURROWS, áp dụng thuậttoán sắp xếp bằng phép đếm phân phối (với một chút thay đổi so vớiở trên):

{$A+,B-,D+,E+,F+,G-,I+,L+,N+,Ơ,P-,Q+,R+,S+,T-,V+,X+,Y+}

{$M16384,0,655360}

programCode;

const

inputfile = ’BURROWS.INP’;

outputfile = ’BURROWS.OUT’;

max = 1000;

maxC = 255;

var

a: array[0 max] of Char;

c: array[0 maxC] of integer;

id: array[0 max] of integer;

n, d: integer;

f, g: text;

procedureEnter;

begin

n := 0;

while not seekeoln(f) do

begin

inc(n);

read(f, a[n]);

end;

readln(f, d);

end;

procedureDistributionCounting;

var

i: integer;

begin

fillchar(c, sizeof(c), 0);

for i := 1 to n do inc(c[Ord(a[i])]);

for i := 2 to maxC do c[i] := c[i] + c[i - 1];

for i := n downto 1 do

begin

id[c[Ord(a[i])]] := i;

dec(c[Ord(a[i])]);

Trang 3

end;

end;

procedureProcess;

var

i: integer;

begin

fillchar(id, sizeof(id), 0);

DistributionCounting;

end;

procedureResult;

var

count: integer;

begin

count := 0;

repeat

write(g, a[id[d]]);

d := id[d];

inc(count);

until count = n;

writeln(g);

end;

procedureSolve;

begin

assign(f, inputfile); reset(f);

assign(g, outputfile); rewrite(g);

while not seekeof(f) do

begin

Enter;

Process;

Result;

end;

close(f); close(g);

end;

begin

Solve;

end

Các bạn có để ý tại saotrong thủ tục DistributionCounting, chúng ta lại cho duyệt ngược

dãy khóatừ cuối không? Điều đó là để đảm bảo cho tính ổn định của thuật toán, mặc dù

việc duyệt từ đầu hay từ cuối đều không ảnhhưởng tới việc sắp tăng giá trị của dãy khóa ban đầu

Ngày đăng: 11/09/2012, 15:26

TỪ KHÓA LIÊN QUAN

w