Ý tưởng
Cho dãy ban đầu a1 , a2 ,... ,an, ta có thể xem như đã có đoạn gồm một phần tử a1 đã được sắp, sau đó thêm a2 vào đoạn a1 sẽ có đoạn a1 a2 được sắp; tiếp tục thêm a3 vào đoạn a1 a2
để có đoạn a1 a2 a3 được sắp; tiếp tục cho đến khi thêm xong aN vào đoạn a1 a2 ...aN-1 sẽ có dãy a1 a2 .... aN được sắp.
1 2 3 4 5 6 7 8
Chèn trực tiếp – insertion sort
88
10
5 7 3 9 2
15
1
1 2 3 4 5 6 7 8
Chèn trực tiếp – insertion sort
8910 10 5 7 3 9 2 15 1 Xem như phần tử thứ 1 đã có thứ tự Tìm vị trí thích hợp để chèn cho phần tử thứ 2
1 2 3 4 5 6 7 8
Chèn trực tiếp – insertion sort
90
7 3 9
2
15
1
Hai phần tử đầu tiên đã có thứ tự
Tìm vị trí thích hợp để chèn cho phần tử thứ 3
105 5
1 2 3 4 5 6 7 8
Chèn trực tiếp – insertion sort
913 9 2 3 9 2 15 1 Ba phần tử đầu tiên đã có thứ tự Tìm vị trí thích hợp để chèn cho phần tử thứ 4 7 10 5
1 2 3 4 5 6 7 8
Chèn trực tiếp – insertion sort
929 9 2 15 1 Bốn phần tử đầu tiên đã có thứ tự Tìm vị trí thích hợp để chèn cho phần tử thứ 5 3 5 7 10
1 2 3 4 5 6 7 8
Chèn trực tiếp – insertion sort
93
2
15
1
Năm phần tử đầu tiên đã có thứ tự
Tìm vị trí thích hợp để chèn cho phần tử thứ 6
9
1 2 3 4 5 6 7 8
Chèn trực tiếp – insertion sort
94
15
1
Sáu phần tử đầu tiên đã có thứ tự
Tìm vị trí thích hợp để chèn cho phần tử thứ 7
2 3 7 9
105 5
1 2 3 4 5 6 7 8
Chèn trực tiếp – insertion sort
95
15
Bảy phần tử đầu tiên đã có thứ tự
Tìm vị trí thích hợp để chèn cho phần tử thứ 8
2 3 7 9
10
1 2 3 4 5 6 7 8
Chèn trực tiếp – insertion sort
9615 15 Kết thúc giải thuật 2 3 7 9 10 5 1
Chèn trực tiếp – insertion sort
97
Dựa vào đâu để xác định được vị
trí chèn thích hợp của một giá trị trong dãy có giá trị tăng dần?
Hãy viết hàm chèn x vào dãy a tăng dần sao cho dãy a thu được cũng tăng dần
Giải thuật
Bước 1: i = 2; // giả sử có đoạn a[1] đã được sắp Bước 2: x = a[i];
Tìm vị trí pos thích hợp trong đoạn [1..i-1] để chèn a[i] vào Bước 3: Dời chỗ các phần tử từ pos đến i-1 sang phải 1 vị trí để dành chỗ cho a[i]
Bước 4: a[pos] = x; // có đoạn a[1]..a[i] đã được sắp Bước 5: i = i+1;
Nếu i ≤ N : Lặp lại Bước 2. Ngược lại : Dừng.
void InsertionSort(int a[], int N ) {
int pos; int x;
for(int i=1 ; i<N ; i++) //đoạn a[0] đã sắp {
x = a[i]; pos = i-1;
while((pos >= 0)&&(a[pos] > x)) {
a[pos+1] = a[pos]; pos--;
}
a[pos+1] = x;// chèn x vào dãy }
}
Bài tập
Minh họa từng bước thực hiện của giải thuật
Insertion Sort khi sắp dãy số sau tăng dần:
Cho biết tổng số gán và số phép so sánh
100
15 7 9 10 6 20
Đánh giá giải thuật
Các phép so sánh xảy ra trong mỗi vòng lặp while
tìm vị trí thích hợp pos, và mỗi lần xác định vị trí đang xét không thích hợp, sẽ dời chỗ phần tử a[pos] tương ứng. Giải thuật thực hiện tất cả N-1 vòng lặp while, do số lượng phép so sánh và dời chỗ này phụ thuộc vào tình trạng của dãy số ban đầu, nên chỉ có thể ước lượng trong từng trường hợp như sau:
Kết luận
“Chèn trực tiếp” và “Chọn trực tiếp” đều có chi phí
cho trường hợp xấu nhất là O(n2) do đó, không thích hợp cho việc sắp xếp các mảng lớn
Dễ cài đặt, dễ kiểm lỗi
“Chèn trực tiếp” tốt hơn “Chọn trực tiếp”, nhất là khi
mảng đã có thứ tự sẵn
Cần có những giải thuật hiệu quả hơn cho việc sắp xếp các mảng lớn
Các giải thuật sắp xếp cơ bản Đổi chỗ trực tiếp – Interchange Sort