java中的常见排序示例代码(含优化方案和拓展方法)
常见的排序方法有以下7种,会一一讲解,外加拓展的计数排序

一. 直接插入排序
public static void insetSort(int[] array){
for(int i=1;i<array.length;i++){
int j=i -1;
int tmp=array[i];
for(;j>=0;j--){
if(array[j]>tmp){
array[j+1]=array[j];
}else{
array[j+1]=tmp;
break;
}
}
array[j+1]= tmp;
}
}时间复杂度:O(N^2)
最坏情况下(逆序) 5 4 3 2 1
最好情况下(本身是有序的)O(N)
如果数据越有序,直接插入排序越快
空间复杂度:O(1)
稳定性:稳定的排序
本身如果是一个稳定的排序,可以实现为不稳定的
但是 如果一个排序 本身就是不稳定,不能实现为稳定的排序
二. 希尔排序
public static void shellSort(int[]array){
int gap=array.length;
while(gap>1){
gap=gap/2;
shell(array,gap);
}
}
private static void shell(int[] array, int gap) {
for(int i=gap;i<array.length;i++){
int j=i -gap;
int tmp=array[i];
for(;j>=0;j-=gap){
if(array[j]>tmp){
array[j+gap]=array[j];
array[j]=tmp;
}else{
array[j+gap]=tmp;
break;
}
}
array[j+gap]= tmp;
}
}时间复杂度: O(N^1.3~N^1.5)
空间复杂度:O(1)
稳定性:不稳定
三. 选择排序
private static void swap(int[] array,int i,int j){
int tmp=array[i];
array[i]=array[j];
array[j]=tmp;
}方法一
public static void selectSort(int[] array){
int left=0;
int right=array.length-1;
while(left<right){
int minIndex=left;
int maxIndex=left;
for (int i = left+1; i <=right; i++) {
if(array[i]<array[minIndex]){
minIndex=i;
}
if(array[i]>array[maxIndex]){
maxIndex=i;
}
}
swap(array,left,minIndex);
if(maxIndex==0){
maxIndex=minIndex;
}
swap(array,right,maxIndex);
left++;
right--;
}
}方法二
public static void selectSort1(int[] array){
for (int i = 0; i < array.length; i++) {
int minIndex=i;
for (int j = i+1; j < array.length; j++) {
if(array[j]<array[minIndex]){
minIndex=j;
}
}
swap(array,i,minIndex);
}
}时间复杂度:O(N^2)
和数据是否与有序无关
空间复杂度:O(1)
稳定性:不稳定
四. 堆排序
private static void swap(int[] array,int i,int j){
int tmp=array[i];
array[i]=array[j];
array[j]=tmp;
}public static void heapsort(int[] array){
createHeap(array);
int end= array.length-1;
while(end>0){
swap(array,0,end);
siftDown(array,0,end);
end--;
}
}
private static void createHeap(int[] array){
for (int parent = (array.length-1-1)/2; parent>=0; parent--) {
siftDown(array,parent,array.length);
}
}
private static void siftDown(int[] array, int parent, int end) {
int child=parent*2+1;
while(child<end){
if(child+1<end && array[child]<array[child+1]){
child++;
}
if(array[child]>array[parent]){
swap(array,parent,child);
parent=child;
child=parent*2+1;
}else{
break;
}
}
}时间复杂度:O(n*logN)
空间复杂度:O(1)
稳定性:不稳定
五. 冒泡排序
加入flg的判断是为了优化此排序
public static void bubbleSort(int[]array){
for (int i = 0; i < array.length-1; i++) {
boolean flg=false;
for (int j = 0; j < array.length-1-i; j++) {
if(array[j]>array[j+1]){
swap(array,j,j+1);
flg=true;
}
}
if(!flg){
break;
}
}
}时间复杂度:O(N^2)
注意:冒泡排序优化前的时间复杂度为O(
),优化后可以达到O(N)
空间复杂度:O(1)
稳定性:稳定
六. 快速排序(已优化)
insertSortRange() getMiddleNum() 是为了优化快速排序
private static void swap(int[] nums,int i,int j){
int tmp=nums[i];
nums[i]=nums[j];
nums[j]=tmp;
} public static void quickSort(int[] array) {
//quick(array,0,array.length-1);
quickNor(array,0,array.length-1);
}private static void quick(int[] array,int start,int end){
if(start>=end){
return;
}
if(end-start+1<=10){
insertSortRange(array,start,end);
return ;
}
int midIndex=getMiddleNum(array,start,end);
swap(array,start,midIndex);
int pivot=partition(array,start,end);
quick(array,start,pivot-1);
quick(array,pivot+1,end);
} private static void insertSortRange(int[] array,int start,int end){
for(int i=start+1;i<=end;i++){
int j=i -1;
int tmp=array[i];
for(;j>=0;j--){
if(array[j]>tmp){
array[j+1]=array[j];
}else{
array[j+1]=tmp;
break;
}
}
array[j+1]= tmp;
}
} private static int getMiddleNum(int[] array,int left,int right){
int mid=(left+right)/2;
if(array[left]<array[right]){
if(array[left]>array[mid]){
return left;
}else if(array[right]<array[mid]){
return right;
}else{
return mid;
}
}else{
if(array[right]>array[mid]){
return right;
}else if(array[left]<array[mid]){
return right;
}else{
return mid;
}
}
} private static int partition2(int[] array, int left, int right){
int tmp=array[left]; //挖坑法
while(left<right){
while(left<right && array[right]>=tmp){
right--;
}
array[left]=array[right];
while(left<right && array[left]<=tmp){
left++;
}
array[right]=array[left];
}
array[left]=tmp;
return left;
}时间复杂度:O(N*logN)
最坏情况下: 当数据给的是1 2 3 4 5 6 7 ……
9 8 7 6 5 4 1 ……
有序的情况下:O(N^2)
最好的情况下:O(N*logN)
注意:一般情况下,说快速排序的时间复杂度默认为 O(N*logN) 优化过后
空间复杂度:O(logN)
最坏情况下:O(N)
最好情况下:O(logN)
稳定性:不稳定
拓展:
1.partition的实现方法
一共有三种实现方法:挖坑法(推荐)
Hoare版
前后指针法
//挖坑法
private static int partition2(int[] array, int left, int right){
int tmp=array[left]; //挖坑法
while(left<right){
while(left<right && array[right]>=tmp){
right--;
}
array[left]=array[right];
while(left<right && array[left]<=tmp){
left++;
}
array[right]=array[left];
}
array[left]=tmp;
return left;
} //hoare版
private static int partitionHoare(int[] array, int left, int right){
int tmp=array[left];
int tmpLeft=left;
while(left<right){
while(left<right && array[right]>=tmp){
right--;
}
while(left<right && array[left]<=tmp){
left++;
}
swap(array,left,right);
}
swap(array,left,tmpLeft);
return left;
} //前后指针法
private static int partition(int[] array, int left, int right){
int cur=left+1;
int prev=left;
while(cur<=right){
if(array[cur]<array[left] && array[++prev]!=array[cur]){
swap(array,cur,prev);
}
cur++;
}
swap(array,prev,left);
return prev;
}2.非递归quick实现方法
public static void quickNor(int[] array,int start,int end){
Deque<Integer> stack =new ArrayDeque<>();
int pivot=partition(array,start,end);
if(pivot>start+1){
stack.push(start);
stack.push(pivot-1);
}
if(pivot<end-1){
stack.push(pivot+1);
stack.push(end);
}
while(!stack.isEmpty()){
end=stack.pop();
start=stack.pop();
pivot=partition(array,start,end);
if(pivot>start+1){
stack.push(start);
stack.push(pivot-1);
}
if(pivot<end-1){
stack.push(pivot+1);
stack.push(end);
}
}
}七. 归并排序
public static void mergesort(int[] array){
mergeSortTmp(array,0,array.length-1);
} private static void mergeSortTmp(int[] array,int left,int right){
if(left>=right){
return;
}
int mid=(left+right)/2;
mergeSortTmp(array,left,mid);
mergeSortTmp(array,mid+1,right);
merge(array,left,mid,right);
}
private static void merge(int[] array, int left, int mid, int right){
int[] tmp=new int[[right-left+1];
int k=0;
int s1=left;
int s2=mid+1;
while(s1<=mid && s2<=right){
if(array[s1]<array[s2]){
tmp[k++]=array[s1++];
}else{
tmp[k++]=array[s2++];
}
}
while(s1<=mid){
tmp[k++]=array[s1++];
}
while(s2<=right){
tmp[k++]=array[s2++];
}
for (int i = 0; i < k; i++) {
array[i+left]=tmp[i];
}
}时间复杂度:O(N*logN)
空间复杂度:O(N)
稳定性:稳定
拓展:非递归实现
public static void mergeSortNor(int[] array){
int gap=1;
while(gap<array.length){
for (int i = 0; i < array.length; i=i+gap*2) {
int left=i;
int mid=left+gap-1;
if(mid>=array.length){
mid=array.length-1;
}
int right=mid+gap;
if(right>=array.length){
right=array.length-1;
}
merge(array,left,mid,right);
}
gap*=2;
}
}八. 计数排序(非基于比较排序)
public static void countSort(int[] array){
int maxVal=array[0];
int minVal=array[0];
for (int i = 0; i < array.length; i++) {
if(minVal>array[i]){
minVal=array[i];
}
if(maxVal<array[i]){
maxVal=array[i];
}
}
int len=maxVal-minVal+1;
int[] count=new int[len];
for (int i = 0; i < array.length; i++) {
int index=array[i];
count[index-minVal]++;
}
int index=0;
for (int i = 0; i < count.length; i++) {
while(count[i]!=0){
array[index]=i+minVal;
index++;
count[i]--;
}
}
}适用范围:数据集中在一定的范围内
如:0~9 89~99 等
时间复杂度:O(范围+N)
范围越大 越慢
空间复杂度:O(范围)
稳定性:稳定
总结:
稳定的排序:
冒泡排序、插入排序、归并排序
表格对比:

到此这篇关于java中常见排序的文章就介绍到这了,更多相关java常见排序内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
相关文章
教你用java stream对集合中的对象按指定字段进行分组并统计
这篇文章主要给大家介绍了关于用java stream对集合中的对象按指定字段进行分组并统计的相关资料,本文主要介绍了如何利用Java的Stream流来实现在list集合中,对具有相同name属性的对象进行汇总计算的需求,需要的朋友可以参考下2024-10-10
Intellij IDEA创建spring-boot项目的图文教程
本文通过图文并茂的形式给大家介绍了Intellij IDEA创建spring-boot项目的教程,本文给大家介绍的非常详细,具有参考借鉴价值,需要的朋友参考下吧2018-01-01
详解MyBatis开发Dao层的两种方式(Mapper动态代理方式)
这篇文章主要介绍了详解MyBatis开发Dao层的两种方式(Mapper动态代理方式),小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧2018-12-12
Java线程编程中isAlive()和join()的使用详解
这篇文章主要介绍了Java线程编程中isAlive()和join()的使用详解,是Java入门学习中的基础知识,需要的朋友可以参考下2015-09-09
2022 最新 IntelliJ IDEA 详细配置步骤演示(推荐)
作为一名开发人员,第一肯定是选择一款趁手的开发利器,本人使用 Java 偏多,这里推荐使用 IntelliJ IDEA, 俗称神级开发工具,具体的安装过程就不过多赘述了,有需要了解的朋友可以参考下本文2022-09-09


最新评论