直接插入排序和折半插入排序
插入排序的基本思想是:在一个一排好序的记录的子集上的基础上,每一步将下一个待排序的记录有序的插入到已经排好序的记录子集中,直到将所有待排序的子集全部插入到序列中为止。
直接插入排序(straight insertion sort)的做法是:每次从无序表中取出第一个元素,把它插入到有序表的合适位置,使有序表仍然有序。 第一趟比较前两个数,然后把第二个数按大小插入到有序表中; 第二趟把第三个数据与前两个数从前向后扫描,把第三个数按大小插入到有序表中;依次进行下去,进行了(n-1)趟扫描以后就完成了整个排序过程。
折半插入排序做法是:
时间复杂度比较:在将一个新元素插入已排好序的数组的过程中,寻找插入点时,将待插入区域的首元素设置为a[low],末元素设置为a[high],则轮比较时将待插入元素与a[m],其中m=(low+high)/2相比较,如果比参考元素小,则选择a[low]到a[m-1]为新的插入区域(即high=m-1),否则选择a[m+1]到a[high]为新的插入区域(即low=m+1),如此直至low<=high不成立,即将此位置之后所有元素后移一位,并将新元素插入a[high+1]。
直接插入排序属于稳定的排序,最坏时间复杂性为O(n^2),空间复杂度为O(1);
折半插入排序算法的时间复杂度仍然为O(n^2),与直接插入排序算法相同。附加空间O(1)。
示例代码如下:
#include<iostream>
using namespace std;
//冒泡排序
void BubbleSort(int *array,int n){
for(int i=0;i<n;i++)
for(int j=i;j<n-1;j++)
if(array[j]>array[j+1]){
int temp=array[j+1];
array[j+1]=array[j];
array[j]=temp;
}
}
//直接插入排序
void InitSort(int *array,int n){
//算法思想:第一趟比较前两个数,然后把第二个数按大小插入到有序表中; 第二趟把第三个数据与前两个数从前向后扫描,把第三个数按大小插入到有序表中;依次进行下去,进行了(n-1)趟扫描以后就完成了整个排序过程。
int j;
for(int i=1;i<n;i++){//从第二个开始
if(array[i]<array[i-1]){
int temp=array[i];
for(j=i-1;j>=0&&array[j]>temp;j--){
array[j+1]=array[j];//逐步往前寻找合适的插入位置,如果插入的数小于当前要插入的位置则要再往前查找
}
array[j+1]=temp;//把大的数放到最后
}
}
}
void BInsertSort(int *array, int length) // length是要排序的元素的个数,0号单元除外
{
int i, j;
int insertNote=0;//保存中间插入的值
for (i=1;i<length;i++) {
int low=0;//最低位
int high=i-1;//最高位
insertNote=array[i];//要插入的数
while (low<=high) {//不断的折半
int mid=(low+high)/2;//找出中间值
if(array[i]>array[mid])low=mid+1;//在大于中间值的那部分查找 //如果大于中间值
else high = mid-1;//在小于中间值的那部分查找
}
for (j=i;j>low;j--) {//将整体数组向后移
array[j]=array[j-1];
}
array[low]=insertNote;//插入到指定的位置
}
}
//表插入排序
int main(){
int array[]={12,23,34,54,67,456,234,2314,134,324,234,34212,234234,234};
int k=sizeof(array)/sizeof(int);
//BubbleSort(array,k);冒泡排序
//InitSort(array,k);
BInsertSort(array,k);
for(int i=0;i<k;i++){
cout<<array[i]<<" ";
}
return 0;
}
(全文完)