直接插入排序:
基本思想:基本操作是将无需数组的每个元素依次插入有序数组中,这个过程会使有序数组不断增大,无序数组不断减小,最终全部有序,这是原来数组排序完成
步骤:首先拿出为无序数组的元素,将其和有序数组的元素依次进行比较,将符合条件的有序数组的元素移动,最后找到该元素的插入位置,将此元素插入
代码实现:
public static void insertSort(int[] arr){
if(arr == null || arr.length <= 1 ){
return ;
}
for (int i = 1;i < arr.length;i++){
int temp = arr[i];//拿出要插入的元素
int j = 0;
//依次与有序数组进行比较,符合条件的元素后移
for (j = i-1;(j>=0)&&(arr[j] > temp);j--){
arr[j+1] = arr[j];
}
//找到插入位置,插入元素
arr[j+1] = temp;
}
}
分析:
稳定性:在插入排序中,若插入元素与有序序列的某一元素相等时,不对相等元素进行搬移,而是将欲插入元素插在相等元素的后面,所以是稳定的
时间复杂度:若是完全有序(从小到大)的数组进行插入排序,不会进入元素的搬移这层循环,则时间复杂度为:O(n);若是无序或为逆序数组,都会对有序数组进行遍历,则此时时间复杂度:O(n^2)
空间复杂度:没有开辟新的空间,空间复杂度:O(1)
折半插入排序:直接插入的优化
思想:根据直接插入排序进行优化得来的,优化的地方是,因为前面的序列已经有序,在寻找插入位置时,可用二分查找法进行查找。
**步骤:**拿出待插入的元素,维护有序区间的变量left、righgt以及mid,left为有序区间开始,right为有序区间的结束,若需要插入元素的位置为i,则right=i-1;每次让有序区间的中间位置的元素与待插入元素进行比较,按照排序条件,定位插入区间,直到left<=right时找到插入位置
代码实现:
public static void iInsertSort(int[] arr){
if(arr == null || arr.length <= 1 ){
return ;
}
for (int i = 1;i < arr.length;i++){
int temp = arr[i];
int j = i-1;
int left = 0;
int right = i-1;
//直到有序区间没有元素时停止
while (left <= right){
int mid = left + ((right-left)>>1);
if (arr[mid] < temp){
left = mid+1;//若待插入元素比中间位置元素大则将区间定位在mid+1到right
}else {
right = mid-1;//若待插入元素比中间位置元素小则将区间定位在left到mid+1
}
}
for (;j>= right +1;j--){
arr[j+1] = arr[j];
}
arr[j+1] = temp;
}
}
分析:
稳定性:稳定
时间复杂度:虽然在查找上效率提高了,但总体来说还是O(n^2)
空间复杂度:O(1)
希尔排序:
思想:排序的思想是将数据分为若干组进行排序,本质是将同组的数据进行插入排序,当分组的间距为1时,此时序列已经接近有序,这时再进行插入排序,序列就完全有序了。
步骤:先设定一个较大的间隔将序列分为若干组,每组数据进行插入排序,再将间隔减小进一步,直到步数为1时是最后一次插入排序,这次插入排序完成后序列完全有序
代码实现:
public static void shell(int[] arr) {
if(arr == null || arr.length <= 1 ){
return ;
}
int step = arr.length >> 1;
while (step >= 1) {
for (int i = step; i < arr.length; i++) {
int temp = arr[i];//拿出和数组的第一个数组合的数;i=step
int j = 0;
//j=i-step 是为了找到与待插入元素组合的数
for (j = i - step; (j >= 0) && (arr[j] > temp); j -= step) {
arr[j + step] = arr[j];//满足条件插入
}
arr[j+step] = temp;//j+step的原因是for循环中j又减了一次step
}
step >>= 1;//让step每次都缩小2倍
}
}
分析:
稳定性:不稳定,一组序列在进行一次插入排序后时稳定的,但是多次之后,相同元素相对位置可能会发生改变,所以不稳定
时间复杂度:nO(logn)-O(n^2)
空间复杂度:O(1)