直接插入排序指的是先將一小部分排好序,然後從未排序的元素中找一個出來.遍曆已排序好的數組,插入到合適位置.
直接插入排序:
void StraightInsertSort(int* arr, int len)
{
int tmp;
int j;
for(int i = 1; i < len; i++)
{
tmp = arr[i];
for(j = i-1; j >=0 ; j --) //遍曆已經排好序的部分,找到合適的位置j + 1
{
if( arr[j] >= tmp)
break;
}
for(int k = i; k > j + 1; k--) //把位置j + 1後面的元素右移
{
arr[k] = arr[k -1];
}
arr[j + 1] = tmp; //插入元素到位置j+1
}
}
我們看到在從已經排好序的數組中找合適的位置的時候可以改進一下,用下二分尋找的方法.
改進的插入排序演算法:(有時也叫作二分插入排序)
void BinaryInsertSort(int* arr, int len)
{
int tmp;
int j;
for(int i = 1; i < len; i++)
{
tmp = arr[i];
int left = 0;
int right = i - 1;
while(left <= right) //通過二分尋找找到合適的插入位置
{
int mid = (left + right)/2;
if( tmp == arr[mid])
{
j = mid;
break;
}
else if( tmp < arr[mid])
right = mid -1;
else if( tmp > arr[mid])
left = mid + 1;
}
if(left > right)
j = left - 1;
for(int k = i; k > j + 1; k--) //把位置j + 1後面的元素右移
{
arr[k] = arr[k -1];
}
arr[j + 1] = tmp; //插入元素到位置j+1
}
}
希爾排序(shell sort)
當數組中的元素基本有序的時候採用直接插入排序效率非常高,根據這個思路產生了一個改進的插入排序演算法,希爾排序.
大體思路是先把整個待排序元素序列分割成若干子序列(由相隔的增量組成)分別採用直接插入排序,這樣每排一次元素就變得更有序,然後增量縮小再接著重複上面的操作.
比如按增量5,3,1,0分別進行插入排序.當增量是1時就相當於對整個數組採取直接插入排序了.
你可能會好奇這個增量是怎麼確定的? 這就存在很多不同的方法了,一般用的較多較容易的就是直接用數組長度n除以2,然後把結果繼續除2.
void ShellSort(int* arr, int len)
{
for( int gap = len/2; gap > 0; gap = gap/2) //通過不同的增量來使數組一步步達到更有序的狀態
{
for( int i = 0; i < gap; i ++)
{
for(int j = i + gap; j < len; j = j + gap) //對每個增量產生的子序列進行插入排序
if( arr[j] < arr[j - gap])
{
int tmp =arr[j];
int k ;
for( k = j - gap; k >= 0; k = k - gap)
{
if( tmp < arr[k])
arr[k + gap] = arr[k];
else
break;
}
arr[ k +gap] = tmp;
}
}
}