Sắp xếp một danh sách các đối tượng theo một thứ tự nào đó là một bài toán thường được vận dụng trong các ứng dụng tin học
Trang 1N i dung ội dung
I Mở đầu 2
II Phát biểu bài toán 2
III Phương pháp nghiên cứu 3
1 Phương pháp 3
2 Đánh giá các giải thuật xử lí ngoài 3
IV Thiết kế cấu trúc dữ liệu và giải thuật 4
1 sắp xếp bằng phương pháp trộn tự nhiên (Phương pháp 1) 4
1.1 Tư tưởng 4
1.2 Giải thuật 4
1.3 Cài đặt chương trình 8
1.4 Đánh giá giải thuật 11
2 sắp xếp ngoài bằng phương pháp trộn khác ( phương pháp 2) 11
2.1 Tư tưởng: 11
2.2 Giải thuật: 12
2.3 Cài đặt chương trình: 14
2.4 Đánh giá giải thuật: 16
3 Cải tiến sắp xếp trộn (phương pháp 3) 16
3.1 Tư tưởng 16
3.2 Giải thuật 16
3.3 Đánh giá giải thuật 18
4 Trộn nhiều đường (phương pháp 4) 19
4.1 Tư tưởng 19
Trang 24.2 Giải thuật 19 4.3 Cài đặt chương trình:( tham khảo chương trình chạy bằng C++) 21 4.4 Đánh giá giải thuật: 26
Trang 3I Mở đầu
Sắp xếp một danh sách các đối tượng theo một thứ tự nào đó là một bài toánthường được vận dụng trong các ứng dụng tin học Ví dụ ta cần sắp xếp danh sáchthí sinh theo tên với thứ tự Alphabet hoặc sắp xếp danh sách sinh viên theo điểmtrung bình từ cao đến thấp Một ví dụ khác là khi cần tìm kiếm một đối tượng trongmột danh sách các đối tượng bằng giải thuật tìm kiếm nhị phân thì danh sách các đốitượng này phải được sắp xếp trước đó
Tóm lại sắp xếp là một yêu cầu không thể thiếu trong khi thiết kế các phầnmềm Do đó việc nghiên cứu các phương pháp sắp xếp là rất cần thiết để vận dụngtrong khi lập trình
Ta đã biết đến các phương pháp sắp xếp trong và trong các giải thuật màchúng ta đề cập từ trước tới nay, chúng ta đã giả sử rằng số lượng các dữ liệu vào làkhá nhỏ để có thể chứa hết ở bộ nhớ trong (main memory) Nhưng điều gì sẽ xảy ranếu ta muốn xử lí phiếu điều tra dân số toàn quốc hay thông tin về quản lí đất đai cảnước chẳng hạn? Trong các bài toán như vậy số lượng dữ liệu vượt quá khả nănglưu trữ của bộ nhớ trong Để có thể giải quyết các bài toán đó chúng ta phải dùng bộnhớ ngoài để lưu trữ và xử lí
II Phát biểu bài toán
Các phương pháp như Bubble-Sort, QuickSort,…là sắp xếp trong làm việcvới dữ liệu nhỏ Nhiều ứng dụng sắp xếp quan trọng liên quan đến việc xử lí các tậptin có kích thước lớn, nên không có đủ bộ nhớ cho những tập tin quá lớn như vậy.Các phương pháp thích hợp cho những ứng dụng như vậy gọi là phương pháp sắpxếp ngoài, vì chúng liên quan đến xử lí dữ liệu bên ngoài đơn vị xử lí trung ương
Do đó chúng ta sử dụng sắp xếp ngoài để sắp xếp khi đối tượng cần sắp xếplớn không thể lưu trữ trên bộ nhớ trong mà phải lưu trữ trên bộ nhớ ngoài
Trang 4III Phương pháp nghiên cứu
Đọc
Đọc Mỗi lần đọc 1 mẫu tin Mỗi lần đọc 1 khối
2 Đánh giá các giải thuật xử lí ngoài
Đối với bộ nhớ ngoài thì thời gian tìm một khối để đọc vào bộ nhớ trong làrất lớn so với thời gian thao tác trên dữ liệu khối đó Vì vậy khi đánh giá các giảithuật thao tác trên bộ nhớ ngoài, chúng ta tập trung vào việc xét số lần đọc khối vào
bộ nhớ trong và số lần ghi khối ra bộ nhớ ngoài ta gọi chung là phép truy xuấtkhối(block access) Vì kích thước các khối là cố định nên ta không thể tìm cách tăngkích thước một khối mà chúng ta phải tìm các giảm số lần truy xuất khối
Bộ nhớ ngoài
Trang 5IV Thiết kế cấu trúc dữ liệu và giải thuật
1 sắp xếp bằng phương pháp trộn tự nhiên (Phương pháp 1)
1.1 Tư tưởng
Sắp xếp tập tin F, sử dụng 2 tập tin phụ F1 và F2
Thực hiện luân phiên 2 công việc:
- Tách tập tin lớn thành 2 tập tin con có thứ tự
- Trộn 2 tập tin con thành tập tin lớn có thứ tự
1.2 Giải thuật
Lặp lại các bước sau:
Phân đoạn F thành F1 và F2
- Trộn F1 và F2 vào F
Cho tới khi số đoạn trong F chỉ còn một
1.2.a Giải thuật phân đoạn
Phân file F thành 2 file F1 và F2
Bước 1: Mở file F để đọc, mở file F1 và F2 để ghi, khởi gán giá trị đầu số
đoạn con = 0 { sodoancon:=0 };
Bước 2: Thực hiện cho tới khi đọc hết file F
- Nếu chưa hết file F thực hiện việc đọc phần tử (PT) của F và ghi nó vào F1 cho đến khi gặp PT nhỏ hơn PT trước nó hoặc hết file F, tăng
số đoạn con lên 1, {inc(sodoancon)};
- Nếu chưa hết file F thực hiện việc đọc PT để của F và ghi nó vào F2 cho đến khi gặp PT nhỏ hơn PT trước nó hoặc hết file F; tăng số đoạn con lên 1, {inc(sodoancon)};
Trang 6Phân file F thành 2 file F1 và F2
Trộn các đoạn con có thứ tự trong file F1 và file F2 vào file F, biến
numsubfile là số đoạn con có trong F
Bước 1: Mở file F1, F2 để đọc, mở file F để ghi;
3 65
Trang 7Bước 2: Đọc PT đầu tiên của file F1 vào biến x và phần tử đầu tiên của F2 vào biến y.
Thực hiện cho tới khi đọc hết file F1 và F2
(i) Thực hiện cho tới khi hết đoạn con trong F1 hoặc hết đoạn con trong F2
i1. Nếu phần tử x của F1 < phần tử y của F2 thì di chuyển x vào F và đọc phần tử tiếp theo của F1
i2. Nếu phần tử x của F1 > phần tử y của F2 thì di chuyển y vào F và đọc phần tử tiếp theo của F2
Bước 3: Nếu file F1 chưa kết thúc thì ghi các phần tử còn lại của nó sang F, ngược lại nếu file F2 chưa kết thúc thì ghi các phần tử còn lại của nó sang F;Bước 4: Đóng file F1, F2, F;
Trang 9Phân file F thành 2 file F1 và F2.
Procedure phandoan(var F,F1,F2:fileType);
Trang 10Thủ tục sao 1 đoạn con từ file F vào file T
Procedure SaoDoancon(var F,T:FileType; var kt:boolean);
{Sao 1 doan con co thu tu F vao T}
Trang 11Giải thuật trộn các đoạn con có thứ tự trong file F1 và file F2 vào file F
Procedure Tron(var F,F1,F2:fileType);
Var kt1,kt2:boolean; v1,v2:infotype;
Trang 121.4 Đánh giá giải thuật
Trong GT phân đoạn hoặc trộn ta có thể dùng mảng hoặc DSLK để thay thế cho các file F1 và F2 nếu không gian bộ nhớ trong cho phép Độ phức tạp của GT
Để sắp xếp tập tin F có n mẩu tin ta sử dụng 4 tập tin F1, F2, G1, G2 Khởi đầu
ta phân phối các mẩu tin của tập tin F đã cho luân phiên vào hai tập tin F1, F2 Như vậy hai tập tin này được xem như được tổ chức thành các đường có độ dài 1
Trang 13Bước 1: Đọc 2 đường mỗi đường có độ dài 1 từ 2 tập tin F1, F2 và trộn đường
này thành đường độ dài 2 và ghi luân phiên vào trong hai tập tin G1, G2 Đổi vai trò của F1 cho G1, F2 cho G2
Bước 2: Đọc 2 đường, mỗi đường độ dài 2 từ hai tập tin F1, F2 và trộn hai
đường này thành đường có độ dài 4 và ghi luân phiên vào trong G1, G2 Đổi vai trò của F1 cho G1, F2 cho G2
Quá trình trên cứ tiếp tục và sau i bước thì độ dài của một đường là 2 Nếu
2i = n thì giải thuật kết thúc, lúc đó tập tin G2 sẽ rỗng và tập tin G1 sẽ chứa các mẩu tin đã được sắp xếp
Bước 1: Trộn các đường có độ dài 1 của F1 và F2 được các đường có độ dài 2 và
ghi luân phiên vào trong hai tập tin G1 và G2:
Trang 14Bước 2: Đổi vai trò F1 và G1, F2 và G2 cho nhau Trộn các đường độ dài 2 trong
tập tin F1 và F2 đựợc các đường có độ dài 4 rồi ghi luân phiên vào trong hai tập tin G1 và G2:
G1
G2
Bước 3: Đổi vai trò của F1 vaf G1, F2 và G2 cho nhau Trộn các đường có độ dài
4 trong hai tập tin F1 và F2 được các đường có độ dài 8 rồi ghi luân phiên vào trong hai tập tin G1 và G2:
G1:
F1
G2
Bước 4: Đổi vai trò của F1 và G1, F2 và G2 cho nhau Trộn các đường có độ dài 8
trong hai tập tin F1 và F2 được các đường có độ dài 16 rồi ghi luân phiên vào trong hai tập tin G1 và G2:
Trang 15Bước 5: Đổi vai trò của F1 và G1, F2 và G2 cho nhau Trộn các đường có độ dài
16 trong tập tin F1 và F2 được một đường có độ dài 21 rồi ghi vào trong tập tin G1:
Used: array[1 2] of interger;
Fin: array[1 2] of boolean;
Current: array[1 2] of RecordType;
else if i=1 then Read( f1,current[1] )
else read( f2, current[2]);
Trang 16While (not fin[1]) or (not fin[2]) do begin
if Fin[1] then x := 2
else if Fin[2] then x := 1 else if current[1].key < current[2].key then x :=1 else x :=2;
if ok then Write( g1, current[x] )
else Write( g2, currenrt[x] );
Trang 17được b mẫu tin thì mỗi bước cần đọc và ghi 2*2*n/2*b =2n/b khối mà chúng ta cần logn bước vậy tổng cộng chúng ta cần (2n/b)logn phép truy xuất khối vậy độ phức tạp của giải thuật này là: O(nlogn)
b Ưu điểm và nhược điểm của giải thuật:
Qua quá trình phân tích ta thấy giải thuật này có khả năng sắp xếp rất nhanh
vì chỉ sắp xếp từng khối nhỏ và độ phức tạp của nó O(nlogn) nhỏ hơn nhiều so với các phương pháp sắp xếp trong như sắp xếp chọn (Selection), sắp xếp xen (Insertion sort), sắp xếp nổi bọt (Bubble sort) có độ phức tạp là O(n)
Tuy nhiên bên cạnh đó ta cũng thấy khả năng truy xuất khối của nó phải nhiều nên mất thời gian
3 Cải tiến sắp xếp trộn (phương pháp 3)
3.1 Tư tưởng
Cũng giống như tư tưởng của sắp xếp trộn đầu tiên để sắp xếp tập tin F có n mẩu tin ta cũng sử dụng 4 tập tin F1,F2,G1,G2 Sau đó ta phân phối các mẩu tin đã cho F luân phiên vào trong 2 tập tin F1,F2 Nhưng cải tiến hơn sắp xếp trộn là ta
không chọn đường độ dài là 1 mà ta chọn một số k thích hợp sao cho k mẩu tin có
thể đủ nhớ trong bộ nhớ trong
3.2 Giải thuật
Để sắp xếp tập tin F có n mẩu tin ta cũng sử dụng 4 tập tin F1,F2,G1,G2.
Khởi đầu: Ta phân phối các mẫu tin của tập tin đã cho F luân phiên vào
trong 2 tập tin F1,F2 Ta giả sử bộ nhớ trong có thể chứa được k mẩu tin Như vậy 2 tập tin này được xem như được tổ chức thành các đương độ dài k.
Bước 1: Đọc 2 đường, mỗi đường độ dài k từ 2 tập tin F1,F2 và trộn 2 đường này thành đường độ dài 2k và ghi luân phiên vào 2 tập tin G1,G2 Đổi vai trò của F1
Trang 18Quá trình trên cứ tiếp tục và sau i bước thì độ dài của 1 đường là k*2 i Nếu
k*2 i > n thì giải thuật kết thúc,lúc đó tập tin G2 sẽ rỗng và tập tin G1 chứa các mẩu
tin được sắp
Ví dụ minh họa:
Lấy tập tin F có 21 mẫu tin với khóa là các số nguyên :
3 65 6 15 29 20 25 5 31 40 12 50 67 45 9 18 34 17 11 98 8
Ta giả sử bộ nhớ trong có thể chứa đươc 3 mẩu tin, ta đọc lần lượt 3 mẩu tin của F vào
bộ nhớ trong,dùng một sắp xếp trong để sắp xếp chúng và ghi phiên vào 2 tập tin F1 và F2
F1
F2
Bước 1: Trộn các đường độ dài 3 của F1 và F2 được các đường độ dài 6 và ghi luân
phiên vào trong 2 tập tin G1 và G2:
G1
G2
Bước 2:Đổi vai trò của F1 và G1,F2 và G2 cho nhau Trộn các đường độ dài 6 trong
2 tập tin F1 và F2 được các đường độ dài 1 rồi ghi luân phiên vào trong 2 tập tin G1
Trang 19Bước 3: Đổi vai trò của F1 và G1,F2 và G2 cho nhau Trộn các đường độ dài 12
trong 2 tập tin F1 và F2 được 1 đường ghi vào trong tập tin G1,còn G2 rỗng :
3 5 6 8 9 11 12 15 17 18 20 25 29 31 34 40 45 50 65 67 98
Tập tin G1 chứa các mẩu tin đã được sắp còn tập tin G2 rỗng
3.3 Đánh giá giải thuật
a Độ phức tạp:
Ta thấy quá trình sắp xếp trộn nói trên bắt đầu từ các độ dài 1 cho nên phải
sau logn bước giải thuật mới kết thúc Chúng ta có thể tiết kiệm thời gian bằng cách chọn một số k thích hợp sao cho k mẩu tin có thể đủ chứa trong bộ nhớ trong Mỗi lần đọc vào bộ nhớ trong k mẩu tin,dùng sắp xếp trong(chẳng hạn dùng Quick sort)
để sắp xếp k mẩu tin này và ghi luân phiên vào hai tập tin F1 và F2 Như vậy chúng
ta bắt đầu sắp xếp trộn với các tập tin dược tổ chức thành các đường độ dài k
Sau i bước thì độ dài mỗi đường là k*2 i Giải thuật sẽ kết thúc khi k*2 i ≥ n
hay i ≥ log n/k Do đó số phép truy xuất khối sẽ là 2*n/b log(n/k)
Dễ thấy 2*n/b log(n/k) < 2*n/b logn tức là ta tăng được tốc độ sắp xếp trộn Vậy độ phức tạp của giải thuật này là: O(nlog(n/k))
b Ưu điểm, nhược điểm:
Trang 204 Trộn nhiều đường (phương pháp 4)
4.1 Tư tưởng
Sắp xếp tập tin F ta dùng m tập tin F1, F2 ,F3… Fm( m là số chẵn, m>4)+ Tách tập tin F thành h tập tin F[1], F[2], F[3],…… F[h] với h=m/2
+ Trộn các tập tin con trong h tập tin F[1], F[2], F[3],…… F[h] thành tập tin lớn có thứ tự rồi ghi luân phiên vào trong F[h+1], F[h+2], F[h+3],… F[m]
Bước 1: _ Trộn các đường độ dài k của h tập tin F[1], F[2], F[3],…… F[h] thành một đường độ dài k*h
_ Ghi luân phiên vào trong h tập tin F[h+1], F[h+2], F[h+3], F[m] _ Đổi vai trò của F[i] và F[h+i] cho nhau
Bước 2: _ Trộn các đường độ dài k*h của h tập tin F[1], F[2], F[3],…… F[h] thành một đường độ dài k*h2
_ Ghi luân phiên vào trong h tập tin F[h+1], F[h+2], F[h+3],… F[m] _ Đổi vai trò của F[i] và F[h+i] cho nhau
Sau i bước thì ta được độ dài mỗi đường là k*hi và giải thuật kết thúc khi k*hi>=n và khi đó ta được tập tin đã sắp xếp chính là 1 đường ghi trong F[h+1]
Ví dụ:
Lấy tập tin F có 21 mẫu tin với khóa là các số nguyên như ví dụ ban đầu
Trang 21Ta sử dụng 6 tập tin để sắp xếp tập tin F Cho k=3 Ta lầ lượt đọc 3 mẫu tin của F vào bộ nhớ trong, dùng sắp xếp trong để sắp xếp và ghi luân phiên vào 3 tập tin F[1], F[2], F[3] :
3 65 6 15 29 20 25 5 31 40 12 50 67 45 9 18 34 17 11 98 8
F[1]
F[2]
F[3]
Bước 1: Trộn các đường độ dài 3 trong các tập tin F[1], F[2], F[3] thành các
đường độ dài 9 và ghi vào trong các tập tin F[4], F[5], F[6]
F[4]
F[5]
F[6]
Đổi vai trò của F[1] cho F[4], F[2] cho F[5], F[3] cho F[6]
Bước 2: Trộn các đường độ dài 9 trong các tập tin F[1], F[2], F[3] thành 1 đường độ dài 23 và ghi vào trong tập tin F[4]
Trang 224.3 Cài đặt chương trình:( tham khảo chương trình chạy bằng C++)
Trang 23memcpy(&x,&X.buffer,sizeof(elem)); //gan buffer cho x
fread(&X.buffer,sizeof(elem),1,X.f); //luc nay X^ chinh la buffer
}
void copyitem(tape &X,tape &Y,int &EOR) //copy 1pt tu tape X vao Y co ktra EOR{
elem x;
readtape(X, x); //doc pt tu tape X vao x
fwrite(&x,sizeof(elem), 1, Y.f); //ghi truc tiep vao file Y
EOR=feof(X.f) || x>X.buffer; //(x>X.buffer)tra ve eof(ss dung compaid)}
//chep 1 run
void copyrun(tape &X,tape &Y)
{
int EOR;
Trang 26mx = i;
copyitem(f[ta[mx]], f[t[j]], EOR);
if(feof(f[ta[mx]].f)){
if (EOR){
k2 ;
hoanvi(ta[mx], ta[k2]);
}} while (k2>0);
Trang 27Ta thấy giải thuật kết thúc khi k.hi>=n hay i>=logh(n/k) Mỗi bước ta phải đọc
từ h tập tin và ghi vào h tập tin, mỗi tập tin có trung bình n/h mẩu tin Giả sử mỗi một khối lưu trữ được b mẫu tin thì mỗi bước cần đọc và ghi 2*h*n/h*b =2n/b khối
mà chúng ta cần log(n/k) bước Vậy tổng cộng chúng ta cần (2n/b)logh(n/k) phép
truy xuất khối Vậy độ phức tạp của giải thuật này là: O(nlog h (n/k))
b Ưu điểm và nhược điểm của giải thuật:
Ưu điểm: Với bài toán dữ liệu lớn thì giải thuật này giúp:
- Chúng ta giảm được số lần truy xuất khối đi rất nhiều tức là tăng được tốc độ sắp xếp trộn
- Chương trình ngắn gọn hơn, không phải đọc và ghi nhiều lần