Tải bản đầy đủ (.doc) (4 trang)

Tài liệu Thuật toán sắp xếp nổi bọt (buble sort): doc

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 (57.75 KB, 4 trang )

Thuật toán sắp xếp nổi bọt (buble sort):
Trong thuật toán này, các giá trị trong mảng sẽ được duyệt từ cuối lên đầu, tại mỗi bước sẽ so sánh giá trị
của 2 phần tử kề nhau. nếu chúng bị ngược thứ tự thì đổi lại vị trí. Sau 1 lần như vậy thì phần tử có giá trị
nhỏ nhất sẽ được chuyển về đầu mảng. và quá trình tiếp tục duyệt từ cuối đến phần tử thứ 2, rồi từ cuối
đến phần tử thứ 3, ... sở dĩ gọi là nổi bọt vì quá trình so sánh giữa các cặp phần tử giống như "bọt" nổi
trên mặt nước.
Thuật toán này có độ phức tạp là O(n^2).
Sắp thứ tự các phần tử của một danh sách:
X1, X2,…, Xn
Sao cho (theo một trường khóa nào đó) chúng có thứ tự tăng dần:
X1 ≤ X2 ≤ … ≤ Xn
Hoặc có thứ tự giảm dần:
X1 ≥ X2 ≥ … ≥ Xn
Sắp xếp kiểu Nổi bọt (bubble sort) là một giải thuật sắp xếp đơn giản. Nó lặp đi lặp lại quá trình duyệt
danh sách cần sắp xếp, so sánh hai phần tử và đổi vị trí nếu chúng neu đứng sai vị trí.
Giải thuật như sau:
1.So sánh 2 phần tử cạnh nhau. Nếu phần tử trước lớn hơn phần tử sau thì đổi vị trí (swap) của
chúng cho nhau.
2.Thực hiện việc đó với mỗi cặp phần tử., từ cặp đầu tiên tới cặp cuối cùng. Tới thời điểm này,
phần tử cuối cùng sẽ là phần tử có giá trị lớn nhất.
3.Lặp lại các bước trên với các phần tử trừ phần tử cuối cùng. Cho tới khi không còn cặp nào cần
so sánh.
Heap là một cấu trúc dữ liệu , có thể được biểu diễn thông qua 2 cách :
-Dạng thứ 1: Dạng cây nhị phân có đặc điểm là node cha thì lớn hơn 2 node con trực tiếp của nó .
-Dạng thứ 2: nếu ta đánh số các node theo thứ tự từ trên xuống và từ trái qua . Bắt đầu là node root = 0 ,
thì ta có thể định nghĩa heap thông qua mảng một chiều , có đặc điểm là phần tử thứ k sẽ lớn hơn các
phần tử thứ 2k+1 và 2k+2 . Ta có thể dễ nhận thấy là phàn tử thứ 0 sẽ tương ứng với root trong cây ở
cách biểu diễn thứ 1
Nguyên tắc sắp xếp của heap sort
Dựa vào tính chất của heap trong cách biểu diễn thứ 1 và thứ 2 , ta có thể thấy phần tử đầu tiên trong
cách biểu diễn theo mảng sẽ là phần tử lớn nhất ---> cách sắp xếp đơn giản là : ( Gọi mảng ban đầu là A )


Khởi tạo : Tạo heap từ mảng ban đầu đã cho (mảng A)
1. Lấy phần tử đầu tiên trong mảng ra bỏ vào mảng kết quả
2. Tạo lại heap từ mảng A
3. Quay lại bước 1
VD : Ta lấy một mảng đã được tạo thành một heap :
y r p d f b k a c
Lấy phần tử đầu tiên là y bỏ vào mảng kết quả C = { y }
khi này A = r p d f b k a c
Tạo heap A = r f p d c b k a
Lấy phần tử đầu tiên ra là r bỏ vào mảng C = { r y }
Khi này A = { f p d c b k a }
1
Tạo heap cho A = { p f k d c b a}
Lấy phần tử đầu tiên ra là p bỏ vào mảng C = { p r y }
Khi này A = { f k d c b a }
Tạo heap cho A = { k f b d c a}
Lấy phần tử đầu tiên ra là k bỏ vào mảng C = { k p r y }
Khi này A = { f b d c a }
Tạo heap cho A = { f d b a c}
Lấy phần tử đầu tiên ra là f bỏ vào mảng C = { f k p r y }
Khi này A = { b d c a }
Tạo heap cho A = { d c b a}
Lấy phần tử đầu tiên ra là d bỏ vào mảng C = {d f k p r y }
Khi này A = { c b a }
Tạo heap cho A = { c a b }
Lấy phần tử đầu tiên ra là c bỏ vào mảng C = {c d f k p r y }
Khi này A = { b a }
Tạo heap cho A = { b a }
Lấy phần tử đầu tiên ra là b bỏ vào mảng C = {b c d f k p r y }
Khi này A = { a }

Tạo heap cho A = { a }
Kết thúc ta có được mảng C đã có thứ tự .
Cải tiến: Ta có thể hạn chế việc sử dụng thêm mảng C bằng cách tận dụng luôn mảng A ban
đầu . Ta làm như sau
A = y r p d f b k a c
Bước 1 :
- Lấy y ra
- Lấy c ra
- Bỏ y vào chổ của c .
- Bỏ c vào chỗ của y
Khi ta bỏ y vào chỗ của c thì giống như ta bỏ y vảo mảng C .
Khi này mảng A sẽ coi như gồm 2 phần A = c r p d f b k a ---- y
Bước 2 : tạo heap cho phần đứng trước của A là c r p d f b k a. Phần sau là chứa y để nguyên
Ta sẽ có A mới là : r f p d c b k a -- y
Quay lại bước 1: Lấy r , a ra và swap r và a
A sẽ thành A= a f p d c b k -- r y
Tạo heap cho A = p f k d c b a -- r y
...........
Làm tương tự đến khi kết thúc
Qua VD ta thấy rằng phần quan trọng nhất là làm sao sinh ra heap từ một mảng cho trước
2
Sau đây là phần code cho phần cải tiến
Giải thuật
Post Condition : Dùng để phục hồi lại heap .
Pre Condition :
Ta sẽ có A mới là : r f p d c b k a -- y
Quay lại bước 1 : Lấy r , a ra và swap r và a
A sẽ thành A= a f p d c b k -- r y
Tạo heap cho A = p f k d c b a -- r y
Thì khi này current chính là a, low là 0

Phần Heap Sort nhưng có 1 chút rắc rối với phần tử đầu tiên a[0], vì nếu áp dụng công thức các phần tử
liên đới thì với i=0 -> 2*i=0 và 2*1+1=1 !!! đáng lẻ ra phải là a[0],a[1],a[2] mới đúng. Do đó nó kô đụng
chạm gì đến a[0] hết. Các bác có cao kiến gì kô :
Phương pháp merge
VD ta có
12 13 45 32 100 34 65 10
Ta có ở trên là 8 phần tử cần được sắp xếp :
Ý tưởng của merge sort là thay vì sắp xếp 8 phần tử (khó sắp ) thì ta chia đôi dãy đó ra làm đôi (số phần
tử nhỏ hơn --> sắp dễ hơn ) và sắp xếp các dãy con rồi ghép 2 dãy con lại ( gọi là merge 2 dãy con )
Vậy ta làm như sau:
Chia đôi --> được hai dãy con mới là 12 13 45 32 và 100 34 65 10
sắp 2 dãy con lại : 12 13 45 32 gọi là dãy A
100 34 65 10 gọi là dãy B
+ Muốn sắp A ta cũng làm y như trên
Chia đôi A , được 2 dãy mới là A11 = { 12 13 } A12 = {45 32 }
Chia đôi B được 2 dãy mới là B11 = {100 34} B12 = {65 10 }
+ Sắp xếp A11, B11 , A12 , B12
+ Muốn sắp xếp A11 thì ta cũng chia đôi đến khi sắp được ta có 2 dãy con là A21 = {12} A22 = { 13}
Sắp 2 dãy con trên được ( đơn giản vì chỉ có một phần tử ) là A21 = {12 } A22 = {13}
Sắp xong thì ta merge lại thành A11 = { 12 13 }
+ Tương tự sắp xếp cho B11 , A12 , B12 ta cũng có
B11 = {34 100} B12 = {10 65 } A12 = {32 45 }
+Sắp xếp xong , ta sẽ merge lại A11 , A12 thành A = { 12 13 32 45 }
B11 , B12 thành B = { 10 34 65 100 }
Sắp xong A , B , ta sẽ merge chúng lại thành dãy ban đầu :
{10 12 13 32 34 45 65 100 }
Phương pháp merge:
VD A = { 12 13 32 45 }
B = { 10 34 65 100}
-Đầu tiên lấy phần tử đầu tiên của A và B : 12 và 10

-10 < 12 nên ta lấy 10 bỏ vào mảng kết quả là C = {10}
-Giử lại số 12 , và lấy tiếp phần tử thay thế 10 trong mảng B là 34
-So sánh 12 và 34 . 12 < 34 , lấy 12 ra và bỏ vào C = {10 12}
-Giử lại 34 . Lấy phần tử kế tiếp để thay cho 12 trong mảng A là 32
-So sánh 32 và 34 chọn 32 bỏ vảo C = { 10 12 32 }
........ Làm tương tự ......
Đến bước cuối cùng A hết phần tử B còn lại B = { 65 100}
Ta sẽ bỏ toàn bộ mảng B vào C . Kết quả C đã được merge và có thứ tự
Giải thuật:(cho trường hợp dùng list để chứa các phần tử cần sort)
Sortable_List là một lớp list có đặc điểm là có hàm sort
Node là một template class biểu diễn cho các node trong list
3
Record là class dùng để biểu diễn data cần sắp xếp . ( VD như sắp một dãy các số nguyên , hay VD là sắp
theo tên của các record bao gồm tên , tuổi , số điện thoại ...)
sublist là list cần sắp xếp
Phương pháp Quick Sort
Thuật toán dựa trên kỹ thuật chia để trị, được đề xuất bởi C.A.R Hoare. Ý tưởng như sau:
- Sắp xếp dãy khóa k[1..n] thì có thể coi là sắp xếp đoạn từ chỉ số 1 tới chỉ số n trong dãy khóa đó.
- Nếu đoạn đó có ít hơn 2 khóa thì không cần làm gì cả,
- Nếu đoạn đó có ít nhất 2 khóa, ta chọn một khóa ngẫu nhiên nào đó làm chốt (pivot). Mọi khóa nhỏ hơn
khóa chốt được xếp vào vị trí đứng trước chốt, mọi khóa lớn hơn chốt được xếp vào vị trí sau chốt. Sau
phép hoán chuyển như vậy thì đoạn đang xét được chia làm 2 đoạn khác rỗng mà mọi khóa trong đoạn
đầu đều <= chốt và mọi khóa trong đoạn sau đều >=chốt.Vấn đề trở thành sắp xếp 2 đoạn mới được tạo
ra (độ dài ngắn hơn độ dài đoạn ban đầu) bằng phương pháp tương tự (gọi đệ quy)
- Độ phức tạp là O(n*lgn):
Selection Sort Nguyên tắc :
Chia mảng cần sắp thành 2 phần
Phần đã được sắp và phần chưa được sắp :
<A = phần được sắp> < B= phần chưa được sắp>
C = phần tử đầu tiên của B

Bước 1 : Tìm trong B phần tử lớn nhất max_key
Bước 2 : swap C và max_key ( hoán đổi vị trí )
Bước 3 : Bỏ max_key vào A . Khi này A mới = { A cũ , max_key } .
Quay lại bước 1
4

×