1 高级排序
排序方法 | 简述 |
---|---|
希尔排序 | 间隔分组插入排序 |
归并排序 | 两个子数组分别有序,依次比较放入新数组 |
快速排序 | 通过分界值将数组分成左右两部分独立排序 |
- 希尔排序和归并排序在处理大批量数据时差别不是很大
- 快速排序和归并排序是互补的:
– ① 归并排序将数组分成两个子数组分别排序,并将有序的子数组归并从而将整个数组排序;而快速排序的方式则是当两个数组都有序时,整个数组自然就有序了。
– ② 在归并排序中,一个数组被等分为两半,归并调用发生在处理整个数组之前;在快速排序中,切分数组的位置取决于数组的内容,递归调用发生在处理整个数组之后。
1.1 希尔排序
public class ShellSort{
//测试
public static void main(String[] args){
int[] arr={9,6,11,3,5,12,8,7,10,15,14,4,1,13,2};
sort(arr);
for(int i=0;i<arr.length;i++){
System.out.print(arr[i]+" ");
}
}
//希尔排序算法
public static void sort(int[] arr){
int h=1;
//Knuth序列,效率比arr.length/2高
while(h<=arr.length/3){
h=h*3+1;
}
for(int gap=h;gap>0;gap=(gap-1)/3){
for(int i=gap;i<arr.length;i++){
for(int j=i;j>gap-1;j-=gap){
if(arr[j]<arr[j-gap]){
swap(arr,j,j-gap);
}
}
}
}
}
//数组元素i和j交换位置
public void swap(int[] arr,int i,int j){
int temp=arr[i];
arr[i]=arr[j];
arr[j]=temp;
}
}
1.2 归并排序
public class MergeSort{
//测试
public static void main(String[] args){
int[] arr={1,4,7,8,3,6,9};
sort(arr,0,6);
for(int i=0;i<arr.length;i++){
System.out.print(arr[i]+" ");
}
}
public static void sort(int[] arr,int left,int right){
//left最左边,right最右边
if(left==right) return;
//分成两半
int mid=left+(right-left)/2;
//左边排序
sort(arr,left,mid);
//右边排序
sort(arr,mid+1,right);
//左右归并
merge(arr,left,mid+1,right);
}
//归并,左右两个子数组已经有序
static void merge(int[] arr,int leftPtr,int rightPtr,int rightBound){
int mid=rightPtr-1;
int[] temp=new int[rightBound-leftPtr+1];
int i=leftPtr;
int j=rightPtr;
int k=0;
while(i<=mid && j<=rightBound){
if(arr[i]<=arr[j]){
temp[k++]=arr[i++];
}else{
temp[k++]=arr[j++];
}
}
while(i<=mid)
temp[k++]=arr[i++];
while(j<=rightBound)
temp[k++]=arr[j++];
for(int m=0;m<temp.length;m++)
arr[leftPtr+m]=temp[m];
}
//数组元素i和j交换位置
static void swap(int[] arr,int i,int j){
int temp=arr[i];
arr[i]=arr[j];
arr[j]=temp;
}
}
补充:JAVA对象排序
TimSort
- 混合、稳定高效的排序算法,源自二分插入排序和归并排序
- 已经排好序的数据块称为“run”,也就是一个个分区,TimSort迭代数据元素,将其放到不同的run里面,同时针对这些run,按规则进行合并至只剩一个,则这个仅剩的 run 即为排好序的结果
- 简要步骤:根据数列大小产生minrun(划分run的一个条件值)—>依次寻找待排序序列中的run—>合并run
1.3 快速排序
public class Quick{
//测试
public static void main(String[] args){
int[] arr={6, 1, 2, 7, 9, 3, 4, 5, 8};
sort(arr,0,arr.length-1);
for(int i=0;i<arr.length;i++){
System.out.print(arr[i]+" ");
}
}
//快速排序算法
//对数组内的元素进行排序
public static void sort(int[] arr,int leftBound,int rightBound){
if(leftBound>=rightBound) return;
//对arr数组中,从leftBound到rightBound的元素进行切分
int mid=partition(arr,leftBound,rightBound);
//对左边分组中的元素进行排序
sort(arr,leftBound,mid-1);
//对右边分组中的元素进行排序
sort(arr,mid+1,rightBound);
}
static int partition(int[] arr,int leftBound,int rightBound){
int pivot=arr[rightBound];
int left=leftBound;
int right=rightBound-1;
while(left<=right){
while(arr[left]<=pivot)
left++;
while(arr[right]>pivot)
right--;
if(left<right)
swap(arr,left,right);
}
swap(arr,left,rightBound);
}
//数组元素i和j交换位置
static void swap(int[] arr,int i,int j){
int temp=arr[i];
arr[i]=arr[j];
arr[j]=temp;
}
}
p.s.
快排改进—>双轴快排(找两个数,三段式less、mid、more)