写在开头
很久没有更新啦,今天来说一说排序的那些事。
排序,就是使一串记录,按照其中的某个或某些关键字的大小,递增或递减的排列起来的操作。平时一般提到的排序一般都是指升序。主要的排序算法有七种:插入排序、希尔排序、选择排序、堆排序、冒泡排序、快速排序、归并排序。
下面看我一一道来。
插入排序
//1.从无序区间拿出一个数
//2.与有序区间上的数比较
//3.插入合适的位置
//时间复杂度:最好 O(n) 最坏 O(n^2) 平均 O(n^2)
//空间复杂度:O(1)
//稳定
public static void insertSort(long[] array){
for(int i=0;i<array.length;i++){
long key=array[i+1];
for(int j=i;j>=0;j--){
if(key<array[j]){
array[j+1]=array[j];
}else{
break;
}
array[j+1]=key;
}
}
}
希尔排序
//1.选定一个间隔,把数组分成几个组
//2.组内排序
//3.间隔缩小再排序 直到gap小于等于1
//时间复杂度:最好 O(n) 最坏 O(n^2) 平均 O(n^1.3)
//空间复杂度:O(1)
//不稳定
public static void shellSort(long[] array){
int gap=array.length/2;
while(true){
insertSortGap(array,gap);
if(gap==1){
break;
}
gap=gap/2;
}
}
private static void insertSortGap(long[] array, int gap) {
for(int i=gap;i<array.length;i++){
long key=array[i];
int j;
for(j=i-gap;j>=0;j=j-gap){
if(array[i]<array[j]){
array[j+gap]=array[i];
}else{
break;
}
}
array[j+gap]=key;
}
}
选择排序
//1.遍历选出无序数组中的最大数 记下它的下标
//2.把它放到最后变成有序部分
//3.不断找出最大数往有序部分里放 直到遍历完
//时间复杂度:O(n^2)
//空间复杂度:O(1)
//不稳定
public static void selectSort(long[] array){
int maxIndex=0;
for(int i=0;i<array.length-1;i++){
for(int j=0;j<array.length-i;j++){
if(array[j]>array[maxIndex]){
maxIndex=j;
}
}
long t=array[maxIndex];
array[maxIndex]=array[array.length-i-1];
array[array.length-i-1]=array[maxIndex];
}
}
堆排序
//1.建大堆(最大的数在堆顶)
//2.把最大的数交换到最后(后面的部分逐渐有序)
//3.剩下无序部分向下调整
//4.重复交换 向下调整 直到有序
//时间复杂度:O(n*log(n))
//空间复杂度:O(1)
//不稳定
public static void heapSort(long[] array){
creatHeap(array,array.length);
for(int i=0;i<array.length-1;i++){
long t=array[0];
array[0]=array[array.length-i-1];
array[array.length-i-1]=t;
shiftDown(array,array.length-i-1,0);
}
}
private static void shiftDown(long[] array, int size, int index) {
while(2*index+1<size){//有左孩子
int maxIndex=2*index+1;
if(maxIndex+1<size&&array[maxIndex+1]>array[maxIndex]){
maxIndex++;
}//如果左孩子比右孩子小
if(array[index]>=array[maxIndex]){
break;
}//父节点比孩子节点大就不用换
long t=array[maxIndex];
array[maxIndex]=array[index];
array[index]=t;//交换
index=maxIndex;//继续向下比较
}
}
private static void creatHeap(long[] array, int size) {
for(int i=(size-2)/2;i>=0;i--){
shiftDown(array,size,i);
}//从最后一个有子树的下标开始向下调整 一直到第一个
}
冒泡排序
//1.在无序区间中相邻数比较 大数往后走 一次遍历找到一个最大的放在最后
//2.一直遍历比较 直到数组有序
//时间复杂度:最好 O(n) 最坏 O(n^2) 平均 O(n^2)
//空间复杂度:O(1)
//稳定
public static void bubbleSort(long[] array){
for(int i=0;i<array.length;i++){
boolean isSorted=true;
for(int j=0;j<array.length-1-i;j++){
if(array[j]>array[j+1]){
long t=array[j];
array[j]=array[j+1];
array[j+1]=t;
isSorted=false;
}
}
if(isSorted){
break;
}
}
}
快速排序
//1.选择第一个数 作为基准
//2.对其做partition 遍历数组 将比它小的数放在它的左侧 比它大的数放在右侧
//3.对左右两部分 进行相同的操作 递归
//时间复杂度: 最好 O(n*log(n)) 平均 O(n*log(n)) 最坏 O(n^2)
//空间复杂度:最好 O(log(n)) 平均 O(log(n)) 最坏 O(n)
//不稳定
public static void quickSort(long[] array){
quickSortInternal(array,0,array.length-1);
}
private static void quickSortInternal(long[] array, int leftIndex, int rightIndex) {
if(leftIndex>=rightIndex){
return;
}
int key=partition(array,leftIndex,rightIndex);
quickSortInternal(array,leftIndex,key-1);
quickSortInternal(array,key+1,rightIndex);
}
private static int partition(long[] array, int lowIndex, int highIndex) {
long key=array[lowIndex];
int leftIndex=lowIndex;
int rightIndex=highIndex;
while(leftIndex<rightIndex){
while(leftIndex<rightIndex&&array[rightIndex]>=key){
rightIndex--;
}//右下标往左走 找到比key小的数停下来
while (leftIndex<rightIndex&&array[leftIndex]<=key){
leftIndex++;
}//左下标往右走 找到比key大的数 停下
long t=array[leftIndex];
array[leftIndex]=array[rightIndex];
array[rightIndex]=t;
//交换
}//两下标相遇 跳出循环
long m=array[leftIndex];
array[leftIndex]=array[lowIndex];
array[lowIndex]=m;
//左下标停下的数与基准数交换
return leftIndex;
}
归并排序
//1.把数组分成两部分 不断划分 进行相同的操作 直到区间只剩下一个数 必然有序
//2.将有序的区间合并 递归
//时间复杂度:O(n*log(n))
//空间复杂度:O(n)
//稳定
public static void mergeSort(long[] array){
mergeSortInternal(array,0,array.length);
}
private static void mergeSortInternal(long[] array, int lowIndex, int highIndex) {
int size=highIndex-lowIndex;
if(size<=1){
return ;
}
int middleIndex=(highIndex+lowIndex)/2;
mergeSortInternal(array,lowIndex,middleIndex);
mergeSortInternal(array,middleIndex,highIndex);
merge(array,lowIndex,middleIndex,highIndex);
}
private static void merge(long[] array, int lowIndex, int middleIndex, int highIndex) {
int size=highIndex-lowIndex;
long[] extraArray=new long[size];
int leftIndex=lowIndex;
int rightIndex=middleIndex;
int extraIndex=0;
while(leftIndex<middleIndex&&rightIndex<highIndex){
if(array[leftIndex]<=array[rightIndex]){
extraArray[extraIndex++]=array[leftIndex++];
}else{
extraArray[extraIndex++]=array[rightIndex++];
}
}
if(leftIndex<middleIndex) {
while (leftIndex < middleIndex) {
extraArray[extraIndex++] = array[leftIndex++];
}
}else{
while(rightIndex<highIndex){
extraArray[extraIndex++]=array[rightIndex++];
}
}
for(int i=0;i<size;i++){
array[lowIndex+i]=extraArray[i];
}
}
好啦,排序算法就总结到这里啦,码字不易,欢迎批评指正!