插入排序(inertion-sort)
插入排序(insertion-sort)
輸入:n個數的一個序列<a1,a2,...,an>.
輸入:輸入序列的一個排列<a'1,a'2,...,a'n>,滿足a'≤a'2≤...a'n.
分類:包括:直接插入排序,二分插入排序(又稱折半插入排序),連結串列插入排序,希爾排序(又稱縮小增量排序)。屬於穩定排序的一種(通俗地講,就是兩個相等的數不會交換位置) 。
插入排序的簡單理解:工作原理是通過構建有序序列,對於未排序的資料,在以排序序列中從後向前掃描,找到相應的位置並插入。插入排序在實現上,通常採用in-place排序(即只需用到O(1)的額外空間的排序),通常就像許多人排序一手撲克牌。開始時,我們的左手並且桌子上的牌面向下。然後,我們每次從桌子上拿走一張牌並將它插入左手中正確的位置。為了找到一張牌的正確位置,我們從右到左將它已在手中的每張牌進行比較。拿在左手上的牌總是排序好的,原來這些牌是桌上牌堆中頂部的牌。(
設計:
演算法設計有很多方法。插入排序使用的是增量(incremental)方法;在排好子陣列A[1..j-1]後,將A[j]插入,形成排好序的子陣列A[1..j];
步驟
⒈從有序數列和無序數列{a2,a3,…,an}開始進行排序;
⒉處理第i個元素時(i=2,3,…,n),數列{a1,a2,…,ai-1}是已有序的,而數列{ai,ai+1,…,an}是無序的。用ai與ai-1,a i-2,…,a1進行比較,找出合適的位置將ai插入;
⒊重複第二步,共進行n-i次插入處理,數列全部有序。
思路
假定這個陣列的序是排好的,然後從頭往後,如果有數比當前外層元素的值大,則將這個數的位置往後挪,直到當前外層元素的值大於或等於它前面的位置為止.這具演算法在排完前k個數之後,可以保證a[1…k]是區域性有序的,保證了插入過程的正確性
插入排序演算法的分析
過程INSERTION-SORT需要的時間依賴於輸入:排序數量大的數比排序小的數需要更長的時間。此外,依據它們已被排序的程度,INSERTION-SORT可能需要不同數量的時間來排序兩個具有相同的輸入序列。
插入排序的虛擬碼如下:
voidinsert_sort(int*array,unsignedintn) { int i,j,temp; for(i=1;i<n;i++) { temp=*(array+i); for(j=i;j>0 && *(array+j-1)>temp;j--) { *(array+j)=*(array+j-1); } *(array+j)=temp; } }
c語言實現:
#include<stdio.h>
void insertionsort(int *arr,int len)
{
int i,j;
int temp;
for(i=1;i<len;i++)
{
temp= *(arr+i); //待插入陣列取出第一個元素
for(j=i;j>0 && *(arr+j-1)>temp;j--)
{
*(arr+j)=*(arr+j-1);
}
*(arr+j)=temp;
}
}
int main()
{
int i=0;
int arr[6]={8,2,4,9,3,6};
insertionsort(arr,6);
for(i=0;i<6;i++){
printf("排序後的數字是:%d\n ", arr[i]);
}
return 0;
}
int i,j;
int temp;
for(i=1;i<len;i++)
{
temp= *(arr+i); //待插入陣列取出第一個元素
for(j=i;j>0 && *(arr+j-1)>temp;j--)
{
*(arr+j)=*(arr+j-1);
}
*(arr+j)=temp;
}
}
int main()
{
int i=0;
int arr[6]={8,2,4,9,3,6};
insertionsort(arr,6);
for(i=0;i<6;i++){
printf("排序後的數字是:%d\n ", arr[i]);
}
return 0;
}
演算法複雜度:
如果目標是把n個元素的序列升序排列,那麼採用插入排序存在最好情況和最壞情況。最好情況就是,序列已經是升序排列了,在這種情況下,需要進行的比較操作需(n-1)次即可。最壞情況就是,序列是降序排列,那麼此時需要進行的比較共有n(n-1)/2次。插入排序的賦值操作是比較操作的次數加上 (n-1)次。平均來說插入排序演算法的時間複雜度為O(n^2)。因而,插入排序不適合對於資料量比較大的排序應用。