1. 插入排序(Insertion Sort)
2. 快排(Quick Sort)
3. 归并排序(Merge Sort)
先说个题外话,arrays.sort是由Timsort实现的,Timsort是归并排序的优化版
一、插入排序
- 从第二个元素(第一个要被排序的新元素)开始,从后向前扫描之前的元素序列
- 如果当前扫描的元素大于新元素,将扫描元素移动到下一位
- 重复2,直到找到一个小于或者等于新元素的位置
- 将新元素插入到该位置
- 对于之后的元素重复步骤1~4,完成升序排序
public void insertionSort(int[] array):
for(int i=1;i<array.length;i++) //从第二个元素开始
{
int cur=array[i];
int j=i-1;
while(j>=0 && array[j]>cur) //处理的数是否大于这个目标数;如果想降序,就用小于号就行
{
array[j+1]=arry[j];
j--; //从后向前循环
}
array[j+1]=cur;
}
时间复杂度:O(n^2)
空间复杂度:O(1)
二、快排 QuickSort
时间复杂度是:O(nlogn),最坏是O(n^2)(当从大到小排,最小的在最右边,刚好被选取为pivot)
空间复杂度:O(logn),最坏是O(n)
步骤:
- 对于当前的数组,取最后一个元素当作基准数(pivot)
- 将所有比基准数小的元素排到基准数之前,比基准数大的排在基准数之后
- 当基准数被放到准确的位置之后,根据基数数的位置将数组切分为前后两个子数组
- 对子数组采用步骤1~4的递归操作,直到子数组的长度小于等于1为止
public class quicksort {
static void quickSort(int[] array,int left,int right)
{
if(left>=right) return;
int partitionIndex=partition(array,left,right);
quickSort(array,left,partitionIndex-1);
quickSort(array,partitionIndex+1,right);
}
static int partition(int[] array,int left,int right)
{
int pivot=array[right];
int leftIndex=left;
int rightIndex=right-1;
while(true)
{
while (leftIndex<right && array[leftIndex]<=pivot)
{
leftIndex++;
}
while (rightIndex>=left && array[rightIndex]>pivot)
{
rightIndex--;
}
if(leftIndex>rightIndex) break;
swap(array,leftIndex,rightIndex);
}
swap(array,leftIndex,right);
return leftIndex;
}
static void swap(int[] array,int left,int right)
{
int temp=array[left];
array[left]=array[right];
array[right]=temp;
}
public static void main(String[] args) {
int[] arr={1,4,3,6,5};
quickSort(arr,0,4);
for(int num:arr) {
System.out.println(num);
}
}
}
三、归并排序 Merge Sort
思想:(分治法)将一个数组分为两个子数组,通过递归重复将数组切分到只剩下一个元素为止。然后将每个子数组中的元素排序后合并,通过不断合并子数组,最后就会拿到一个排好序的大数组。
public class MergeSort {
public static void sort(int []arr){
int []temp = new int[arr.length];//在排序前,先建好一个长度等于原数组长度的临时数组,避免递归中频繁开辟空间
sort(arr,0,arr.length-1,temp);
}
private static void sort(int[] arr,int left,int right,int []temp){
if(left<right){
int mid = (left+right)/2;
sort(arr,left,mid,temp);//左边归并排序,使得左子序列有序
sort(arr,mid+1,right,temp);//右边归并排序,使得右子序列有序
merge(arr,left,mid,right,temp);//将两个有序子数组合并操作
}
}
private static void merge(int[] arr,int left,int mid,int right,int[] temp){
int i = left;//左序列指针
int j = mid+1;//右序列指针
int t = 0;//临时数组指针
while (i<=mid && j<=right){
if(arr[i]<=arr[j]){
temp[t++] = arr[i++];
}else {
temp[t++] = arr[j++];
}
}
while(i<=mid){//将左边剩余元素填充进temp中
temp[t++] = arr[i++];
}
while(j<=right){//将右序列剩余元素填充进temp中
temp[t++] = arr[j++];
}
t = 0;
//将temp中的元素全部拷贝到原数组中
while(left <= right){
arr[left++] = temp[t++];
}
}
}