插入排序
基本思想
从初始有序的子集合开始,不断的把新的元素插入到已经排好序的子集合的合适位置上,使得子集合中数据元素的个数不断增多。当子集合等于集合时,插入排序算法结束。
常用的插入排序有
- 直接插入排序
- 希尔排序
直接插入排序
基本思想
顺序的把待排序的数据元素按照大小插入到已排序数据元素子集合的适当位置。子集合的数据元素个数从只有一个开始逐步递增到和集合大小相同时排序完毕
排序过程
代码实现
C实现
void InsertSort(DataType a[],int n){
int i,j;
DataType temp;
for (i=0;i<n-1;i++){
temp = a[i+1];
j=i;
while (j>-1&&temp<a[j]){
a[j+1] = a[j];
j--;
}
a[j+1]=temp;
}
}
java代码实现
/**
* 插入排序
*/
public static void insertSort(int[] arr) {
int temp;
for (int i = 1; i < arr.length; i++) {
int j = i - 1;
temp = arr[i];
while (j >= 0 && arr[j] > temp) {
arr[j + 1] = arr[j];
j--;
}
arr[j + 1] = temp;
}
}
算法分析
最好情况时间复杂度:
- 集合全部有序,此时内存while循环次数为0,外层for循环每次比较次数为1,整个排序的比较次数n-1,时间复杂度为O(n)
最坏情况时间复杂度
- 集合逆序 内层while循环次数均为i 时间复杂度O(n^2)
平均时间复杂度
- 期望时间复杂度为O(n^2)
空间复杂度 O(1)
稳定性
- 直接插入算法是一种稳定的排序算法
希尔排序
基本思想
- 把待排序的数据元素分成若干个小组,对同一个小组内的数据元素用直接插入法排序;
- 小组的个数逐步缩小
- 当完成了所有元素都在一个组内的排序后排序过程结束
希尔排序又叫做缩小增量排序
排序过程
代码实现
C实现
void ShellSort(DataType a[],int n,int d[],int numOfD){
int i,j,k,m,span;
DataType temp;
for (m=0;m<numOfD;m++){//共numOfD次循环
span = d[m];//取本次的增量值
for (k=0;k<span;k++){
/*组内是直接插入排序 区别是每次不是增1而是增Span*/
for (i=k;i<n-span;i=i+span){
temp = a[i+span];
j = i;
while (j>-1&&a[j]>=temp){
a[j+span] = a[j];
j = j-span;
}
a[j+span] = temp;
}
}
}
}
public static void shellSort(int[] arr, int[] d) {
int arrLength = arr.length, dLength = d.length;
int temp, m;
for (int i = 0; i < dLength; i++) {
int span = d[i];//取当前增量值
for (int j = 0; j < span; j++) {
for (int k = j; k < arrLength - span; k = k + span) {
temp = arr[k+span];
m = k;
while (m > -1 && arr[m] >= temp) {
arr[m + span] = arr[m];
m = m - span;
}
arr[m + span] = temp;
}
}
printArr(arr);
System.out.println();
}
}
算法分析
直接插入排序是两重循环
希尔排序是四重循环 每重循环次数都很小
- 时间复杂度 O(n(log2n)^2)
- 空间复杂度O(1)
- 不稳定的排序算法