Ý tưởng chính của giải thuật là xuất phá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ế. [r]
(1)CHƯƠNG
CÁC THUẬT TOÁN SẮP XẾP
(2)• Chọn trực tiếp - Selection Sort
1
• Chèn trực tiếp - Insertion Sort
2
• Đổi chỗ trực tiếp - Interchange Sort
3
• Nổi bọt - Bubble Sort
4
• Sắp xếp dựa phân hoạch - Quick Sort
5
• Trộn trực tiếp - Merge Sort
6
(3)Các khái niệm
• Sắp xếp ?
– Sắp xếp trình xử lý danh sách phần tử (hoặc mẫu tin) để đặt chúng theo thứ tự thỏa mãn tiêu chuẩn đó
• Khái niệm nghịch thế:
– Xét mảng số a0, a1, … ,aN
– Giả sử xét mảng có thứ tự tăng dần, có i < j
(4)Các khái niệm
• Để xếp mảng => tìm cách giảm số nghịch mảng cách hoán vị các cặp phần tử
• Cho trước dãy số a1, a2, … aN lưu trữ trong cấu trúc liệu mảng
Ví dụ: int a[N];
(5)• Ý tưởng: thực N-1 lần việc đưa phần tử nhỏ nhất dãy hành vị trí đứng đầu dãy
• Nhận xét: mảng có thứ tự phần tử ai là (ai,ai+1, ,an-1) => Ý tưởng thuật toán chọn trực tiếp:
– Chọn phần tử nhỏ N phần tử ban đầu, đưa phần tử vị trí đứng đầu dãy hành;
– Sau khơng quan tâm phần tử nữa, xem dãy hành N-1 phần tử dãy ban đầu, vị trí thứ 2;
– Lặp lại q trình cho dãy hành … dãy hành phần tử
(6)• Giải thuật : B1: i = 0;
B2: Tìm phần tử a[min] nhỏ dãy hành từ a[i] đến a[n]
B3: if (min ≠ i) : hoán vị a[min] a[i]
B4: if (i≤ (n-1):
B4.1: i++
B4.2: Lặp lại B2
Ngược lại : dừng // vì n-1 phần tử nằm vị trí
(7)(8)(9)void SelectionSort(int a[],int n ) {
int min; // chỉ số phần tử nhỏ nhất trong dãy hiện hành
for (int i=0; i<n-1 ; i++) {
min = i;
for(int j = i+1; j < n ; j++)
if (a[j] < a[min])
= j; // ghi nhận vị trí phần tử nhỏ nhất
if (min != i)
Swap(a[min], a[i]);
} }
(10)• Ở lượt thứ I, cần (n-i) lần so sánh để tìm phần tử nhỏ hành Số lượng phép so sánh khơng phụ thuộc vào tình trạng dãy ban đầu
• Trong trường hợp số lần so sánh
• Số lần hốn vị (một hoán vị phép gán) phụ thuộc vào tình trạng ban đầu dãy số
Đánh giá giải thuật Chọn trực tiếp
Xấu
0 Tốt
Số phép gán Số lần so sánh
Trường hợp
2 ) (n n
2 ) (n n
2 ) (
3n n
(11)Ý tưởng:
• Giả sử dãy {a0,a1,…an-1} có k phần tử
{a0,a1,…ak-1} có thứ tự
• Chèn phần tử ak vào k phần tử có
thứ tự cách tìm vị trí phần tử k theo giải thuật tìm (Sequential Search)
có dãy {a0,a1,…,ak-1,ak} có thứ tự
• Vị trí cần chèn ak phần tử ai-1 ai
sao cho ai-1 ≤ ak+1 ≤ ai
(12)Thuật toán:
B1: k = //Giả sử đoạn a[0] xếp
B2: x = ak Tìm vị trí pos thích hợp đoạn a0 đến ak-1 để chèn ak vào
B3: Dời chỗ phần tử từ apos đến ak-1 sang phải vị trí để dành chỗ cho ak
B4: apos = x; // đoạn a0 … ak
B5: k = k+1
Nếu i<= n: lặp lại B2 Ngược lại : dừng
(13)Ví dụ mơ chèn trực tiếp • Cho dãy số a : N = ;
(14)(15)void InsertionSort (int a [ ], int n) { int k=0, i;
while (a[k]≤a[k+1] && k<n) k++;
while (k<n)
{ int x=a[k+1]; i=k;
while (x<a[i] && i>0)
{ a[i+1] = a[i];
i ;
}
a[i+1]=x;
k++;
} return;
(16)• Trường hợp tốt nhất: mảng a ban đầu có thứ tự tăng
– Số phép gán: Gmin = 2*(n-1)
– Số phép so sánh: Smin = 1+2+…+ (n-1) = n*(n-1)/2
• Trường hợp xấu nhất: mảng a ban đầu ln có phần tử nhỏ n-k phần tử còn lại
– Số phép gán: Gmax = 2*(n-1) + n*(n-1)/2
– Số phép so sánh: Smax = n-1
• Độ phức tạp thuật toán: O(n2)
(17)Ý tưởng:
• Phương pháp chèn nhị phân tương tự phương pháp chèn trực tiếp
• Tuy nhiên, thực tìm kiếm vị trí i cho phần tử ai để chèn vào đoạn {a0,a1,…,ai-1} có thể dùng phương pháp tìm kiếm nhị phân (Binary Search) thay cho tìm kiếm (Sequential Search)
(18)void BinaryInsertionSort(int a[], int n )
{ int l,r,m,i;
int x;//lưu trữ giá trị a[i] tránh bị ghi đè khi dời chỗ các phần tử
for(int i=0 ; i<n ; i++)
{ x = a[i]; l = 0; r = i-1;
while(l<=r) // tìm vị trí chèn x
{ m = (l+r)/2; // tìm vị trí thích hợp m
if(x < a[m]) r = m-1;
else l = m+1;
}
for(int j = i ; j >l ; j )
a[j] = a[j-1]; // dời chỗ các phần tử sẽ đứng sau x
a[l] = x; // chèn x vào dãy
}
(19)• Phương pháp chèn nhị phân cải tiến cách tìm kiếm vị trí thích hợp phần tử a[i], làm giảm số lần so sánh lại không làm thay đổi số lần di chuyển
• Vì việc cải tiến không đáng kể Độ phức tạp thuật toán O(n2)
(20)Đổi chỗ trực tiếp - Interchange Sort
• Ý tưởng :