1. 程式人生 > 其它 >Java常用排序演算法

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

}