Java常用排序演算法
阿新 • • 發佈:2022-03-06
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 + " ");
}
}