插入排序:
插入排序的原理就是当前位置的元素值大于后进来元素值,就进行交换。
排序过程如下:
10 3 26 9 30 15 18 211
3 10 26 9 30 15 18 211
3 10 26 9 30 15 18 211
3 10 26 9 30 15 18 211
3 9 10 26 30 15 18 211
3 9 10 26 30 15 18 211
3 9 10 15 26 30 18 211
3 9 10 15 18 26 30 211
3 9 10 15 18 26 30 211
代码实现:
#include<stdio.h>
void InsertSort(int arr[],int nLength)
{ //日常检测
if(arr == NULL || nLength <=0)return;
int i;
int j;
int temp;
for(i = 1;i<nLength;i++)
{
j = i-1; //有序的最后一个
temp = arr[i]; //无序第一个元素
//找到无序元素所在位置
while(arr[j] > temp && j>=0)
{
arr[j+1] = arr[j];
j--;
}
//值放入
arr[j+1] = temp;
}
}
void Print(int arr[],int nLength)
{
int i;
for(i = 0;i<nLength;i++)
{
printf("%d ",arr[i]);
}
printf("\n");
}
int main()
{
int arr[] = {10,3,26,9,30,15,18,211};
InsertSort(arr,sizeof(arr)/sizeof(arr[0]));
Print(arr,sizeof(arr)/sizeof(arr[0]));
return 0;
}
效果展示:
复杂度与稳定性:
插入排序的平均时间复杂度是O(n^2),最好情况是O(n),最差情况是O(n^2),是一种稳定的排序方法,空间复杂度是O(1)。备注:大部分已排序好时较好使用。
算法优化:
1.设置哨兵位:
哨兵的插入排序中的哨兵元素有两个作用:
1、暂时存放待插入的元素
2、防止数组下标越界,当待插入的元素小于已排序的子数组中的最小元素时,j=-1,越界,而采用哨兵,arr[0]<arr[j],当j=0时,就结束循环,不会出现越界。
for(i = 1;i<nLength;i++)
{
j = i-1; //有序的最后一个
temp = arr[i]; //无序第一个元素
arr[0] = temp;//设置哨兵位
//找到无序元素所在位置
while(arr[j] > temp)
{
arr[j+1] = arr[j];
j--;
}
//值放入
arr[j+1] = temp;
}
2.使用二分排序法:
查找过程是:在有序表中,取中间的记录作为比较关键字,若给定值与中间记录的关键字相等,则查找成功;若给定的值小于中间记录的关键字,则在中间记录的左半区间继续查找;若给定值大于中间记录的关键字,则在中间记录的右半区间继续查找;不断重复这个过程,直到查找成功。否则查找失败。
#include<iostream>
using namespace std;
int Binarysearch(int arr[],int item,int low,int high)
{
if(high<=low) return (item>=arr[low])?(low+1):low;
int mid = low+(high-low)/2;
if(item == arr[mid]) return mid;
if(item > arr[mid])
return Binarysearch(arr,item,mid+1,high);
else //item< mid
return Binarysearch(arr,item,low,mid-1);
}
void InsertSort(int arr[],int nLength)
{
if(arr == NULL || nLength <=0)return;
int i;
int j;
int temp;
int k;
for(i = 1;i<nLength;i++)
{
j = i-1; //有序的最后一个
temp = arr[i]; //无序第一个元素
k = Binarysearch(arr,temp,0,j);
//找到无序元素所在位置
while(j >= k )
{
arr[j+1] = arr[j];
j--;
}
//值放入
arr[j+1] = temp;
}
}
void Print(int arr[],int nLength)
{
int i;
for(i = 0;i<nLength;i++)
{
printf("%d ",arr[i]);
}
printf("\n");
}
int main()
{
int arr[] = {10,3,26,9,30,15,18,211};
cout<<"原来的:";
Print(arr,sizeof(arr)/sizeof(arr[0]));
cout<<"现在的:";
InsertSort(arr,sizeof(arr)/sizeof(arr[0]));
Print(arr,sizeof(arr)/sizeof(arr[0]));
system("pause");
return 0;
}
复杂度与稳定性:
插入排序一般情况下复杂度时O(n^2),最差情况下复杂度是O(n^2);最好情况是O(n),空间复杂度是O(1),是一种稳定的算法。