Tải bản đầy đủ (.ppt) (13 trang)

Sắp xếp chèn - InsertionSort pot

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 (157.12 KB, 13 trang )


Insertion 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

Insertion 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

Insertion 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.

Insertion 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.

Insertion 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

Vớ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ử

Insertion 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;
}
}

Insertion 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

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;
}
}

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


Thời gian thực hiện giải thuật là Θ(n
2
) 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(
2
1
1
n
nn
i
n
i
Θ=

=



=
Insertion Sort : Phân tích
for ( int i = 1; i < n; ++i )
int j = i-1;
while(j >=0 && tmp < array[j])
array[j+1] = array[j];

Phân tích

Nếu ta biết phép so sánh (tmp < array[j] ) để
thực hiện phép gán array[j+1] = array[j] chạy
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 ).

Insertion Sort


Một dãy ngẫu nhiên có d = O(n
2
) các nghịch
thế. Do đó trung bình của Insert sort Θ( d
+ n ).

Insertion sort sẽ chạy trong Θ( n ) thời
gian nếu:

Các phần tử nằm sai vị trí quá xa thì nhỏ, và…

Những phần tử còn lại hầu như ở gần vị trí đúng của nó.

Tổng quát, giải thuật không có ích khi
dãy ban đầu là lớn

Sắp xếp dãy có kích thước 2
23
≈ 8 000 000 mất thời gian xấp xỉ
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


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(n
2
)
Dãy có thứ tự ngược
Trung bình
O(d + n)
Không may, d = O(n
2
)
Tốt nhất
O(n)
Rất ít cặp có thứ tự ngược
Insertion Sort
Kết luận

×