Java常用排序算法
1、冒泡排序
public class BubbleSort {
public static void main(String[] args) {
// TODO Auto-generated method stub
//冒泡排序
int[] arr = {2,0,-4,9,54,28,8,13,0};
for (int end = arr.length-1; end > 0; end--) {
for (int i = 0; i < end; i++) {
if (arr[i] > arr[i+1]) {
swap(arr, i, i+1);
}
}
}
printOut(arr);
}
//交换
public static void swap(int[] arr,int i,int j) {
arr[i] = arr[i] ^ arr[j];
arr[j] = arr[i] ^ arr[j];
arr[i] = arr[i] ^ arr[j];
}
static void printOut(int[] arr) {
for( int cur : arr)
System.out.print(cur + " ");
}
}
2、插入排序
public class InsertSort {
public static void main(String[] args) {
// TODO Auto-generated method stub
//插入排序
int[] arr = {2,0,-4,9,54,28,8,13,0};
for(int i = 0;i<arr.length;i++) {
for(int j = i-1;j >=0 && arr[j] > arr[j+1];j--) {//将arr[i]交换到正确位置
swap(arr,j,j+1);
}
}
printOut(arr);
}
//交换
public static void swap(int[] arr,int i,int j) {
arr[i] = arr[i] ^ arr[j];
arr[j] = arr[i] ^ arr[j];
arr[i] = arr[i] ^ arr[j];
}
static void printOut(int[] arr) {
for( int cur : arr)
System.out.print(cur + " ");
}
}
3、选择排序
public class SelectSort {
public static void main(String[] args) {
// TODO Auto-generated method stub
//选择排序
int[] arr = {2,0,-4,9,54,28,8,13,0};
for(int i = 0;i < arr.length-1;i++) {
int minIndex = i;
for(int j = i+1;j<arr.length;j++) {
minIndex = arr[j] < arr[minIndex] ? j:minIndex;//在后面无序的里面选择最小的一个的下标
}
swap(arr,i,minIndex);
}
printOut(arr);
}
//交换
public static void swap(int[] arr,int i,int j) {
arr[i] = arr[i] ^ arr[j];
arr[j] = arr[i] ^ arr[j];
arr[i] = arr[i] ^ arr[j];
}
static void printOut(int[] arr) {
for( int cur : arr)
System.out.print(cur + " ");
}
}
4、快排
3.0版本,随机选择一个划分值。
public class QuickSort {
public static void main(String[] args) {
// TODO Auto-generated method stub
//快排
int[] arr = {2,0,-4,9,54,28,8,13,0};
quickSort(arr,0,arr.length - 1);
printOut(arr);
}
public static void quickSort(int[] arr,int L,int R) {
if(L < R) {
swap(arr,L + (int)(Math.random()*(R - L +1)),R);//随机选择一个位置,把它和最后位置数做交换
int[] p = partition(arr,L,R);//p的长度为2,表示等于划分值的左边界和右边界,也可说是<区的后面一位数,>区的前面一位数
quickSort(arr,L,p[0] - 1);//< 区,所以p[0] - 1是<区域的右边界
quickSort(arr,p[1] +1,R);//>区
}
}
public static int[] partition(int[] arr,int L,int R) {
int less = L -1;// <区边界
int more = R;// >区边界,arr[R]是划分值
while(L < more) {//L表示当前数的位置
if(arr[L] < arr[R]) {//当前值 < 划分值
swap(arr,++less,L++);
}else if(arr[L] > arr[R]) {
swap(arr,--more,L);
}else {
L++;
}
}
swap(arr,more,R);//把arr[R]划分值插入到 >区的最左边
return new int[] {less + 1,more};
}
public static void swap(int[] arr,int i,int j) {
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
static void printOut(int[] arr) {
for( int cur : arr)
System.out.print(cur + " ");
}
}
5、归并排序
public class MergeSort {
public static void main(String[] args) {
// TODO Auto-generated method stub
//归并排序
//思路:1、将一个数组一分为二,将两部分分别排好序
//2、用两个指针,一个指向前面有序的第一个位置,一个指向后面有序的第一个位置
//3、开辟一个辅助数组空间,将两个指针所在位置的数进行比较,把较小的数放入辅助空间数组,并将指针后移
//4、直到有指针越界,将另一个指针后面的数一切拷贝到辅助空间
int[] arr = {2,0,-4,9,54,28,8,13,0};
process(arr,0,arr.length - 1);
printOut(arr);
}
public static void process(int[] arr,int L,int R) {
if(L == R) return ;
int mid = L + ((R - L)>>1);
process(arr,L,mid);
process(arr,mid+1,R);
merge(arr,L,mid,R);
}
public static void merge(int[] arr,int L,int mid,int R) {
int[] help = new int[R -L +1];
int i =0;
int p1 = L;
int p2 = mid +1;
while(p1 <= mid && p2 <= R) {
help[i++] = arr[p1] <= arr[p2]?arr[p1++]:arr[p2++];
}
while(p1 <=mid) {
help[i++] = arr[p1++];
}
while(p2 <= R) {
help[i++] = arr[p2++];
}
for(int j =0;j<help.length;j++)
arr[L+j] = help[j];
}
static void printOut(int[] arr) {
for( int cur : arr)
System.out.print(cur + " ");
}
}
6、堆排
import java.util.PriorityQueue;
public class HeapSort {
public static void main(String[] args) {
// TODO Auto-generated method stub
//堆排序
int[] arr = {2,0,-4,9,54,28,8,13,0};
for(int i = 0;i < arr.length;i++) {//O(N)
heapInsert(arr,i);//O(logN),把节点插入树中并形成大根堆
}
printOut(arr);
int heapSize = arr.length;//帮助判断左右孩子是否越界
//问题:去除堆的最大节点,剩下的保持大根堆结构
swap(arr,0,--heapSize);
while(heapSize > 0) {
heapfy(arr,0,heapSize);//O(lonN)
swap(arr,0,--heapSize);
}
printOut(arr);
}
//当前节点是index,判断是否需要上移
public static void heapInsert(int[] arr,int index) {
while(arr[index] > arr[(index - 1) /2]) {//和父节点比较
swap(arr,index,(index - 1) / 2);//和父节点交换
index = (index - 1) / 2;
}
}
//把一个二叉树改成大根堆
public static void heapfy(int[] arr,int index,int heapSize) {
int left = index * 2 +1;//左孩子下标
while(left < heapSize) {//判断是否越界,是否还有左孩子
//两个孩子中谁最大,把下标给largest
//left +1是右孩子
int largest = (left +1) < heapSize && arr[left +1] > arr[left]?left +1:left;
//父节点和子节点最大的比较
largest = arr[largest] > arr[index] ? largest : index;
if(largest == index)//如果父节点就是最大的,不用交换
break;
swap(arr,largest,index);
index = largest;//当前值跳到左孩子或者右孩子上,继续和它的左右孩子比较
left = index * 2 +1;
}
}
public static void swap(int[] arr,int i,int j) {
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
static void printOut(int[] arr) {
for( int cur : arr)
System.out.print(cur + " ");
}
public static void LittleHeap() {//小根堆
PriorityQueue<Integer> heap = new PriorityQueue<>();
heap.add(8);
heap.add(4);
heap.add(0);
heap.add(-3);
while(!heap.isEmpty()) {
System.out.println(heap.poll());//弹出最小值O(logN)
}
}
}
7、基数排序
package com;
public class RadixSort {
public static void main(String[] args) {
// TODO Auto-generated method stub
//基数排序
int[] arr = {2,0,4,9,54,28,8,13};//不能有负数,否则会报错
radixSort(arr,0,arr.length - 1,maxbits(arr));
printOut(arr);
}
//求出数组中最长数据有几位
public static int maxbits(int[] arr) {
int max = Integer.MIN_VALUE;
for(int i =0;i < arr.length;i++) {
max = Math.max(max, arr[i]);//找到数组中的最大值
}
int res = 0;//最大值有几位
while(max != 0) {
res++;
max /= 10;
}
return res;
}
//在数组的L...R范围内排序
public static void radixSort(int[] arr,int L,int R,int digit) {//digit最大值的进制位
final int radix = 10;
int i = 0,j = 0;
//有多少个数准备多少个辅助空间,和排序个数等规模
int[] bucket = new int[R - L +1];
for(int d = 1;d <= digit;d++) {//有多少位就进几次桶
int[] count = new int[radix];//词频表
//count[i]表示当前位是0~i的数字有多少个
for(i = L;i <= R;i++) {
j = getDigit(arr[i],d);//获取arr[i]数据第d位是什么数
count[j]++;//词频表相应位置++
}
for(i = 1;i<radix;i++) {
count[i] = count[i] + count[i - 1];//count计算前缀和
}
for(i = R;i>=L;i--) {//从右往左
j = getDigit(arr[i],d);
bucket[count[j] - 1] = arr[i];
count[j]--;
}
for(i = L,j = 0;i <= R;i++,j++) {
arr[i] = bucket[j];
}
}
}
public static int getDigit(int x,int d) {
return ((x / ((int) Math.pow(10, d - 1))) % 10);
}
static void printOut(int[] arr) {
for( int cur : arr)
System.out.print(cur + " ");
}
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律