一、选择排序
过程分析:
- 找到数组中最小的那个元素;
- 将它和数组的第一个元素交换位置(如果第一个元素就是最小元素,那么它就和自己交换);
- 在剩下的元素中找到最小的元素,将它与数组的第二个元素交换位置;如此往复,直到将整个数组排序。
算法的时间效率取决于比较的次数。
注:对于长度为N的数组,选择排序需要大约N^2/2次比较和N次交换。
特点:
- 运行时间和输入无关;
- 数据移动最少;每次交换改变两个数组元素的值,选择排序用了N次交换——交换次数和数组大小呈线性关系。
//升序排列
public static void sort(int[] a){
int N = a.length;
for(int i = 0;i < N;i++){
int min = i; //最小元素的索引
for(int j = i+1;j < N;j++){
if(a[j] < a[min]){
min = j;
}
}
int temp = a[i];
a[i] = a[min];
a[min] = temp;
}
}
二、插入排序
定义:选择要插入的元素,将其余所有元素在插入之前向右移动一位给要插入的元素腾出空间。
插入排序所需的时间取决于输入中元素的初始顺序。
注:对于随机排列的长度为N且主键不重复的数组,平均情况下插入排序需要N2/4次比较及N2/4次交换。最坏的情况下需要N2/2次比较及N2/2次交换,最好情况下需要N-1次比较和0次交换。
public int[] sortArray(int[] nums){
int N = nums.length;
for(int i = 1;i<N;i++){
//将nums[i]依次前插
for(int j = i;j>0;j--){
if(nums[j]<nums[j-1]){
int temp = nums[j];
nums[j] = nums[j-1];
nums[j-1] = temp;
}
}
}
return nums;
}
注:插入排序需要的交换操作和数组中倒置的数量相同,需要的比较次数大于等于倒置的数量,小于等于倒置的数量加上数组的大小再减一。
插入排序对于部分有序的数组十分高效,也很适合小规模数组;对于大规模乱序数组插入排序很慢,因为它只会交换相邻的元素。
==对于随机排序的无重复主键的数组,插入排序和选择排序的运行时间是平方级别的,两者之比应该是一个较小的常数。==插入排序通常应该比选择排序稍快一些。
三、希尔排序
定义:一种基于插入排序的快速排序算法。
思想:使数组中任意间隔为h的元素都是有序的(h有序数组);一个h有序数组就是h个互相独立的有序数组编织在一起组成的一个数组。对于每个h,用插入排序将h个子数组独立地排序/在插入排序的代码中将移动元素的距离由1改为h。
//希尔排序
public int[] sortArray(int[] nums){
int N = nums.length;
int h = 1;
while(h<N/3) h = 3*h+1; //h = 1,4,13,40...
//疑问:为什么间隔h选择N/3
while(h>=1){
//将数组变为h有序
for(int i = h;i<N;i++){
for(int j = i;j>=h;j-=h){
//将nums[i]依次前插h
if(nums[j]<nums[j-h]){
int temp = nums[j];
nums[j] = nums[j-h];
nums[j-h] = temp;
}
}
}
h = h/3; //将h有序的间隔逐渐缩小,直到间隔为1,此时排序完成
}
return nums;
}
希尔排序比选择排序和插入排序要快的多,并且数组越大,优势越大。
注:使用递增序列1,4,13,40…的希尔排序所需的比较次数不会超出N的若干倍乘以递增序列的长度。
四、归并排序
定义:将两个有序的数组归并成一个更大的有序数组
性质:保证将任意长度为N的数组排序时间和NlogN成正比
缺点:所需的额外空间和N成正比
原地归并:
自顶向下的归并排序:
五、快速排序
public int[] quickSort(int[] arr, int left, int right){
if(left > right){
return arr;
}
int low = left,high = right;
// 基准数
int temp = arr[low];
while(left < right){
while(temp <= arr[right] && left < right){
right--;
}
while(temp >= arr[left] && left < right){
left++;
}
if(left < right){
int swapTemp = arr[left];
arr[left] = arr[right];
arr[right] = swapTemp;
}
}
arr[low] = arr[left];
arr[left] = temp;
quickSort(arr, low, left-1);
quickSort(arr, left+1, high);
return arr;
}