以下三种插入排序时间复杂度均为O(n^2)
简单插入排序,简单直接。假定数组有序,插入 i, 从后往前遍历找到适合位置 j,移动 j +1 ~ i -1往后一位,插入i到j中。
void insertSort(int *arr, int numsSize)
{
int i, j, k, v;
for (i = 1; i < numsSize; i++)
{
for (j = i - 1; j >= 0; j--)
{
if (arr[i] >= arr[j])
break;
}
v = arr[i];
for (k = i; k > j + 1; k--)
arr[k] = arr[k-1];
arr[k] = v;
}
return;
}
折半插入排序,和简单插入排序相比减少比较次数,稍稍好那么一丢丢,时间复杂度还是O(n^2)
void BiInsertSort(int *arr, int numsSize)
{
int high, low, m, i, j, v;
for (i = 1; i < numsSize; i++)
{
high = i - 1;
low = 0;
v = arr[i];
while (low <= high)
{
m = (low + high)/2;
if (arr[m] >= arr[i])
high = m - 1;
else
low = m + 1;
}
for (j = i; j > low; j--)
{
arr[j] = arr[j-1];
}
arr[low] = v;
}
}
2路插入排序,减少移动次数,额外增加一个循环数组,需要考虑边界溢出,特别容易出错。时间复杂度和其它插入排序相比没有基本改变,不建议使用但是要理解并能够写出代码。first和final分别表示循环数组中的起始位置。
void insertSort2(int *array, int arraysize)
{
int final, first, i, j, n;
final = first = 0;
if (!array || arraysize < 1)
return ;
int *tmp = (int *)malloc(sizeof(int) * arraysize);
if (!tmp)
{
printf("malloc error\n");
return ;
}
tmp[0] = array[0];
for (i = 1; i < arraysize; i++)
{
if (array[i] >= tmp[0])
{
//插入到左边
j = final;
while(array[i] < tmp[j])j--;
for (n = ++final; n > j + 1; n--)
tmp[n] = tmp[n-1];
tmp[n] = array[i];
}
else
{
//插入到右边
if (first == 0)
{
first = arraysize - 1;
tmp[first%arraysize] = array[i];
}
else
{
j = first - arraysize;
while(tmp[(j + arraysize)%arraysize] < array[i])
j++;
for (n = (--first - arraysize); n < (j - 1); n++)
tmp[(n + arraysize)%arraysize] = tmp[(n + 1 + arraysize)%arraysize];
tmp[(n + arraysize)% arraysize] = array[i];
}
}
}
}
=============================================================================================
Linux应用程序、内核、驱动、后台开发交流讨论群(745510310),感兴趣的同学可以加群讨论、交流、资料查找等,前进的道路上,你不是一个人奥^_^。