1.堆排序
(1)堆排序首先要建一个堆
(2)以大堆为例,只有根节点是最大的,根节点和最后一个元素交换
(3)交换之后树发生了变化,调用向下调整的方法
package cn.tan.allKindsOfSort;
import java.util.Arrays;
public class HeapSort {
private static void swap(long[] arr,int i,int j){
long t=arr[i];
arr[i]=arr[j];
arr[j]=t;
}
public static void heapSort(long[] arr){
//1.建立大堆
createBigHeap(arr);
for(int i=0;i<arr.length-1;i++){
// 2.1 交换之前的无序区间 [0, n - i)
swap(arr,0,arr.length-i-1);
// 交换之后的无序区间 [0, n - i - 1),元素个数 n - i - 1 个
//经过了交换需要对对里面的0号下标进行调整,堆里的元素个数就是无序区间的个数
shiftDown(arr,arr.length-i-1,0);
}
}
private static void shiftDown(long[] arr, int size,int index) {
while(2*index+1<size){
int maxIdx=2*index+1;
int right=maxIdx+1;
if(right<size&&arr[maxIdx]<arr[right]){
maxIdx=right;
}
if(arr[index]>=arr[maxIdx]){
return;
}
swap(arr,index,maxIdx);
index=maxIdx;
}
}
private static void createBigHeap(long[] arr) {
int index=(arr.length-2)/2;
for(int i=index;i>=0;i--){
shiftDown(arr,arr.length,i);
}
}
public static void main(String[] args) {
long[] arr={9,8,7,6,5,4};
heapSort(arr);
System.out.println(Arrays.toString(arr));
}
}
2.插入排序
(1)插入排序是无序区间的第一个数与有序区间的数进行比较插入到相应的位置
package cn.tan.allKindsOfSort;
import java.util.Arrays;
//插入排序
public class InsertSort {
public static void insertSort(long[] arr){
for(int i=0;i<arr.length-1;i++){
//因为单个数的时候一定是有序的,所以第一个肯定是不用进行操作的就对arr.length-1个数进行操作
//之后就是根据当前的数和之前的有序区间进行比较
long k=arr[i+1];//这个就是当前要进行插入操作的数
//进行比较的操作
//比较分两种情况,如果当前数很大,一定放在有序数组的最后
//如果较小,就需要与有序数组比较插入到相应位置
int j;
for( j=i;j>=0;j--){
if(k>=arr[j]){
break;
}
if(k<arr[j]){
arr[j+1]=arr[j];
}
}
arr[j+1]=k;
}
}
public static void main(String[] args) {
long[] arr={1,3,4,2,6,5,9,7};
insertSort(arr);
System.out.println(Arrays.toString(arr));
}
}
3.希尔排序
(1)插入排序是希尔排序的特殊情况
(2)这里有序区间是相差gap个距离的一组数
(3)比较一次就会得到相差gap距离的一组有序的数
(4)希尔排序时就不断地缩小
package cn.tan.allKindsOfSort;
import java.util.Arrays;
//希尔排序
public class InsertSortWithGap {
public static void insertSort(long[] arr){
for(int i=0;i<arr.length-1;i++){
//因为单个数的时候一定是有序的,所以第一个肯定是不用进行操作的就对arr.length-1个数进行操作
//之后就是根据当前的数和之前的有序区间进行比较
long k=arr[i+1];//这个就是当前要进行插入操作的数
//进行比较的操作
//比较分两种情况,如果当前数很大,一定放在有序数组的最后
//如果较小,就需要与有序数组比较插入到相应位置
int j;
for( j=i;j>=0;j--){
if(k>=arr[j]){
break;
}
if(k<arr[j]){
arr[j+1]=arr[j];
}
}
arr[j+1]=k;
}
}
private static void InsertSortWithGap(long[] arr,int gap){
for(int i=0;i<arr.length-gap;i++){
long k=arr[i+gap];
int j;
for(j=i;j>=0&&arr[j]>k;j=j-gap){
arr[j+gap]=arr[j];
}
arr[j+gap]=k;
}
}
public static void shellSort(long[] arr){
int gap=arr.length/2;
while(gap!=1){
InsertSortWithGap(arr,gap);
gap=gap/2;
}
insertSort(arr);
}
public static void main(String[] args) {
long[] arr={9,8,6,4,1,5,7,2,0,3};
shellSort(arr);
System.out.println(Arrays.toString(arr));
}
}
4.归并排序
(1)归并排序用左闭右开的区间比较好操作
(2)归并的过程就是左右两个区间的元素进行比较,谁小谁进入临时的数组
(3)最后记得把左边区间或者右边区间剩下的没有比的加入到临时区间
package cn.tan.allKindsOfSort;
import java.util.Arrays;
public class MergeSort {
public static void mergesort(long[] arr){
mergeSortRange(arr,0,arr.length);
}
// 这里的 [from, to) 是左闭右开来表示区间的
private static void mergeSortRange(long[] arr, int from, int to) {
int size=to-from;
if(size<=1){
return;
}
int mid=from+(size/2);
mergeSortRange(arr,from,mid);
mergeSortRange(arr,mid,to);
merge(arr,from,mid,to);
}
private static void merge(long[] arr, int from, int mid, int to) {
int size=to-from;
long[] other=new long[size];
int left=from;//左边小区间的下标
int right=mid;//右边小区间的下标
int dest=0;//临时空间的下标
while (left<mid&&right<to){
if(arr[left]<arr[right]){
other[dest++]=arr[left++];
}else{
other[dest++]=arr[right++];
}
}
while(left<mid){
other[dest++]=arr[left++];
}
while (right<to){
other[dest++]=arr[right++];
}
for (int i = 0; i < size; i++) {
arr[from+i]=other[i];
}
}
public static void main(String[] args) {
long[] array = { 9, 5, 8, 7, 1, 6, 0, 4, 2, 3 };
mergesort(array);
System.out.println(Arrays.toString(array));
}
}
5.快速排序
(1)切记partition是快排的一步操作,不是整个快速排序过程
(2)进行一次partition就是返回一个基准值的过程
(3)partitionA和partitionB方法类似
(4)partitionC
package cn.tan.allKindsOfSort;
import java.util.Arrays;
public class QuickSort {
private static void swap(long[] arr,int i,int j){
long t=arr[i];
arr[i]=arr[j];
arr[j]=t;
}
public static void quickSort(long[] arr){
quickSortRange(arr,0,arr.length-1);
}
private static void quickSortRange(long[] arr, int from, int to) {
if(to-from+1<=1){
return ;
}
int pi=partitionC(arr,from,to);
quickSortRange(arr,from,pi-1);
quickSortRange(arr,pi+1,to);
}
private static int partitionA(long[] arr, int from, int to) {
long pivot=arr[to];
int left=from;
int right=to;
/*
分为
*/
while(left<right){
while(left<right&&arr[left]<=pivot){
left++;
}
// 循环停止时,说明 array[left] > pivot
while(left<right&&arr[right]>=pivot){
right--;
}
// 循环停止时,说明 array[right] < pivot
// 两边都卡住时,交换 [left] 和 [right] 位置的元素
swap(arr,left,right);
}
// 说明 left == right,说明 [left, right) 区间内一个元素都没有了
// 所有元素都和 pivot 进行过比较了,然后都在各自应该的位置上了
// 并且 array[left] 一定是 >= pivot 的第一个元素(不给大家证明了)
swap(arr,to,left);
return left;
}
/*
填坑式的partition方法
*/
private static int partitionB(long[] arr, int from, int to) {
/*
pivot已经被记录下来了,可以看做该位置已经没有用了,可以变成一个坑了
*/
long pivot=arr[to];
int left=from;
int right=to;
while(left<right){
while(left<right&&arr[left]<=pivot){
left++;
}
//当arr【left】>pivot的时候,直接填坑right下标处,arr[right]=arr[left];
arr[right]=arr[left];
while(left<right&&arr[right]>=pivot){
right--;
}
//当arr【right】<pivot的时候,直接填坑left下标处,arr[left]=arr[right];
arr[left]=arr[right];
}
arr[left]=pivot;
return left;
}
private static int partitionC(long[] arr,int from,int to){
int s=from;
long pivot=arr[to];
for(int i=from;i<to;i++){
if(arr[i]<pivot){
swap(arr,i,s);
s++;
}
}
arr[to]=arr[s];
arr[s]=pivot;
return s;
}
public static void main(String[] args) {
// long[] array = {-1, -1, -1, -1, 3, 5, 2, 7, 6, 4, 9, 8, -1, -1, -1 };
long[] array = {-1, -1, -1, -1, 3, 5, 2, 7, 6, 4, 9, 4, -1, -1, -1 };
// long[] array = {-1, -1, -1, -1, 1, 2, 3, 4, 5, 6, 7, 8, -1, -1, -1 };
// long[] array = {-1, -1, -1, -1, 8, 7, 6, 5, 4, 3, 2, 1, -1, -1, -1 };
//int pi = partitionB(array, 4, 11);
//System.out.println(pi);
quickSort(array);
System.out.println(Arrays.toString(array));
}
}
6.选择排序
(1)选择排序就是求最值法
(2)求一个最值然后放到前面或者后面,慢慢构成有序区间
package cn.tan.allKindsOfSort;
import java.util.Arrays;
//选择排序
public class SelectSort {
private static void swap(long[] arr,int i,int j){
long t=arr[i];
arr[i]=arr[j];
arr[j]=t;
}
//选择排序是在每一趟中选出来最大的值得索引,然后再交换到最后或者最前面
public static void selectSort(long[] arr){
for(int i=0;i<arr.length-1;i++){
//假定最大值索引为第一个位置
int maxIndex=0;
for(int j=1;j<arr.length-i;j++){
if(arr[j]>arr[maxIndex]){
maxIndex=j;
}
}
swap(arr,maxIndex,arr.length-i-1);
}
}
public static void main(String[] args) {
long[] arr={9,8,7,6,5,4};
selectSort(arr);
System.out.println(Arrays.toString(arr));
}
}
7.冒泡排序
package cn.tan.allKindsOfSort;
import java.util.Arrays;
//冒泡排序
public class Sort {
private static void swap(long[] arr,int i,int j){
long t=arr[i];
arr[i]=arr[j];
arr[j]=t;
}
public static void bubbleSort(long[] arr){
for (int i = 0; i < arr.length-1; i++) {
for(int j=0;j<arr.length-i-1;j++){
if(arr[j]>arr[j+1]){
swap(arr,j,j+1);
}
}
}
}
public static void main(String[] args) {
//long[] arr={9,8,7,6,5,4};
//long[] arr={4,5,6,7,8,9};
long[] arr={1,1,1,1,1,1};
bubbleSort(arr);
System.out.println(Arrays.toString(arr));
}
}