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 + " ");
}

}

posted @   nofight  阅读(46)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律
点击右上角即可分享
微信分享提示