开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第30天,[点击查看活动详情]
归并排序
mergeSort
是建立在归并操作上的。
采用分治法。将已有序的子序列合并,得到完整的有序序列
将两个有序表合并成一个有序表,称为2路归并
特点
时间复杂度:O(nlog2n)
空间复杂度:O(n)
是稳定的
代码
import java.util.Random;
public class MergeSort{
public static void main(String[] args){
int[] arr=new int[20];
Random random=new Random();
for(int i=0;i<arr.length;i++){
arr[i]=random.nextInt(50);
}
mergeSort(arr,0,arr.length-1);
System.out.println(Arrayds.toString(arr));
}
private static void mergeSort(int[] arr,int l,int r){
//优先排序,如果元素较少
if(r-l<=10){
//改造希尔排序,使用于一个区间
/*
shellSort(arr,0,3)//0~3,进行排序
public static void shellSort(int[] arr,int l,int r){
int len = r-l+1;
for(gap=len)
for(i<=r)
for(j-gap>=l)
}
*/
ShellSort.shellSort(arr,l,r);
return;
}
int mid=(l+r)/2;
//分
mergeSort(arr,l,mid);
mergeSort(arr,mid+1,r);
//合
//r如果左边的最后小于右边的最初,则没必要合并
if(arr[mid]>arr[mid+1]){
merge(arr,l,mid,r);
}
}
private static void merge(int[] arr,int l,int mid,int r){
int[] aux=new int[r-l+1];
for(int i=l;i<=r;i++){
aux[i-l]=arr[i];
}
int i=l;
int j=mid+l;
for(int k=l;k<=r;k++){
if(i>mid){
arr[k]=aux[j-l];
j++;
}else if(j>r){
arr[k]=aux[i-l];
i++;
}else if(aux[i-l] < aux[j-l]){
arr[k]=aux[i-l];
i++;
}else{
arr[k]=aux[j-l];
j++;
}
}
}
}
堆排序
利用堆数据结构设计的算法。
堆积是一个近似完全二叉树的结构,同时满足堆积的性质。即子节点的键值或索引总小于(大于)它的父节点。
二叉堆是一颗完全二叉树。
堆中的某个结点的值不大于父节点的值——最大堆。
下层的某一元素不一定小于上层的某一元素。
既然是完全二叉树,所以可以用数组定义该结构。
父节点的角标:(i-1)/2
左孩子的角标:2i+1
右孩子的角标:2i+2
特点
时间复杂度:O(nlog2n)
空间复杂度:s(1)
是不稳定的。
代码
public class HeapSort{
public static void main(String[] args){
int[] arr=new int[20];
Random random=new Random();
for(int i=0;i<arr.length;i++){
arr[i]=random.nextInt(50);
}
heapSort(arr);
System.out.println(Arrays.toString(arr));
}
private static int len;
private static void heapSort(int[] arr){
len=arr.length;
//1,将传入的数组,堆化
heapify(arr);
//2,将最大值与最后一个进行交换,再堆化
for(int i=arr.length-1;i>=0;i--){
swap(arr,0,i);
len--;
heapify(arr);
}
}
private static void heapify(int[] arr){
for(int i=len-1;i>=0;i--){
sifDown(arr,i);
}
System.out.println(Arrays.toString(arr));
}
private static void sifDown(int[] arr,int k){
while(leftChild(k)<len){
int j = leftChild(k);
if(j+1<len && arr[j+1]>arr[j]){
j=rightChild(k);
}
if(arr[k]<arr[j]){
swap(arr,k,j);
k=j;
}else{
break;
}
}
}
private static void swap(int[] arr,int i,int j){
int temp=arr[i];
arr[i]=arr[j];
arr[j]=temp;
}
private static int leftChild(int i){
return i*2+1;
}
private static int rightChild(int i){
return i*2+2;
}
private static int parent(int i){
return (i-1)/2;
}
}