Tải bản đầy đủ (.pdf) (60 trang)

Các phương pháp sắp xếp trong

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (852.54 KB, 60 trang )

ĐẠI HỌC ĐÀ NẴNG
TRƯỜNG ĐẠI HỌC SƯ PHẠM
KHOA TIN
----------

LÊ PHƯỚC HUYỀN

SẮP XẾP TRONG

KHÓA LUẬN TỐT NGHIỆP

-1-


LỜI CẢM ƠN
Bốn năm học tại trường Đại Học Sư Phạm, các thầy cô đã trang bị cho em
kiến thức lẫn kỹ năng sống. Vì vậy em muốn gởi lời cảm ơn đến Ban Giám Hiệu
nhà trường, các thầy cô đã giúp em có một hành trang kiến thức khá vững vàng
cho tương lại.
Trải qua 4 tháng thực hiện, vận dụng những gì đã học được và cũng học
được thêm nhiều điều, giờ thì luận văn tốt nghiệp cũng đã hồn thành. Để có
được kết quả này, đó khơng phải là cơng sức của một mình em làm ra, mà cịn
có sự hỗ trợ hết mình từ gia đình, thầy cô và bạn bè.
Đầu tiên em xin gởi đến PGS.TSKH.Trần Quốc Chiến lời cảm ơn chân
thành nhất, thầy là giảng viên trực tiếp hướng dẫn em trong suốt quá trình
nghiên cứu và thực hiện đề tài này. Thầy đã tận tình hướng dẫn, cung cấp tài liệu
cần thiết để em và các bạn trong nhóm luận văn do thầy hướng dẫn có thể hồn
thành luận văn một cách tốt nhất.
Kế đến em xin gởi đến những người thân yêu trong gia đình mình, những
người ln ủng hộ em khơng chỉ trong thời gian qua mà còn cả những ngày
tháng sau này.


Và lời cảm ơn cuối cùng dành cho những người bạn đáng quý đã cùng em
vượt qua những khó khăn, luôn chia sẽ những kiến thức trong học tập, những
vui buồn trong cuộc sống. Cảm ơn các bạn!
Với lượng thời gian có hạn và điều kiện của một sinh viên, luận văn
khơng tránh khỏi những hạn chế và sai sót. Em kính mong nhận được lời góp ý
chân thành của quý thầy cô và bạn bè gần xa.
SVTH: LÊ PHƯỚC HUYỀN

-2-


MỤC LỤC
LỜI CẢM ƠN ......................................................................................................... 2
MỤC LỤC ............................................................................................................... 3
MỞ ĐẦU ................................................................................................................. 5
1. Lý do chọn đề tài ..............................................................................................5
2. Mục đích nghiên cứu ........................................................................................5
3. Nhiệm vụ nghiên cứu .......................................................................................6
4. Đối tượng và phạm vi nghiên cứu ....................................................................6
5. Phương pháp nghiên cứu ..................................................................................6
CHƯƠNG I THUẬT TOÁN VÀ ĐỘ PHỨC TẠP........................................... 6
1.1 Khái niệm giải thuật ........................................................................................7
1.2 Các đặc trưng của giải thuật ...........................................................................7
1.3 Ngơn ngữ giải thuật ........................................................................................7
1.4 Độ phức tạp tính toán của giải thuật ...............................................................8
1.5 Biểu diễn thời gian chạy của thuật giải ..........................................................9
1.6 Xác định độ phức tạp tính toán của giải thuật ..............................................10
1.6.1 Qui tắc cộng ..........................................................................................10
1.6.2 Qui tắc nhân ..........................................................................................11
1.6.3 Qui tắc tổng quát để phân tích một chương trình .................................11

1.7 Phân tích các chương trình đệ quy................................................................11
1.7.1 Thành lập phương trình đệ quy .............................................................11
1.7.2 Giải phương trình đệ quy .......................................................................12
CHƯƠNG II PHƯƠNG PHÁP SẮP XẾP TRONG ........................................ 15
2.1 SELECTION SORT .....................................................................................15
2.2 INSERTION SORT ......................................................................................17
2.3 BUBBLE SORT ...........................................................................................19
2.4 INTERCHANGE SORT ( đổi chỗ trực tiếp) ............................................21
2.5 SHELL SORT ...............................................................................................23
2.6 QUICKSORT................................................................................................27
2.7 HEAPSORT ..................................................................................................36
-3-


2.8 BINSORT .....................................................................................................41
2.9 MERGE SORT .............................................................................................45
2.10 RADIXSORT..............................................................................................50
CHƯƠNG III CHƯƠNG TRÌNH MINH HỌA ............................................. 54
3.1 Tổng quan về phần mềm: .............................................................................54
3.2 Hướng phát triển của phần mềm: ................................................................56
KẾT LUẬN ........................................................................................................... 57
TÀI LIỆU THAM KHẢO ................................................................................... 57

-4-


MỞ ĐẦU
1. Lý do chọn đề tài
Nếu muốn lập trình được một phần mềm giúp ích cho cuộc sống thì ngồi
nắm vững về ngơn ngữ lập trình chúng ta cần phải nắm vững về thuật tốn. Vì

vậy mơn học CẤU TRÚC DỮ LIỆU và GIẢI THUẬT được xem là môn học
đóng vai trị nền tảng cơ bản đối với những ai bắt đầu bước vào thế giới lập
trình. Mơn học giúp chúng ta hiểu rõ bản chất của các thuật toán biết được độ
phức tạp của của từng phương pháp nhờ đó chúng ta có thể lựa chọn cách lập
trình tốt nhất. Và sắp xếp các số liệu là một yêu cầu không thể thiếu đối với các
phần mềm do đó bất cứ lập trình viên nào cũng phải nắm vững kiến thức về lĩnh
vực này từ đó chọn được phương pháp sắp xếp phù hợp với người sử dụng và số
liệu nhập vào.
Vì vậy em chọn đề tài “ sắp xếp trong ” để đi sâu, nắm vững kiến thức
một cách sâu sắc có hệ thống.
2. Mục đích nghiên cứu
Đồ án này sẽ trình bày một số phương pháp sắp xếp trong. Mục đích là sau
khi nghiên cứu chúng ta sẽ nắm vững các phần sau của mỗi phương pháp:
Đánh giá
Ý tưởng

Minh họa
PP Sắp xếp

Chương
Trình

Giải Thuật

-5-


3. Nhiệm vụ nghiên cứu
Nghiên cứu về ý tưởng, thuật toán, của từng phương pháp “ sắp xếp trong
”. Sau đó cài đặt chương trình minh hoạ cho đề tài.

Đánh giá về độ phức tạp của từng phương pháp “sắp xếp trong” và rút ra
ưu, khuyết điểm của từng phương pháp sắp xếp.
Qua đó chúng ta rút ra kết luận mỗi phương pháp sắp xếp trong nên dùng
trong từng bài tốn nào.
4. Đối tượng và phạm vi nghiên cứu
Có rất nhiều phương pháp sắp xếp trong nhưng đề tài chỉ nghiên cứu các
phương pháp “ sắp xếp trong ” cơ bản sau đây:
1.Selection sort

2.Insertion sort

3.Shell sort

4.Heap sort

5.Interchange sort

6.Bubble sort

7.Quick sort

8.Merge sort

9.Binsort

10.Radixsort

5. Phương pháp nghiên cứu
-Thu thập, phân tích các tài liệu liên quan đến sắp xếp trong
-Phân tích bài tốn, xây dựng chương trình đệ quy

-Tổng hợp kết quả.

-6-


CHƯƠNG I
THUẬT TOÁN VÀ ĐỘ PHỨC TẠP
1.1 Khái niệm giải thuật
Giải thuật là một khái niệm quan trọng của toán học. Giải thuật là một dãy
xác định, hữu hạn các thao tác mà sau khi thực hiện chúng một cách tuần tự ta sẽ
được kết quả mong muốn. “ Hữu hạn ” được hiểu là cả về mặt thời gian thực
hiện lẫn công cụ thực hiện.
1.2 Các đặc trưng của giải thuật
* Tính dừng : Sau một bước hữu hạn giải thuật phải dừng.
* Tính xác định : Các bước của thao tác phải rõ ràng, không gây sự nhập
nhằng. Nói rõ hơn là trong cùng một điều kiện, hai bộ xử lý cùng thực hiện một
bước của giải thuật phải cho kết quả như nhau.
* Tính hiệu quả : Giải thuật cần phải đúng đắn nghĩa là sau khi đưa dữ liệu
vào giải thuật sẽ hoạt động và đưa kết quả như ý muốn.
* Tính phổ dụng : Giải thuật có thể giải bất kỳ bài tốn nào trong lớp các bài
tốn. Cụ thể là giải thuật có thể có các đầu vào là các bộ dữ liệu khác nhau trong
một miền xác định.
* Yếu tố vào ra : Một giải thuật ln ln có một đối tượng vào và một đối
tượng ra.
1.3 Ngôn ngữ giải thuật
Giải thuật thường được mô tả bằng một dãy các lệnh. Bộ xử lý sẽ thực hiện
lệnh theo một trật tự nhất định cho đến khi gặp lệnh dừng thì kết thúc. Ngơn ngữ
giải thuật gồm 3 loại :
 Ngôn ngữ liệt kê từng bước
 Sơ đồ khối

 Ngôn ngữ cấu trúc

-7-


1.4 Độ phức tạp tính tốn của giải thuật
Với một bài tốn khơng chỉ có một giải thuật. Chọn một giải thuật đưa tới kết
quả nhanh nhất là một đòi hỏi thực tế. Như vậy cần có một căn cứ nào đó để nói
rằng giải thuật này nhanh hơn giải thuật kia ?.
Thời gian thực hiện một giải thuật bằng chương trình máy tính phụ thuộc
vào nhiều yếu tố. Một yếu tố cần chú ý nhất là kích thước của dữ liệu vào. Dữ
liệu càng lớn thì thời gian xử lý càng chậm, chẳng hạn như thời gian sắp xếp
một dãy số phải chịu ảnh hưởng của số lượng các số thuộc dãy số đó. Nếu gọi n
là kích thước dữ liệu đưa vào thì thời gian thực hiện của một giải thuật có thể
biễu diễn một cách tương đối như một hàm của n: T(n).
Phần cứng máy tính, ngơn ngữ viết chương trình và chương trình dịch ngơn
ngữ ấy đều ảnh hưởng tới thời gian thực hiện. Những yếu tố này khơng giống
nhau trên các loại máy, vì vậy không thể dựa vào chúng khi xác định T(n). Tức
T(n) không thể biểu diễn bằng đơn vị giờ, phút, giây được. Tuy nhiên, khơng
phải vì thế mà khơng thể so sánh được các giải thuật về mặt tốc độ. Cách đánh
giá thời gian thực hiện giải thuật độc lập với máy tính và các yếu tố liên qua tới
máy tính sẽ dẫn tới khái niệm gọi là: Độ phức tạp tính tốn của giải thuật. Kí
hiệu O
Giả sử T(n) và g(n) là các hàm thực không âm của đối số ngun khơng âm
n. Trong đó thời gian thực hiện giải thuật được biểu diễn là T(n) và có độ phức
tạp O( g(n) ). Hàm T(n) được gọi là O(g(n)) nếu tồn tại các hằng số dương c và
n0 sao cho T(n) <= cg(n) với mọi n >= n0. Như vậy, T(n) = O(g(n)) có nghĩa là
hàm T(n) bị chặn trên bởi hàm g(n) với một nhân tử hằng nào đó khi n đủ lớn.
Muốn chứng minh được T(n)= O(g(n)), chúng ta cần chỉ ra nhân tử hằng c, số
nguyên dương n0 và chứng minh được T(n) <= cg(n) với mọi n >= n0.

Ví dụ. Giả sử T(n) = 5n3+ 2n2+ 13n + 6
ta có: T(n) = 5n3+ 2n2+ 13n + 6 <= 5n3+ 2n3+ 13n3+ 6n3= 26n3. Bất đẳng thức
trên đúng với mọi n >= 1, và ta có n 0= 1, c = 26. Do đó, ta có thể nói T(n) =
O(n3).

-8-


Tổng quát nếu T(n) là một đa thức bậc k của n:
f(n) = aknk+ ak-1nk-1+ ... + a1n + a0 thì T(n) = O(nk).
Ký hiệu O(g(n)) xác định một tập hợp vô hạn các hàm bị chặn trên bởi hàm
g(n), cho nên ta viết T(n) = O(g(n)) chỉ có nghĩa T(n) là một trong các hàm đó.
Ví dụ: T(n) = O(n2) thì T(n) =O(75n2), T(n) = O(0,01n2), T(n) = O(n2+ 7n +
logn), T(n) = O(n3),..., tức là có vơ số hàm là cận trên.
1.5 Biểu diễn thời gian chạy của thuật giải
Thời gian chạy của thuật giải là một hàm của cỡ dữ liệu vào, ta gọi là hàm
T(n). Chúng ta sẽ biểu diễn thời gian chạy của thuật giải bởi ký hiệu:
T(n) = O(f(n)), biểu diễn này có nghĩa là thời gian chạy T(n) bị chặn trên bởi
hàm f(n). Thế nhưng như ta đã nhận xét, một hàm có vô số cận trên. Trong số
các cận trên của thời gian chạy, chúng ta sẽ lấy cận trên chặt để biểu diễn thời
gian chạy của thuật giải.
Định nghĩa. Ta nói f(n) là cận trên chặt của T(n) nếu
- T(n) = O(f(n)),
- Nếu T(n) = O(g(n)) thì f(n) = O(g(n)).
Nói một cách khác, f(n) là cận trên chặt của T(n) nếu nó là cận trên của
T(n) và ta khơng thể tìm được một hàm g(n) là cận trên của T(n) mà lại tăng
chậm hơn hàm f(n). Sau này khi nói thời gian chạy của thuật giải là O(f(n)),
chúng ta cần hiểu f(n) là cận trên chặt của thời gian chạy.
Nếu T(n) = O(1) thì điều này có nghĩa là thời gian chạy của thuật giải bị chặn
trên bởi một hằng số nào đó, và ta thường nói thuật giải có thời gian chạy hằng.

Nếu T(n) = O(n), thì thời gian chạy của thuật giải bị chặn trên bởi hàm tuyến
tính, và do đó ta nói thời gian chạy của thuật giải là tuyến tính.

-9-


Các cấp độ thời gian chạy của thuật giải và tên gọi của chúng được liệt kê như
sau:
Kí Hiệu

Tên Gọi

O(1)

Hằng

O(logn)

Logarit

O(n)

Tuyến tính

O(nlogn)

nlogn

O(n2)


Bình phương

O(n3)

Lập phương

O(2n)



Đối với một thuật giải, chúng ta sẽ đánh giá thời gian chạy của nó thuộc cấp
độ nào trong các cấp độ đã liệt kê trên. Trong bảng trên, chúng ta đã sắp xếp các
cấp độ thời gian chạy theo thứ tự tăng dần, chẳng hạn thuật giải có thời gian
chạy là O(logn) chạy nhanh hơn thuật giải có thời gian chạy là O(n),... Các thuật
giải có thời gian chạy là O(nk), với k = 1,2,3,..., được gọi là các thuật giải thời
gian chạy đa thức.
1.6 Xác định độ phức tạp tính tốn của giải thuật
Cách tính độ phức tạp của một giải thuật bất kỳ là một vấn đề khơng đơn
giản. Tuy nhiên ta có thể tn theo một số nguyên tắc sau:
1.6.1 Qui tắc cộng
Nếu T1(n) và T2(n) là thời gian thực hiện của hai đoạn chương trình
P1 và P2; và T1(n)=O(f(n)), T2(n)=O(g(n)) thì thời gian thực hiện của đoạn
hai chương trình đó nối tiếp nhau là T(n)=O(max(f(n),g(n))).

- 10 -


1.6.2 Qui tắc nhân
Nếu T1(n) và T2(n) là thời gian thực hiện của hai đoạn chương trình
P1và P2 và T1(n) = O(f(n)), T2(n) = O(g(n)) thì thời gian thực hiện của đoạn hai

đoạn chương trình đó lồng nhau là T(n) = O(f(n).g(n)).
1.6.3 Qui tắc tổng quát để phân tích một chương trình
 Thời gian thực hiện của mỗi lệnh gán, READ, WRITE là O(1), thời
gian thực hiện của một chuỗi tuần tự các lệnh được xác định bằng
qui tắc cộng. Như vậy thời gian này là thời gian thi hành một lệnh
nào đó lâu nhất trong chuỗi lệnh.
 Thời gian thực hiện cấu trúc IF là thời gian lớn nhất thực hiện lệnh
sau THEN hoặc sau ELSE và thời gian kiểm tra điều kiện. Thường
thời gian kiểm tra điều kiện là O(1).
 Thời gian thực hiện vòng lặp là tổng (trên tất cả các lần lặp) thời
gian thực hiện thân vịng lặp. Nếu thời gian thực hiện thân vịng lặp
khơng đổi thì thời gian thực hiện vịng lặp là tích của số lần lặp với
thời gian thực hiện thân vòng lặp.
1.7 Phân tích các chương trình đệ quy
Với các chương trình đệ quy, trước hết ta cần thành lập các phương trình đệ
quy, sau đó giải phương trình đệ quy, nghiệm của phương trình đệ quy sẽ là thời
gian thực hiện của chương trình đệ quy.
1.7.1 Thành lập phương trình đệ quy
Phương trình đệ quy là một phương trình biểu diễn mối liên hệ giữa T(n) và
T(k), trong đó T(n) là thời gian thực hiện chương trình với kích thước dữ liệu
nhập là n, T(k) thời gian thực hiện chương trình với kích thước dữ liệu nhập là
k, với k < n. Ðể thành lập được phương trình đệ quy, ta phải căn cứ vào chương
trình đệ quy.

- 11 -


Thơng thường một chương trình đệ quy để giải bài tốn kích thước n, phải có
ít nhất một trường hợp dừng ứng với một n cụ thể và lời gọi đệ quy để giải bài
tốn kích thước k (k

Để thành lập phương trình đệ quy, ta gọi T(n) là thời gian để giải bài tốn
kích thước n, ta có T(k) là thời gian để giải bài tốn kích thước k. Khi đệ quy
dừng, ta phải xem xét khi đó chương trình làm gì và tốn hết bao nhiêu thời gian,
chẳng hạn thời gian này là c(n). Khi đệ quy chưa dừng thì phải xét xem có bao
nhiêu lời gọi đệ quy với kích thước k ta sẽ có bấy nhiêu T(k). Ngồi ra ta cịn
phải xem xét đến thời gian để phân chia bài toán và tổng hợp các lời giải, chẳng
hạn thời gian này là d(n).
Dạng tổng quát của một phương trình đệ quy sẽ là:

C (n)

T ( n)  

 F (T (k ))  d(n) 
Trong đó C(n) là thời gian thực hiện chương trình ứng với trường hợp đệ quy
dừng. F(T(k)) là một đa thức của các T(k). d(n) là thời gian để phân chia bài
toán và tổng hợp các kết quả.
1.7.2 Giải phương trình đệ quy
Có ba phương pháp giải phương trình đệ quy:
1.- Phương pháp truy hồi
2.- Phương pháp đoán nghiệm.
3.- Lời giải tổng quát của một lớp các phương trình đệ quy.
1.7.2.1 Phương pháp truy hồi
Dùng đệ quy để thay thế bất kỳ T(m) với m < n vào phía phải của phương
trình cho đến khi tất cả T(m) với m > 1 được thay thế bởi biểu thức của các T(1)
hoặc T(0). Vì T(1) và T(0) ln là hằng số nên chúng ta có cơng thức của T(n)
chứa các số hạng chỉ liên quan đến n và các hằng số. Từ công thức đó ta suy ra
T(n).

- 12 -



1.7.2.2 Phương pháp đoán nghiệm
Ta đoán một nghiệm f(n) và dùng chứng minh quy nạp để chứng tỏ rằng
T(n) ≤ f(n) với mọi n. Thông thường f(n) là một trong các hàm quen thuộc như
2

3

n

logn, n, nlogn, n , n , 2 , n!.
Ðơi khi chúng ta chỉ đốn dạng của f(n) trong đó có một vài tham số chưa
xác định và trong quá trình chứng minh quy nạp ta sẽ suy diễn ra giá trị thích
hợp của các tham số.
1.7.2.3 Lời giải tổng quát cho một lớp các phương trình đệ quy
Ðể giải một bài tốn kích thước n, ta chia bài toán đã cho thành a bài toán
con, mỗi bài tốn con có kích thước

n
. Giải các bài toán con này và tổng hợp
b

kết quả lại để được kết quả của bài toán đã cho. Với các bài tốn con chúng ta
cũng sẽ áp dụng phương pháp đó để tiếp tục chia nhỏ ra nữa cho đến các bài
tốn con kích thước 1. Kĩ thuật này sẽ dẫn chúng ta đến một giải thuật đệ quy.
Giả thiết rằng mỗi bài tốn con kích thước 1 lấy một đơn vị thời gian và
thời gian để chia bài tốn kích thước n thành các bài tốn con kích thước

n


b

tổng hợp kết quả từ các bài toán con để được lời giải của bài toán ban đầu là
d(n).
n
b

Nếu gọi T(n) là thời gian để giải bài tốn kích thước n thì T( ) là thời gian
để giải bài tốn con kích thước

n
. Khi n = 1 theo giả thiết trên thì thời gian giải
b

bài tốn kích thước 1 là 1 đơn vị, tức là T(1) = 1. Khi n lớn hơn 1, ta phải giải đệ
n
b

quy a bài tốn con kích thước bn, mỗi bài toán con tốn T( ) nên thời gian cho a
n
b

lời giải đệ quy này là aT( ). Ngồi ra ta cịn phải tốn thời gian để phân chia bài
toán và tổng hợp các kết quả, thời gian này theo giả thiết trên là d(n).

- 13 -


Vậy ta có phương trình đệ quy:


if
1

T (n)   n
aT ( b )  d (n) if

n = 1


n >1


Ta sử dụng phương pháp truy hồi để giải phương trình này. Khi n >1 ta có

n
T (n)  aT ( )  d (n)
b
n
n
n
n
T (n)  a[aT ( 2 )]  d ( )]  d (n)  a 2T ( 2 )  ad ( )  d (n)
b
b
b
b
n
n
n

T (n)  a 2 [aT ( 3 )  d ( 2 )]  ad ( )  d (n)
b
b
b
n
n
n
 a3T ( 3 )  a 2 d ( 2 )  ad ( )  d (n)
b
b
b
T (n)  .................................
n i1 j a
T (n)  a T ( i )   a d ( j )
b
b
j 0
i

Giả sử n = bk, quá trình suy rộng trên sẽ kết thúc khi i = k.
Khi đó ta được T (

n
)  T (1)  1 . Thay vào trên ta có:
bk

k 1

T (n)  a   a j d (bk  j )
k


j 0

- 14 -


CHƯƠNG II
PHƯƠNG PHÁP SẮP XẾP TRONG
2.1 SELECTION SORT
2.1.1 Ý Tưởng
- Chọn phần tử nhỏ nhất đặt vào vị trí đầu tiên.
- Chọn phần tử nhỏ nhất trong số n - 1 phần tử cịn lại đặt vào vị trí thứ 2.
- Lặp lại quá trình trên cho đến khi mảng chỉ cịn 1 phần tử.
2.1.2 Thuật Tốn
Bước 1: Khởi tạo i = 1
Bước 2: Khởi đầu min = i, j = i + 1
Bước 3: Nếu a[j] < a[min] thì min = j, nếu khơng thì sang bước 4.
Bước 4: Tăng j thêm 1 đơn vị.
Bước 5: Nếu j < n thì quay lại bước 3, nếu khơng thì sang bước 6.
Bước 6: Đổi chỗ a[min] và a [i], tăng i lên 1 đơn vị.
Bước 7: Nếu i < n – 1 thì quay lại bước 2, nếu khơng thì kết thúc.
2.1.3 Minh họa
Sắp xếp mảng gồm 8 mẩu tin có khố là các số ngun:12,2,8,5,1,6,4,15
Khố
a[1]

a[2]

a[3]


a[4]

a[5]

a[6]

a[7]

a[8]

Bước
Ban đầu 12
Bước 1
Bước 2
Bước 3
Bước 4
Bước 5

1

2

8

5

1

6


4

15

2

8

5

12

6

4

15

2

8

5

12

6

4


15

4

5

12

6

8

15

5

12

6

8

15

6

12

8


15

8

12

15

12

15

Bước 6
Bước 7

- 15 -


Bước 8
Kết quả

15
1

2

4

5


6

2.1.4 Chương trình
PROCEDURE SelectionSort;
VAR
i,j,LowIndex: integer;
LowKey: KeyType;
BEGIN
{1} FOR i := 1 TO n-1 DO BEGIN
{2} LowIndex := i;
{3} LowKey := a[i].key;
{4} FOR j := i+1 TO n DO
{5} IF a[j].key < LowKey THEN
BEGIN
{6} LowKey := a[j].key;
{7} LowIndex := j;
END;
{8} Swap(a[i],a[LowIndex]);
END;
END;

- 16 -

8

12

15



2.1.5 Đánh giá
Cần thấy rằng thủ tục Swap lấy O(1) thời gian vì chỉ thực hiện 3 lệnh gán nối
tiếp nhau. Các lệnh (2), (3) đều lấy O(1) thời gian. Vịng lặp for (4) - (7) thực
hiện n-i lần, vì j chạy từ i+1 đến n, mỗi lần lấy O(1), nên lấy O(n-i) thời gian.
Do đó thời gian tổng cộng là:

2.2 INSERTION SORT
2.2.1 Ý tưởng
-Tại bước thứ i thì các phần tử từ a[1] đến a[i-1] đều có thứ tự tăng dần.
- Đầu tiên ta bắt đầu với i = 2 (a[1] khơng cần sắp)
- Tìm vị trí thích hợp để chèn a[2] vào đoạn a[0]…a[2]
- Kế tiếp, tìm vị trí thích hợp để chèn a[3] vào đoạn a[1]…a[3]
- Làm tiếp tục cho đến khi sắp được phần tử cuối cùng.
2.2.2 Thuật tốn
Bước 1: i = 2; { đoạn có 1 phần tử a[1] đã được sắp
Bước 2: x = a[i]; Tìm vị trí thích hợp trong đoạn a[1] đến a[i-1] để chèn
x vào.
Bước 3: Dời các phần tử từ vị trí tìm được đến a[i-1] sang phải 1 vị trí
để dành chổ cho a[i].
Bước 4: chèn x vào vị trí tìm được; { có đoạn a[1]..a[i] đã được sắp
Bước 5: i = i+1; Nếu i < N-1 : Lặp lại Bước 2. Ngược lại : Dừng

- 17 -


2.2.3 Minh họa
Xét mảng cho ở phần minh họa trên
a[1]

a[2]


a[3]

a[4]

a[5]

a[6]

a[7]

a[8]

Ban đầu

12

2

8

5

1

6

4

15


Bước 1

2

12

Bước 2

2

8

12

Bước 3

2

5

8

12

Bước 4

1

2


5

8

12

Bước 5

1

2

5

6

8

12

Bước 6

1

2

4

5


6

8

12

Bước 7

1

2

4

5

6

8

12

2.2.4 Chương trình
procedure InsertionSort;
var

i,j: integer;

begin

{1}

for i := 2 to n do begin

{2}

j := i;

{3}

while (j>1) and (a[j].key < a[j-1].key) do begin

{4}

swap(a[j], a[j-1]);

{5}

j := j-1;
end;
end;

end;

- 18 -

15


2.2.5 Đánh giá

Phương pháp sắp xếp xen lấy O(n) để sắp xếp n phần tử.
Ta thấy các lệnh {4} và {5} đều lấy O(1). Vòng lặp {3} chạy nhiều nhất i-1 lần,
mỗi lần tốn O(1) nên {3} lấy i-1 thời gian. Lệnh {2} và {3} là hai lệnh nối tiếp
nhau, lệnh {2} lấy O(1) nên cả hai lệnh này lấy i-1.
Vịng lặp {1} có i chạy từ 2 đến n nên nếu gọi T(n) là thời gian để sắp n phần tử
thì ta có

2.3 BUBBLE SORT
2.3.1 Ý tưởng
- Đưa dần các phần tử có khóa (giá trị) nhỏ về phía trước.
- Xuất phát từ cuối (đầu) dãy, đổi chỗ các cặp phần tử kế cận để đưa
phần tử nhỏ (lớn) hơn trong cặp phần tử đó về vị trí đúng đầu (cuối) dãy
hiện hành, sau đó sẽ khơng xét đến nó ở bước tiếp theo.
- Ở lần xử lý thứ i có vị trí đầu dãy là i.
- Lặp lại xử lý trên cho đến khi khơng cịn cặp phần tử nào để xét.
2.3.2 Giải Thuật
Bước 1: Xét các phần tử từ a[n] đến a[2], với mỗi phần tử a[j], so sánh
khố của nó với khố của phần tử a[j-1] đứng ngay trước nó. Nếu khố
của a[j] nhỏ hơn khố của a[j-1] thì hốn đổi a[i] và a[j-1] cho nhau.
Bước 2: Xét các phần tử từ a[n] đến a[3], và làm tương tự như trên.
Tổng quát ở bước thứ i, ta sẽ xét các phần tử từ a[n] đến
a[i+1].
Sau n bước ta thu được mảng có thứ tự.

- 19 -


2.3.3 Minh họa

Khoá


a[1]

a[2]

a[3]

a[4]

a[5]

a[6]

a[7]

a[8]

Ban đầu

12

2

8

5

1

6


4

15

Bước 1

1

12

2

8

5

4

6

15

2

12

4

8


5

6

15

4

12

5

8

6

15

5

12

6

8

15

6


12

8

15

8

12

15

12

15

12

15

Bước

Bước 2
Bước 3
Bước 4
Bước 5
Bước 6
Bước 7
Kết quả


1

2

4

5

2.3.4 Chương trình
procedure BubbleSort;
var
i,j: integer;
begin
(1)
(2)

for i := 1 to n-1 do
for j := n downto i+1 do

(3)

if a[j].key < a[j-1].key then

(4)

Swap(a[j],a[j-1]);

end;


- 20 -

6

8


2.3.5 Đánh giá
Phương pháp sắp xếp nổi bọt lấy O(n) để sắp n phần tử.
Dòng lệnh {3} lấy một hằng thời gian. Vòng lặp {2} thực hiện (n-i) bước, mỗi
bước lấy O(1) nên lấy O(n-i) thời gian. Như vậy đối với tồn bộ chương trình ta
có:

2.4 INTERCHANGE SORT ( đổi chỗ trực tiếp)
2.4.1 Ý Tưởng
- Xuất phát từ đầu dãy, tìm tất cả nghịch thế chứa phần tử này, triệt tiêu chúng
bằng cách đổi chỗ phần tử này với phần tử tương ứng trong cặp nghịch thế. Lặp
lại xử lý trên với các phần tử tiếp theo trong dãy.
2.4.2 Giải Thuật
- Bước 1: Khởi tạo i = 1 { bắt đầu từ đầu dãy
- Bước 2: j = i+1;

{tìm các cặp phần tử a[j] < a[i], j>i

- Bước 3: Trong khi j < n thực hiện
• Nếu a[j]• j = j+1;
- Bước 4: i = i+1;
• Nếu i < n-1: Lặp lại bước 2.


- 21 -


2.4.3 Minh họa

Khố

a[1]

a[2]

a[3]

a[4]

a[5]

a[6]

a[7]

a[8]

Ban đầu

12

2

8


5

1

6

4

15

i =1

1

12

8

5

2

6

4

15

2


12

8

5

6

4

15

4

12

8

6

5

15

5

12

8


6

15

6

12

8

15

8

12

15

12

15

12

15

Bước

i =2

i:=3
i:=4
i:=5
i:=6
i:=7
Kết quả

1

2

4

5

2.4.4 Chương trình
Procedure

interchangesort;

Var

i,j:integer;

Begin
For i:=1 to n-1 do
For j:=i+1 to n do
If a[j]Swap(a[i],a[j]);
End;


- 22 -

6

8


2.4.5 Đánh Giá
Dòng lệnh {3} lấy một hằng thời gian. Vòng lặp {2} thực hiện (n-i) bước,
mỗi bước lấy O(1) nên lấy O(n-i) thời gian. Như vậy đối với toàn bộ chương
trình ta có:

2.5 SHELL SORT
2.5.1 Ý Tưởng
Trong phương pháp sắp xếp kiểu chèn thì muốn chèn một khóa tại vị trí đầu
dãy thì đẫn đến hạn chế của thuật tốn này. Vì vậy để khắc phục nhược điểm
người ta có một phương pháp sắp xếp là shell sort.
Ý tưởng chính
Xét một dãy a[1]...a[n], cho một số nguyên h (1≤h≤n), ta có thể chia dãy
đó thành h dãy con như sau:
Dãy con 1 : a[1], a[1+ h], a[1+2h]...
Dãy con 2 : a[2], a[2+h], a[2+2h]...
Dãy con 3 : a[3], a[3+h], a[3+2h]…
……………………………
Dãy con h:a[h],a[2h],a[3h]…
Ví dụ:
Dãy ban đầu:

10


3

7

6

2

5

4

16 ( N=8

và h=3 )
Ta có dãy con sau:
Dãy 1: 10
Dãy 2:

6
3

Dãy 3:

4
2

7


16
5

Những dãy này được coi là những dãy con xếp theo độ dài bước h. Tư tưởng
chính của thuật tốn ShellSort là: Với mỗi bước h, áp dụng thuật toán sắp xếp
kiểu chèn từng dãy con độc lập để làm mịn dần các phần tử trong dãy chính.
- 23 -


Tiếp tục làm tương tự đối với bước (h div 2)... cho đến khi h = 1 thì ta được
dãy phần tử được sắp.Xét trong ví dụ trên, nếu chúng ta dùng phương pháp chèn
thì với phần tử a[5] = 2 là phần tử nhỏ nhất trong dãy, do đó nó phải chèn vào vị
trí thứ 1, tức là phải chèn trước 4 phần tử trước nó. Nhưng nếu chúng ta xem 2 là
phần tử của dãy 2 thì ta chỉ cần chèn trước một phần tử là 3. Đây chính là
ngun nhân thuật tốn ShellSort thực hiện hiệu quả hơn sắp xếp chèn. Khi đó
khóa nhỏ nhanh chóng đưa về gần vị trí đúng của nó.
2.5.2 Thuật tốn
Bước 1:
Chọn k khoảng cách h[1],h[2],…..,h[k] và i=1
Bước 2:
Chia dãy ban đầu thành các dãy con có bước nhảy là h[i].
Thực hiện sắp xếp từng dãy con bằng phương pháp chèn trực
tiếp.
Bước 3 :

i=i+1

Nếu i > k:Dừng.
Ngược lại: Về bước 2.


- 24 -


2.5.3 Ví dụ minh họa

Khố

a[1]

a[2]

a[3]

a[4]

a[5]

a[6]

a[7]

a[8]

10

3

7

6


2

5

4

16

Bước
Ban đầu
Dãy 1

5

10

h= 5
Dãy 2

4

3

Dãy 3

16

7


Dãy 4

6

Dãy 4

2

Kết quả

Khoá

5

3

7

6

2

10

4

a[1]

a[2]


5

3

16

a[3]

a[4]

a[5]

a[6]

a[7]

a[8]

7

6

2

10

4

16


Bước
Ban đầu
h= 3

Dãy 1

6

5

Dãy 2

4
2

3

Dãy 3

16
10

7

Kết quả

4

2


7

6

3

10

5

16

Với h=1 ta dùng phương pháp sắp xếp chèn trực tiếp sẽ được kết quả như sau:
2

3

4

5

6

7

Dãy trên đã có thứ tự

- 25 -

10


16


×