1、折半插入排序
例如:数组{12,2,6,1,5}
第一次:在[0,1)之间找插入2的位置==>left = [0] ==> {2,12,6,1,5}
第二次:在[0,2)之间找插入6的位置==>left = [1] ==> {2,6,12,1,5}
第三次:在[0,3)之间找插入1的位置==>left = [0] ==>{1,2,6,12,5}
第四次:在[0,4)之间找插入5的位置==>left = [2] ==>{1,2,5,6,12}
@Test
public void test(){
int[] arr = {12,2,6,1,5};
sort(arr);
System.out.println(Arrays.toString(arr));
}
public void sort(int[] arr){
for (int i=1; i<arr.length; i++){
//找到[0,i)之间插入arr[i]的位置
//使用二分查找法
int left = 0;
int right=i-1;
while (left<=right){
int mid = (left + right)/2;
if(arr[i]<=arr[mid]){
right = mid - 1;
}else{
left = mid + 1;
}
}
//在[0,i)插入arr[i]
if(left < i){
int temp = arr[i];
System.arraycopy(arr,left,arr,left+1,i-left);
arr[left] = temp;
}
}
}
2、快速排序
@Test
public void test(){
int[] arr = {5, 2, 6, 12, 1,7,9};
sort(arr,0, arr.length-1);
System.out.println(Arrays.toString(arr));
}
//将[start+1,end]之间的元素分为两拨,左边的所有元素比arr[start]小,右边的所有元素比arr[start]大
public void sort(int[] arr, int start, int end) {
if (start >= end) //无需排序
return;
int left = start + 1;
int right = end;
int pivot = arr[start];//基准元素
while (left <= right) {
//从左往右,从[start+1]开始找比基准元素大的数arr[left],让它与arr[right]交换
//当arr[left]大于arr[start]就停止循环,因为此时找到了比基准元素大的数arr[left]
while (left <= right && arr[left] <= pivot) {
//必须先判断left<=right,否则可能数组索引越界异常。
left++;
}
//从右往左,从[end]开始找比基准元素小的数arr[right],让它与arr[left]交换
//当arr[right]小于基准元素就停止循环,因为此时找到了比基准元素小的数arr[right]
while (right >= left && arr[right] >= pivot) {
right--;
}
//交换左右的两边的元素,然后left++ ,right--,即从下一个位置继续查找
if (left < right) {
int temp = arr[left];
arr[left++] = arr[right];
arr[right--] = temp;
}
}
//循环结束,left与right已经重合,甚至交错,这时交换基准元素与right位置元素
arr[start] = arr[right];
arr[right] = pivot;
//此时[start,right-1]之间都是比arr[start]小的数据了,但是它们还未排序
//此时[right+1,end]之间都是比arr[start]大的数据了,但是它们还未排序
//所以需要分别对[start,right-1]、[right+1,end]之间元素重复上面的操作继续排序
sort(arr, start, right - 1);
sort(arr, right + 1, end);
}