了解一个排序算法一般要从排序算法的实现原理,代码实现,时间复杂度,空间复杂度,稳定性,适合场景,哪些缺陷或者有哪些优化措施。
-
插入排序
-
实现原理:可以将待排序数组分为有序区间和无序区间,每次都从无序区间选取第一个数据放到有序区间的合适位置。
-
代码实现:
private void insertSort(int[] nums){
for(int i=1;i<nums.length;i++){
int tmp=nums[i];
int d=i-1;
//不写nums[d]>=tmp是保证稳定性
while(d>=0&&nums[d]>tmp){
nums[d+1]=nums[d];
d--;
}
nums[d+1]=tmp;
}
}
- 时间复杂度:O(N^2)
- 空间复杂度:O(1)
- 稳定性:稳定
- 比较适合待排序数据比较有序,数据数量比较小的场景
- 折半插入排序
既然每次都是在有序区间查找合适的位置,所以可以用二分查找来搜索插入位置
private void insertBinarySort(int[] nums){
for(int i=1;i<nums.length;i++){
int tmp=nums[i];
int left=0;
int right=i;
while(left<right){
int mid=(left+right)>>1;
if(nums[mid]<=tmp){
left=mid+1;
}else{
right=mid;
}
}
System.arraycopy(nums,left,nums,left+1,i-left);
nums[left]=tmp;
}
}
-
希尔排序
-
实现原理:希尔排序又叫缩小增量法。每次选定一个间隔gap,间隔相同的为一组,对同一组的数据进行排序,然后不断的缩小gap,gap>1时候的排序都是预排序,当gap等于1的时候,数组已经接近有序了,gap等于1排完后就有序了。
-
代码实现:
private void shellSort(int[] nums){
int gap=nums.length;
while(gap>1){
shell(nums,gap);
gap=gap/3+1;
}
shell(nums,1);
}
private void shell(int[] nums,int gap){
for(int i=gap;i<nums.length;i++){
int tmp=nums[i];
int d=i-gap;
while(d>=0&&nums[d]>tmp){
nums[d+gap]=nums[d];
d-=gap;
}
nums[d+gap]=tmp;
}
}
-
时间复杂度:跟gap的取值有关,平均:O(N^1.3)
-
空间复杂度:O(1)
-
稳定性:不稳定