Insertion Sort• Lưu ý quan sát sau đây: – Dãy có 1 phần tử thì được sắp... Insertion SortVí dụ • Hãy xem dãy được sắp sau đây chứa k = 8 phần tử • Giả sử ta muốn chèn phần tử 14 vào tr
Trang 1Insertion Sort
• Nội dung
– Giải thuật
– Ví dụ minh họa
– Phân tích thời gian chạy
• Trường hợp xấu nhất
• Trung bình
• Tốt nhất
Trang 2Insertion Sort
• Lưu ý quan sát sau đây:
– Dãy có 1 phần tử thì được sắp.
– Tổng quát : nếu ta có dãy đã được sắp có k phần tử,
ta có thể chèn một phần tử mới để tạo ra một dãy
được sắp có kích thước k + 1
Trang 3Insertion Sort
Ví dụ
• Hãy xem dãy được sắp sau đây chứa k =
8 phần tử
• Giả sử ta muốn chèn phần tử 14 vào
trong dãy sao cho dãy vẫn được sắp.
• Bắt đầu đi từ cuối dãy, nếu phần tử
mang giá trị lớn hơn 14, copy nó sang phải
Trang 4Insertion Sort
Khi tìm được phần tử có giá trị bé hơn 14, chèn 14 vào
vị trí bỏ trống.
Trang 5Insertion Sort
• Với dãy bất kỳ:
– Xem phần tử đầu tiên là một dãy được sắp có kích
thước k = 1.
• Sau đó, giả sử ta đã có dãy được sắp
có kích thước k.
– Chèn phần tử thứ (k + 1) trong dãy chưa được sắp
vào trong dãy trên.
– Dãy được sắp bây giờ có kích thước k + 1
Giải thuật
Trang 6Với mỗi phần tử (thứ i ) trong dãy, bắt đầu từ phần tử thứ hai ….
Tìm ngược về đầu dãy, xuất phát j = i -1
Nếu phần tử đang xét thứ j lón hơn phần tử thứ i
Dịch chuyển phần tử thứ j đến vị trí j+1
Ngược lại, đặt phần tử thứ i vào vị trí j+1
Insertion Sort
Giải thuật Insert sort với dãy có n phần tử
Trang 7Insertion Sort : Cài đặt
void Insertion( int array[], int const n )
{
for ( int i = 1; i < n; ++i )
{
int tmp = array[i];
int j= i-1;
while(j>=0 && tmp < array[j]) {
array[j+1] = array[j];
j ;
}
array[j+1]= tmp;
}
}
Trang 8Insertion Sort : Phân tích
void Insertion( int array[], int const n )
{
for ( int i = 1; i < n ; ++i )
{
int tmp = array[i];
int j= i-1 ;
while(j>=0 && tmp < array[j])
{
array[j+1] = array[j];
j ;
}
array[j+1]= tmp;
}
}
Điều kiện này thực hiện n lần
Những phép gán này đươc thưc hiện trong từng bước
lặp
Trang 9Phân tích
void Insertion( int array[], int const n )
{
for ( int i = 1; i < n; ++i )
{
int tmp = array[i];
int j= i-1;
while(j>=0 && tmp < array[j])
{
array[j+1] = array[j];
j ;
}
array[j+1]= tmp;
}
}
Phép so sánh đươc thưc hiện i lần trong từng bước
lặp
Phép gán đươc thưc hiện
có thể i lần trong từng
bước lặp
Trang 10• Thời gian thực hiện giải thuật là Θ (n2) do:
• Thực tế, giải thuật có thể chạy nhanh hơn:
– Nếu điều kiện thất bại, vòng while sẽ thoát sớm
)
( 2
) 1
1 1
n
n
n i
n
i
Θ
=
−
=
∑−
=
for ( int i = 1; i < n; ++i )
int j = i-1;
while(j >=0 && tmp < array[j])
array[j+1] = array[j];
Trang 11Phân tích
như thế nào ta sẽ biết độ phức tạp của nó.
• Nếu phép gán xảy ra d lần, điều kiện kiểm tra
là (d+n) lần (do có n phần tử cần kiểm tra).
• Tuy nhiên mỗi phép gán tương đương với sự hoán đổi 2 phần tử kề nhau.
• Mỗi một phép hoán đổi là sửa lại một bộ có thứ
tự ngược
• Vì thế d chính là số các nghịch thế trong dãy ban đầu
• Vì vậy thời gian chạy của insertsort sẽ là :
Θ ( d + n )
Trang 12Insertion Sort
thế Do đó trung bình của Insert sort Θ ( d + n )
gian nếu:
– Các phần tử nằm sai vị trí quá xa thì nhỏ, và…
• Tổng quát, giải thuật không có ích khi
dãy ban đầu là lớn
một ngày
– Tăng kích thước gấp đôi thời gian tăng gấp 4
Kết luận
Trang 13• Bảng sau tổng kết thời gian thực
hiện của giải thuật Insertion Sort
Truờng hợp Run Time Ghi chú
Xấu nhất O(n2) Dãy có thứ tự ngược
Trung bình O(d + n) Không may, d = O(n2)
Tốt nhất O(n) Rất ít cặp có thứ tự ngược
Insertion Sort Kết luận