一、排序算法(Java实现)——插入排序
插入排序一般有3种,直接插入排序,折半插入排序,希尔排序。
(1)直接插入排序
基本思想: 将一个元素插入到已排序的有序表中,进而得到一个新的有序表。给定一个无序数组,从第一个元素开始,将数组分为有序区和无序区(一般是左边为有序区,右边为无序区也可成为待排区),依次从无序区中取出一个元素,将该元素与有序区元素进行比较,插入到相应位置(一般是从有序区的右边开始比较,这样可以做到一边比较一边移动元素的效果)。
代码实现:
public void straightInsertionSort(int[] nums) {
for (int i = 1; i < nums.length; i++) {
int temp = nums[i];//设置哨兵,相当于将要插入的变量存起来
int j = i-1;
//找到要插入的下标
while(j>=0) {
if(nums[j]>temp)
nums[j+1] = nums[j];//边比较边移动元素
else
break;
j--;
}
nums[j+1] = temp;//插入元素
}
}
算法分析:
- 时间复杂度: O ( n 2 ) O(n^2) O(n2)
- 空间复杂度: O ( n ) O(n) O(n)(原地算法,没有开辟新的空间)
- 排序是否稳定:是
(2)折半插入排序
基本思想: 折半插入排序是直接插入排序的改进版,在查找插入位置时,直接插入排序是顺序查找,查找的时间复杂度为O(n),由于是在有序区进行元素查找,所以可以将元素查找改为折半查找,此时的查找的时间复杂度为O(logn)。
代码实现:
public void binaryInsertSort(int[] nums) {
for(int i = 1; i<nums.length; i++) {
int temp = nums[i];
int low = 0;
int hight = i-1;
//通过折半查找进行查找要插入的位置
while(low<=hight) {
int mid = (low+hight)/2;
if(nums[mid]<temp) low = mid+1;
else hight = mid-1;
}
//对要插入的位置进行元素后移
for(int j = i-1;j>=hight+1;j--) {
nums[j+1] = nums[j];
}
//将待插元素插入
nums[hight+1] = temp;
}
}
算法分析:
- 时间复杂度: O ( n 2 ) O(n^2) O(n2)
- 空间复杂度: O ( n ) O(n) O(n)
- 排序是否稳定:是
(3)希尔排序
基本思想: 先将整个待排记录序列分割成为若干个子序列分别进行直接插入排序,待整个序列中的记录“基本有序”时,再对全体进行一次直接插入排序。希尔排序又称为“缩小增量排序”,其时间复杂度与上述两种插入排序相比有着很大的提高。
//k表示增量,即增量为k的直接插入排序
public void shellInsert(int[] nums,int k) {
for(int i = k ; i<nums.length; i++) {
int temp = nums[i];
int j = i - k;
while(j>=0) {
if(nums[j]>temp) nums[j+k] = nums[j];
else break;
j = j - k;
}
nums[j+k] = temp;
}
}
//对于希尔排序而言有很多增量序列可以选择,在这里我们选择的增量为待排序列长度的一半,但是要注意的是最后一次增量一定要为1
public void shellSort(int[] nums) {
int t = nums.length/2;
for(int i = 0;i<t;i++) {
shellInsert(nums,t);//增量为nums.lenght/2进行排序
}
shellInsert(nums,1);//保证最后一轮排序,增量为1
}
算法分析:
- 时间复杂度:希尔排序的时间复杂度与增量选取有关,直接插入排序就可以看作增量为1的希尔排序。有人指出增量序列为 d l t a [ k ] = 2 t − k + 1 − 1 dlta[k] = 2^{t-k+1}-1 dlta[k]=2t−k+1−1 时(其中,t为排序趟数, 1 ≤ k ≤ t ≤ ⌊ l o g 2 ( n + 1 ) ⌋ 1 \leq k \leq t \leq \lfloor log_2(n+1) \rfloor 1≤k≤t≤⌊log2(n+1)⌋ ),希尔排序时间复杂度为 O ( n 3 / 2 ) O(n^{3/2}) O(n3/2)
- 空间复杂度: O ( n ) O(n) O(n)
- 排序是否稳定:否
参考资料:严蔚敏版《数据结构》