#include <iostream>
using namespace std;
//直接插入的思想:把需要插入的元素插入到一个有序序列中
//1.默认第一个元素是有序的,然后在有序序列中找到一个位置使这个位置上的数小于需要插入的元素
//2.然后将找到的有序序列位置之后的元素依次向后移动
//3.将需要插入的元素插入到有序序列之后的位置(注:假如在有序序列中所有的元素都比要插入的元素大,则需要将整个有序序列向后移动)
void DirectInsert_Sort(int a[],int length){
int i = 1; //默认第一个数有序
int j;
for( ; i<length ;i++){
//找到要插入的位置 , j = -1 时说明i位置所在的元素比i之前位置的有序序列的长度都小
for(j = i - 1 ;j >= 0 ;j--)
if(a[j] <= a[i])
break;
//先移动元素再进行插入
if(j != i - 1){//j=i-1 说明j所在位置的元素已经比i小了,不需要移动
int temp = a[i],k;//记录ai的值
for( k = i - 1; k > j; k-- ){
a[k+1] = a[k];
}
a[k+1] = temp;
}
}
}
// 直接插入排序的第二种方法,将查找和移动元素的操作放在一起
void DirectInsert_Sort2(int a[], int length){
int i = 1;
int j ;
for (; i < length; i++) {
if(a[i] < a[i-1]){// 如果需要插入的元素比它的前一个元素小,则与有序序列的元素进行比较
int temp = a[i];
for (j = i - 1; j >= 0 && a[j] > temp ; j--) {// 如果有序序列的元素比需要插入的元素大将有序序列中的元素向后移动
a[j+1] = a[j];
}
a[j+1] = temp;
}
}
}
// 打印设置哨兵的序列
void printfSort_UseZero(int a[],int n){
for (int i = 1; i < n; i++) {
cout<<a[i]<<" ";
}
cout<<endl;
}
// 设置 a[0] 为哨兵,用于判断结束移动的位置
// 排序打印出来的值忽略第一位
void DirectInsert_Sort3(int a[] , int length){
int i,j;
for (i = 2; i <= length; i++) {
if(a[i] < a[i-1]){
a[0] = a[i];// 设置哨兵
for(j = i - 1; a[j] > a[0]; j--){ //如果 j = i 会多移动一次
a[j+1] = a[j];
}
a[j+1] = a[0];
}
}
}
// 希尔排序:是一个突破时间复杂度为 O(n^2) 的第一批算法之一
// 原理:对于直接插入排序在序列基本有序时很高效。还有当序列足够少时直接插入的优势也很明显。
// 故采用跳跃分割的策略,将相距某个增量的记录组成一个子序列,来保证整个序列基本有序。
void ShellS_Sort(int a[] , int length){
int i,j;
int increament = length;
while(increament > 1){
increament = increament/3 + 1;
for(i = increament + 1; i <= length; i++){ //对每一组进行排序
if(a[i] < a[i-increament]){
a[0] = a[i];
for (j = i - increament; j > 0 && a[0] < a[j]; j-=increament)
a[j + increament] = a[j];
a[j + increament] = a[0];
}
}
}
}
int main(int argc, const char * argv[]) {
int a[100] , n ;
cin>>n;
for(int i = 0 ;i < n ; i++){
cin>>a[i];
}
//printf("直接插入排序\n");
//DirectInsert_Sort3(a, n-1);
cout<<"希尔排序"<<endl;
ShellS_Sort(a, n-1);
printfSort_UseZero(a, n);
return 0;
}
直接插入排序的时间复杂度和空间复杂度:
1. 当最好的情况,序列本身有序时需要比较 n-1 次,当最后的情况,序列本身为逆序的时候,需要比较 2+3+ ~ n=(n+2)*(n-1)/2 次(因为需要和哨兵比较所以每次比较多了一次)。
2. 移动次数为 3+4~n+2=(n+4)*(n-1)/2 次
故得出直接插入算法的时间复杂度为 O(n^2)
希尔排序的时间复杂度和空间复杂度:
1.