目录
思想:每次左右两两比较,把最大或最小元素放到最后,直到整体有序
时间复杂度:O(n²)
稳定性:稳定
- package com.xch2.DiGui;
-
- import java.util.*;
-
- public class Main7_1 {
-
- //冒泡排序
- //小到大排序
- public static void f8(int[] arr) {
- boolean flag=true;
- int mid;
- for (int i = arr.length-1; i > 0; i--) {
- for (int j = 0; j < i; j++) {
- if(arr[j]>arr[j+1]) {
- mid=arr[j];
- arr[j]=arr[j+1];
- arr[j+1]=mid;
- flag=false;
- }
- }
- //优化,提前整体有序
- if(flag) {
- return;
- }
- flag=true;
- }
- }
-
- //大到小排序
- public static void f9(int[] arr) {
- boolean flag=true;
- int mid;
- for (int i = arr.length-1; i > 0; i--) {
- for (int j = 0; j < i; j++) {
- if(arr[j]
1]) { - mid=arr[j];
- arr[j]=arr[j+1];
- arr[j+1]=mid;
- flag=false;
- }
- }
- //优化,提前整体有序
- if(flag) {
- return;
- }
- flag=true;
- }
- }
-
- public static void main(String[] args) {
- // TODO 自动生成的方法存根
- int[] arr= {5,2,8,9,2,6,7,10};
- // f8(arr);
- f9(arr);
- System.out.println(Arrays.toString(arr));
-
- }
-
- }
思想:每次从待排数组中取一个最小或最大的元素放到前面,直到整体有序
时间复杂度:O(n²)
稳定性:不稳定
- package com.xch2.DiGui;
-
- import java.util.*;
-
- public class Main7_1 {
-
- //选择排序(简单选择排序)
- //小到大排序
- public static void f6(int[] arr) {
- int min=arr[0],p=0,mid;
- for (int i = 0; i < arr.length-1; i++) {
- for (int j = i+1; j < arr.length; j++) {
- if(arr[j]
- p=j;
- min=arr[j];
- }
- }
- mid=arr[p];
- arr[p]=arr[i];
- arr[i]=mid;
-
- min=arr[i+1];
- p=i+1;
- }
- }
-
- //大到小排序
- public static void f7(int[] arr) {
- int max=arr[0],p=0,mid;
- for (int i = 0; i < arr.length-1; i++) {
- for (int j = i+1; j < arr.length; j++) {
- if(arr[j]>max) {
- p=j;
- max=arr[j];
- }
- }
- mid=arr[p];
- arr[p]=arr[i];
- arr[i]=mid;
-
- max=arr[i+1];
- p=i+1;
- }
- }
-
- public static void main(String[] args) {
- // TODO 自动生成的方法存根
- int[] arr= {5,2,8,9,2,6,7,10};
- // f6(arr);
- f7(arr);
- System.out.println(Arrays.toString(arr));
-
- }
-
- }
3、插入排序
思想:每次取一个元素拆入到已排序的数组中有序的位置,直到整体有序
时间复杂度:O(n²)
稳定性:稳定
- package com.xch2.DiGui;
-
- import java.util.*;
-
- public class Main1 {
-
- //插入排序
- static void f8(int[] arr,int k) {//k代表个数或数组长度
- if(k==1)//k代表元素个数
- return;
- f8(arr,k-1);//先把前k-1个元素排好序
- int index=k-1;//index代表数组下标
- while(index>0&&arr[index]
1]) { - int mid=arr[index];
- arr[index]=arr[index-1];
- arr[index-1]=mid;
- index--;
- }
- }
-
- //方法二(前往后排序)
- static void f9(int[] arr,int index) {//index代表开始下标,为0
- if(index==arr.length)
- return;
- int r=index;
- while(r>0&&arr[r]
1]) { - int mid=arr[r];
- arr[r]=arr[r-1];
- arr[r-1]=mid;
- r--;
- }
- f9(arr,index+1);//把剩余的index+1下标元素排序
- }
-
- //方法三(后往前排序)
- static void f10(int[] arr,int index) {//index代表结束下标,为arr.length-1
- if(index==-1)
- return;
- int r=index;
- while(r
1&&arr[r]>arr[r+1]) { - int mid=arr[r];
- arr[r]=arr[r+1];
- arr[r+1]=mid;
- r++;
- }
- f10(arr,index-1);//把剩余的index-1下标元素排序
- }
-
- public static void main(String[] args) {
- // TODO 自动生成的方法存根
- int[] arr1=new int[]{2,5,99,5,1,-5,-9};
- f8(arr1,7);
- for (int i = 0; i < arr1.length; i++) {
- System.out.print(arr1[i]+",");
- }
- System.out.println();
-
- int[] arr2=new int[]{2,5,99,5,1,-5,-9};
- f9(arr2,0);
- for (int i = 0; i < arr2.length; i++) {
- System.out.print(arr2[i]+",");
- }
- System.out.println();
-
- int[] arr3=new int[]{2,5,99,5,1,-5,-9};
- f10(arr3,6);
- for (int i = 0; i < arr3.length; i++) {
- System.out.print(arr3[i]+",");
- }
- System.out.println();
-
- }
-
- }
4、希尔排序
思想:确定一个渐进缩小的增量,进行分组后在组内插入排序,直到整体有序(插入排序的进阶版)
时间复杂度:O(nlogn)
稳定性:不稳定
- package com.xch2.DiGui;
-
- import java.util.*;
-
- public class Main2 {
-
- //希尔排序(缩小增量排序,优化插入排序)
- static void f2(int arr[]) {
- for (int incre = arr.length/2; incre > 0; incre=incre/2) {
- for (int i = incre; i < arr.length; i++) {
- int target=i;
- while(target>=incre&&arr[target]
- int mid=arr[target];
- arr[target]=arr[target-incre];
- arr[target-incre]=mid;
- target-=incre;
- }
- }
- }
- }
-
- public static void main(String[] args) {
- // TODO 自动生成的方法存根=
- int arr1[]=new int[] {9,8,7,6,5,4,3,6,2,1,99,0,-4};
- f2(arr1);
- for (int i : arr1) {
- System.out.print(i+",");
- }
- System.out.println();
-
- }
-
- }
5、归并排序
思想:分治思想,把待排数组渐进分割,进行有序合并,直到整体有序(偏合并)
时间复杂度:O(nlogn)
稳定性:稳定
- package com.xch2.DiGui;
-
- public class Main5 {
-
- //归并排序
- static int[] arr1;
- static void f1(int[] arr,int l,int r) {
- arr1=new int[arr.length];//外移到递归函数外,不会多次new节省存储空间
- f2(arr,l,r);
- }
- static void f2(int[]arr,int l,int r) {
- if(l>=r)//递归出口
- return;
-
- int mid=l+((r-l)>>1),left=l,right=mid+1,ori=l;
- f2(arr,l,mid);//子递归
- f2(arr,mid+1,r);
-
- for (int i = 0; i < arr1.length; i++) {
- arr1[i]=arr[i];//更新辅助数组
- }
- while(left<=mid&&right<=r) {//递归体
- if(arr1[left]<=arr1[right]) {
- arr[ori]=arr1[left];
- left++;
- }else {
- arr[ori]=arr1[right];
- right++;
- }
- ori++;
- }
- while(left<=mid) {
- arr[ori]=arr1[left];
- left++;
- ori++;
- }
- }
-
- public static void main(String[] args) {
- // TODO 自动生成的方法存根
- int[] arr=new int[] {11,8,3,4,9,8,22,0,5,8,3};
- f1(arr,0,10);
- for (int i : arr) {
- System.out.print(i+" ");
- }
- System.out.println();
-
- }
-
- }
6、快速排序
思想:分治思想,先定主元把数组分为两(三)段[小于(等于)大于],后调整主元位置,递归渐进分割比较,直到整体有序(偏拆分)
时间复杂度:O(nlogn)
稳定性:不稳定
其中,实现方法分为三种:
1、双指针-单向扫描快速排序
2、双指针-双向扫描快速排序
3、三指针-双向扫描快速排序(相等元素优化)
定主元的两种方法:
1、取第一个
2、三点中值法(推荐,取本段数组头中尾三个元素比较值)
- package com.xch2.DiGui;
-
- public class Main4 {
-
- //单向单指针扫描分区快排法
- static void f1(int[] arr,int l,int r) {
- if(l>=r)//递归出口
- return;
-
- int left=l+1,right=r,mid=0;
- while(left<=right) {//递归体
- if(arr[left]<=arr[l])
- left++;
- else {
- mid=arr[left];
- arr[left]=arr[right];
- arr[right]=mid;
- right--;
- }
- }
- mid=arr[right];
- arr[right]=arr[l];
- arr[l]=mid;
-
- f1(arr,l,right-1);//子递归
- f1(arr,right+1,r);
- }
-
- //双向双指针扫描分区快排法
- static void f2(int[] arr,int l,int r) {
- if(l>=r)//递归出口
- return;
-
- int left=l+1,right=r,mid=0;
- while(left<=right) {//递归体
- while(left<=right&&arr[left]<=arr[l])
- left++;
- while(left<=right&&arr[right]>arr[l])
- right--;
- if(left
- mid=arr[right];
- arr[right]=arr[left];
- arr[left]=mid;
- }
- }
- mid=arr[right];
- arr[right]=arr[l];
- arr[l]=mid;
-
- f2(arr,l,right-1);//子递归
- f2(arr,right+1,r);
- }
-
- //双向和等于三指针扫描分区快排法
- static void f3(int[] arr,int l,int r) {
- if(l>=r)//递归出口
- return;
-
- int equ=l,left=l+1,right=r,mid=0;
- while(left<=right) {//递归体
- while(left<=right&&arr[left]<=arr[l]) {
- if(arr[left]==arr[l]&&equ==l)
- equ=left;
- if(arr[left]
- mid=arr[left];
- arr[left]=arr[equ];
- arr[equ]=mid;
- equ++;
- }
- left++;
- }
- while(left<=right&&arr[right]>arr[l])
- right--;
- if(left
- mid=arr[right];
- arr[right]=arr[left];
- arr[left]=mid;
- }
- }
- if(equ!=l) {
- equ--;
- mid=arr[equ];
- arr[equ]=arr[l];
- arr[l]=mid;
-
- f3(arr,l,equ-1);//子递归
- f3(arr,right+1,r);
- }else {
- mid=arr[right];
- arr[right]=arr[l];
- arr[l]=mid;
-
- f3(arr,l,right-1);//子递归
- f3(arr,right+1,r);
- }
- }
-
- //以上方法均为去第一个随机数为比较主元
- //一般用三点取中值法取比较主元,如f4单指针,其他一样(取中值后和第一个数值换成为主元)
-
- //单向单指针扫描分区快排法(三点取中值为主元法)
- static void f4(int[] arr,int l,int r) {
- if(l>=r)//递归出口
- return;
-
- int left=l+1,right=r,mid=0;
-
- int midsub=l+((r-l)>>1);//三点取中值
- if(arr[l]>=arr[midsub]&&arr[midsub]>=arr[r]||
- arr[l]<=arr[midsub]&&arr[midsub]<=arr[r]) {
- mid=arr[midsub];
- arr[midsub]=arr[l];//换主元
- arr[l]=mid;
- }else if(arr[midsub]>=arr[r]&&arr[r]>=arr[l]||
- arr[midsub]<=arr[r]&&arr[r]<=arr[l]){
- mid=arr[r];
- arr[r]=arr[l];
- arr[l]=mid;
- }
-
- while(left<=right) {//递归体
- if(arr[left]<=arr[l])
- left++;
- else {
- mid=arr[left];
- arr[left]=arr[right];
- arr[right]=mid;
- right--;
- }
- }
- mid=arr[right];
- arr[right]=arr[l];
- arr[l]=mid;
-
- f4(arr,l,right-1);//子递归
- f4(arr,right+1,r);
- }
-
- public static void main(String[] args) {
- // TODO 自动生成的方法存根
- int[] arr=new int[] {0,1,9,5,4,1};
- // f1(arr,0,5);
- // f2(arr,0,5);
- // f3(arr,0,5);
- f4(arr,0,5);
- for (int i : arr) {
- System.out.print(i+" ");
- }
- System.out.println();
-
- }
-
- }
7、堆排序
思想:利用二叉树的特性,每次把最大或最小的元素比较到根节点维持一个大或小顶堆,取出根节点放到最后,直到整体有序
时间复杂度:O(nlogn)
稳定性:不稳定
分为两种:
1、小顶堆-逆向排序
2、大顶堆-顺向排序
- package com.xch2.DiGui;
-
- import java.util.*;
-
- public class Main7 {
-
- //堆排序(小顶堆=逆序,大顶堆=顺序)
- //建小顶堆
- static void f1(int[] arr,int index,int leng) {//index初始为数组二分值减一
- if(index<0) //leng 初始为数组长度
- return;
-
- int left=2*index+1,right=2*index+2,mid;
- if(left==leng-1) {//最后一个父节点为单亲节点
- if(arr[left]
- mid=arr[left];
- arr[left]=arr[index];
- arr[index]=mid;
- }
- }else {
- if(arr[left]<=arr[right]&&arr[left]
- mid=arr[left];
- arr[left]=arr[index];
- arr[index]=mid;
- }else if(arr[right]<=arr[left]&&arr[right]
- mid=arr[right];
- arr[right]=arr[index];
- arr[index]=mid;
- }
- }
-
- f1(arr,index-1,leng);
- }
-
- //小顶堆转逆序数组
- static void f2(int arr[],int leng) {
- if(leng==1)
- return;
-
- f1(arr,leng/2-1,leng);
- int mid=arr[leng-1];
- arr[leng-1]=arr[0];
- arr[0]=mid;
- leng--;
-
- f2(arr,leng);
- }
-
- //建大顶堆
- static void f3(int[] arr,int index,int leng) {//index初始为数组二分值减一
- if(index<0) //leng 初始为数组长度
- return;
-
- int left=2*index+1,right=2*index+2,mid;
- if(left==leng-1) {//最后一个父节点为单亲节点
- if(arr[left]>arr[index]) {
- mid=arr[left];
- arr[left]=arr[index];
- arr[index]=mid;
- }
- }else {
- if(arr[left]>=arr[right]&&arr[left]>arr[index]) {
- mid=arr[left];
- arr[left]=arr[index];
- arr[index]=mid;
- }else if(arr[right]>=arr[left]&&arr[right]>arr[index]) {
- mid=arr[right];
- arr[right]=arr[index];
- arr[index]=mid;
- }
- }
-
- f3(arr,index-1,leng);
- }
-
- //大顶堆转顺序数组
- static void f4(int arr[],int leng) {
- if(leng==1)
- return;
-
- f3(arr,leng/2-1,leng);
- int mid=arr[leng-1];
- arr[leng-1]=arr[0];
- arr[0]=mid;
- leng--;
-
- f4(arr,leng);
- }
-
- public static void main(String[] args) {
- // TODO 自动生成的方法存根
- int arr[]= {5,2,8,9,2,6,7,10};
- // f1(arr,arr.length/2-1,8);
- f2(arr,8);
- // f3(arr,arr.length/2-1,8);
- // f4(arr,8);
- for (int i : arr) {
- System.out.print(i+" ");
- }
- System.out.println();
-
- }
-
- }
8、计数排序
思想:利用数组的特性,把元素值记录到新的辅助数组对应下标中,后顺序恢复即可(适用于元素较为集中的排序,如年龄、分数等)
时间复杂度:O(n)
稳定性:稳定
- package com.xch2.DiGui;
-
- import java.util.*;
-
- public class Main7 {
-
- //计数顺序排序(包含负数)
- static void f5(int[] arr) {
- int cur=0,max=0,min=0;
- for (int i : arr) {
- if(i>max)
- max=i;
- else if(i<-min)
- min=-i;
- }
- int[] helper=new int[max+1];
- int[] helper1=new int[min+1];
- for (int i : arr) {
- if(i>=0)
- helper[i]++;
- else
- helper1[-i]++;
- }
- for (int i = helper1.length-1; i > 0; i--) {
- while(helper1[i]>0) {
- arr[cur]=-i;
- helper1[i]--;
- cur++;
- }
- }
- for (int i = 0; i < helper.length; i++) {
- while(helper[i]>0) {
- arr[cur]=i;
- helper[i]--;
- cur++;
- }
- }
- }
-
- //方法二
- static void f5_1(int[] arr){
- int max=0,min=0,cur=0;
- for (int i : arr) {
- if(i>max)
- max=i;
- else if(i
- min=i;
- }
- for (int i = 0; i < arr.length; i++) {
- arr[i]-=min;//把所有负数转正数
- }
- int[] helper=new int[max-min+1];
- for (int i : arr) {
- helper[i]++;
- }
- for (int i = 0; i < helper.length; i++) {
- while(helper[i]!=0) {
- arr[cur]=i+min;//恢复原数组输出
- helper[i]--;
- cur++;
- }
- }
- }
-
- public static void main(String[] args) {
- // TODO 自动生成的方法存根
- // int arr1[]= {-3,2,4,-3,66,4,66,9,0,-90,2};
- // // f5(arr1);
- // f5_1(arr1);
- // System.out.println(Arrays.toString(arr1));
-
- }
-
- }
9、桶排序
思想:利用链表的特性,通过公式把数组分为多个数段的子链表(桶,元素进入链表时是有序插入),再顺序取出即可(计数排序的进阶版:浪费率相比更低、适用数据分布相比更广)
时间复杂度:O(n)
稳定性:稳定
- package com.xch2.DiGui;
-
- import java.util.*;
-
- public class Main7 {
-
- //桶排序(包含负数)
- static void f6(int[] arr) {
- int max=arr[0],min=arr[0],cur=0;
- for (int i : arr) {
- if(i>max)
- max=i;
- else if(i
- min=i;
- }
- List
> bucketlist=new ArrayList<>(); - for (int i=0;i
- bucketlist.add(new LinkedList
());//初始化桶 - }
- for (int i : arr) {
- int num=(i-min)*arr.length/(max-min+1);//最优公式,元素放置桶
- bucketlist.get(num).add(i);
- }
- for (LinkedList
linkedlist:bucketlist) { - Collections.sort(linkedlist);//归并排序桶中的集合
- }
- for (LinkedList
linkedlist:bucketlist) { - for (Integer integer : linkedlist) {
- arr[cur]=integer;//遍历输出
- cur++;
- }
- }
- }
-
- public static void main(String[] args) {
- // TODO 自动生成的方法存根
- // int arr1[]= {-3,2,4,-3,66,4,66,9,0,-90,2};
- // // f6(arr1);
- // System.out.println(Arrays.toString(arr1));
-
- }
-
- }
10、基数排序
思想:利用链表的特性,通过数字的位数(个-十-百…)渐进顺序分配到链表中,再顺序收集即可,直到最高位即整体有序(桶排序的进阶版)
时间复杂度:O(n)
稳定性:稳定
- package com.xch2.DiGui;
-
- import java.util.*;
-
- public class Main7 {
-
- //基数排序(包含负数)
- static void f7(int[] arr) {
- List
[] bucketarr=new List[10]; - for (int i = 0; i < bucketarr.length; i++) {
- bucketarr[i]=new LinkedList
();//初始化数组中的集合 - }
- int maxd=0,min=arr[0];
- for (int i:arr) {
- int len=(i+"").length();
- if(len>maxd)
- maxd=len;//找最大位数
- if(i
- min=i;//找最小值
- }
- if(min<0) {
- for (int i = 0; i < arr.length; i++) {
- arr[i]=arr[i]-min;//负数移位转正数
- }
- }
- int der=1,cur=0;
- for (int i = 1; i <= maxd; i++) {
- for (int j = 0; j < arr.length; j++) {
- int x=(arr[j]/der)%10;
- bucketarr[x].add(arr[j]);//入桶
- }
- for (int j = 0; j < bucketarr.length; j++) {
- for (Integer value : bucketarr[j]) {
- arr[cur]=value;//出桶
- cur++;
- }
- bucketarr[j].clear();
- }
- der*=10;
- cur=0;
- }
- if(min<0) {
- for (int i = 0; i < arr.length; i++) {
- arr[i]=arr[i]+min;//负数移位复原
- }
- }
- }
-
- public static void main(String[] args) {
- // TODO 自动生成的方法存根
- // int arr1[]= {-3,2,4,-3,66,4,66,9,0,-90,2};
- // // f7(arr1);
- // System.out.println(Arrays.toString(arr1));
-
- }
-
- }
十大排序算法的时间复杂度:

时间复杂度效率对比:

-
相关阅读:
linux下基于boost/process库实现多进程管理,基于c++开发
温敏传感器概述
实例分割Yolact边缘端部署 (三) 从onnx到caffemodel
VM虚拟机安装ikuai软路由系统
不解压的情况下从各种压缩包中直接读取文本行内容
23、JAVA进阶——日期操作类
DETR纯代码分享(五)__init__.py(datasets)
数据统计和分析怎么做?spss如何做好数据分析?
2022年(第二届)信息技术服务业应用技能大赛网络与信息安全管理赛项的通知
二维数组与稀疏数组转换(java)
-
原文地址:https://blog.csdn.net/weixin_51091560/article/details/126920866