排序演算法-JAVA程式碼
阿新 • • 發佈:2018-12-11
1、插入排序:
import java.util.Arrays; public class InsertionSort { public static void insertionSort(int[] input ,int n) { int i , j , temp; //temp記錄每次插入的值 //預設已經插入一個值。 for(i = 1 ; i <= n - 1 ; i++) { temp = input[i]; for(j = i ; j > 0 && input[j - 1] > temp ; j--) { input[j] = input[j - 1]; //每次比較後向後移一位 } input[j] = temp; //將要插入的值插入到屬於它的位置 } } public static void main(String[] args) { int input[] = {10,15,14,18,20,36,40}; insertionSort(input, 7); System.out.println(Arrays.toString(input)); } }
2、希爾排序
import java.util.Arrays; public class ShellSort { /** * 希爾排序法(縮小增量法) 屬於插入類排序,是將整個無序列分割成若干小的子序列分別進行插入排序的方法。 * 基本思想:演算法先將要排序的一組數按某個增量d(n/2,n為要排序數的個數)分成若干組,每組中記錄的下標相差d. * 對每組中全部元素進行直接插入排序,然後再用一個較小的增量(d/2)對它進行分組,在每組中再進行直接插入排序。當增量減到1時,進行直接插入排序後,排序完成。 * @param input * @param n */ public static void shellSort(int[] input , int n) { int i , j , temp; //插入法使用的臨時變數 //縮小增量,初始增量為n/2,按照增量的1/2縮小 for(int incre = n/2 ; incre >= 1 ; incre = incre / 2) { //從下表incre開始,進行插入操作,初始插入座標指向第一個插入的位置 for(i = incre ; i < n ; i++) { temp = input[i]; //插入元素的值 for(j = i ; j >= incre && input[j - incre] > temp ; j = j - incre) { input[j] = input[j - incre]; } input[j] = temp; } } } public static void main(String[] args) { int input[] = {10,15,14,18,20,36,40}; shellSort(input, 7); System.out.println(Arrays.toString(input)); } }
3、氣泡排序
import java.util.Arrays; public class BubbleSort { //氣泡排序,顧名思義,從下往上遍歷,每次遍歷往上固定一個最小值 public static void bubbleSort(int[] input , int n) { for(int i = 0 ; i < n-1 ; i++) { for(int j = n - 1 ; j >= i + 1 ; j--) { if(input[j - 1] > input[j]) { int temp = input[j - 1]; input[j - 1] = input[j]; input[j] = temp; } } } } //加一個標誌位,當某一趟氣泡排序沒有元素交換時,則冒泡結束,元素已經有序,可以有效的減少冒泡次數。 public static void optimizedBubbleSort(int[] input , int n) { boolean flag = true; for(int i = 0 ; i < n-1 && flag ; i++) { flag = false; for(int j = n - 1 ; j >= i + 1 ; j--) { if(input[j - 1] > input[j]) { int temp = input[j - 1]; input[j - 1] = input[j]; input[j] = temp; flag = true; } } } } // 如果0-i已是有序區間,上次的掃描區間是i-n,記上次掃描時最後一次交換的位置lastswappose, // 則lastswappose在i-n之間,不難發現i-lastswappose區間已是有序的, // 否則這個區間也會發生交換;所以下次掃描區間可以由i-n縮減到lastswappose-n。 public static void LastSwapPoseBubbleSort(int[] input , int n) { int lastSwapPose = 0 , lastSwapPoseTemp = 0; for(int i = 0 ; i < n-1 ; i++) { lastSwapPose = lastSwapPoseTemp; for(int j = n - 1 ; j > lastSwapPose ; j--) { if(input[j - 1] > input[j]) { int temp = input[j - 1]; input[j - 1] = input[j]; input[j] = temp; lastSwapPoseTemp = j; } } if(lastSwapPose == lastSwapPoseTemp) { break; } } } public static void main(String[] args) { int input[] = {10,15,14,18,20,36,40}; // bubbleSort(input, 7); optimizedBubbleSort(input, 7); System.out.println(Arrays.toString(input)); } }
4、快速排序
import java.util.Arrays;
/**
* 對於給定的一組記錄,選擇一個基準元素,通常選擇第一個元素或者最後一個元素,
* 通過一趟掃描,將待排序列分成兩部分,一部分比基準元素小,一部分大於等於基準元素,
* 此時基準元素在其排好序後的正確位置,然後再用同樣的方法遞迴地排序劃分的兩部分,直到序列中的所有記錄均有序為止。
* 演算法優化:
* (1)在遞迴到規模比較小時,使用選擇排序/插入排序代替。
* (2)選取一個比較靠譜的pivot。(取first,取last,取middle,取三者的中)
* (3)使用迴圈代替遞迴。
* @author 李頂聖
*
*/
public class Quicksort {
/*
* 排序的核心演算法
*
* @param input 待排序陣列
*
* @param startIndex 開始位置
*
* @param endIndex 結束位置
*/
private static void sortCore(int[] input, int startIndex, int endIndex) {
if (startIndex >= endIndex) {
return;
} else {
int boundary = getBoundary(input, startIndex, endIndex);
sortCore(input, startIndex, boundary - 1);
sortCore(input, boundary + 1, endIndex);
}
}
/*
* 交換並返回分界點
*
* @param input 待排序陣列
*
* @param startIndex 開始位置
*
* @param endIndex 結束位置
*
* @return 分界點
*/
private static int getBoundary(int[] input, int startIndex, int endIndex) {
int standard = input[startIndex]; // 定義標準
int leftIndex = startIndex; // 左指標
int rightIndex = endIndex; // 右指標
while (leftIndex < rightIndex) {
while (leftIndex < rightIndex && input[rightIndex] >= standard) {
rightIndex--;
}
input[leftIndex] = input[rightIndex];
while (leftIndex < rightIndex && input[leftIndex] <= standard) {
leftIndex++;
}
input[rightIndex] = input[leftIndex];
}
input[leftIndex] = standard;
return leftIndex;
}
public static void main(String[] args)
{
int input[] = {20,15,14,18,21,36,40,10};
sortCore(input, 0, 7);
System.out.println(Arrays.toString(input));
}
}
5、選擇排序
import java.util.Arrays;
public class SelectionSort {
/**
* 選擇排序,就是每次選出待排序部分最小值,與其應該放的位置上的元素進行替換,比較的次數多,但是替換的次數會降低。
* @param input
* @param n
*/
private static void selectionSort(int[] input , int n)
{
int min = 0;
for(int i = 0 ; i < n - 1 ; i++)
{
min = i ;
for(int j = i + 1 ; j <= n - 1 ; j++)
{
if(input[min] > input[j])
{
min = j;
}
}
int temp = input[i];
input[i] = input[min];
input[min] = temp;
}
}
public static void main(String[] args)
{
int input[] = {10,15,14,18,20,36,40};
// bubbleSort(input, 7);
selectionSort(input, 7);
System.out.println(Arrays.toString(input));
}
}
6、堆排序
public class HeapSort {
// 構建大根堆:將array看成完全二叉樹的順序儲存結構
private int[] buildMaxHeap(int[] array) {
// 從最後一個節點array.length-1的父節點(array.length-1-1)/2開始,直到根節點0,反覆調整堆
for (int i = (array.length - 2) / 2; i >= 0; i--) {
adjustDownToUp(array, i, array.length);
}
return array;
}
// 將元素array[k]自下往上逐步調整樹形結構
private void adjustDownToUp(int[] array, int k, int length) {
int temp = array[k];
for (int i = 2 * k + 1; i <= length - 1; i = 2 * i + 1) { // i為初始化為節點k的左孩子,沿節點較大的子節點向下調整
if (i < length - 1 && array[i] < array[i + 1]) { // 取節點較大的子節點的下標
i++; // 如果節點的右孩子>左孩子,則取右孩子節點的下標
}
if (temp >= array[i]) { // 根節點>=左右子女中關鍵字較大者,調整結束
break;
} else { // 根節點<左右子女中關鍵字較大者
array[k] = array[i]; // 將左右子結點中較大者array[i]調整到雙親節點上
k = i; // 【關鍵】修改k值,以便繼續向下調整
}
}
array[k] = temp; // 被調整的結點的值放人最終位置
}
// 堆排序
public int[] heapSort(int[] array) {
array = buildMaxHeap(array); // 初始建堆,array[0]為第一趟值最大的元素
for (int i = array.length - 1; i >= 1; i--) {
int temp = array[0]; // 將堆頂元素和堆低元素交換,即得到當前最大元素正確的排序位置
array[0] = array[i];
array[i] = temp;
adjustDownToUp(array, 0, i); // 整理,將剩餘的元素整理成堆,注意i的含意
}
return array;
}
public void toString(int[] array) {
for (int i : array) {
System.out.print(i + " ");
}
}
public static void main(String args[]) {
HeapSort hs = new HeapSort();
int[] array = {4,5,1,6,2,7,3,8};
System.out.print("構建大根堆:");
hs.toString(hs.buildMaxHeap(array));
System.out.print("\n" + "大根堆排序:");
hs.toString(hs.heapSort(array));
}
}
7、歸併排序
import java.util.Arrays;
public class MergeSort {
/**
* 歸併排序,遞迴做法,分而治之
* 先使每個子序列有序,再將兩個已經排序的序列合併成一個序列的操作。若將兩個有序表合併成一個有序表,稱為二路歸併。
* @param input
* @param left
*/
public static void mergeSort(int[] input , int left , int right)
{
int mid = (right + left) / 2;
if(left < right)
{
//左邊
mergeSort(input, left, mid);
//右邊
mergeSort(input, mid + 1, right);
//左右歸併
merge(input, left, mid, right);
}
}
//將左右倆組的按序子序列排列成按序序列
public static void merge(int[] input , int left , int mid , int right)
{
int[] temp = new int[right - left + 1];//對兩個有序序列合併後儲存的臨時陣列
int i = left; //左指標
int j = mid + 1; //右指標
int k = 0;
// 把較小的數先移到新陣列中
while(i <= mid && j <= right)
{
if(input[i] < input[j])
{
temp[k++] = input[i++];
}else {
temp[k++] = input[j++];
}
}
// 把左邊剩餘的數移入陣列
while(i <= mid)
{
temp[k++] = input[i++];
}
// 把右邊邊剩餘的數移入陣列
while(j <= right)
{
temp[k++] = input[j++];
}
// 把新陣列中的數覆蓋原陣列
for(int m = 0 ; m < temp.length ; m++)
{
input[m + left] = temp[m];
}
}
public static void main(String[] args)
{
int input[] = { 51, 46, 20, 18, 65, 97, 82, 30, 77, 50 };
mergeSort(input, 0, input.length - 1);
System.out.println("排序結果:" + Arrays.toString(input));
}
}
8、桶排序
import java.util.ArrayList;
import java.util.Collections;
/**
* 適用範圍:
* 桶排序可用於最大最小值相差較大的資料情況,比如[9012,19702,39867,68957,83556,102456]。
* 但桶排序要求資料的分佈必須均勻,否則可能導致資料都集中到一個桶中。比如[104,150,123,132,20000], 這種資料會導致前4個數都集中到同一個桶中。導致桶排序失效。
* 過程:
* 桶排序的基本思想是:把陣列 arr 劃分為n個大小相同子區間(桶),每個子區間各自排序,最後合併。
* 計數排序是桶排序的一種特殊情況,可以把計數排序當成每個桶裡只有一個元素的情況。
* 1.找出待排序陣列中的最大值max、最小值min
* 2.我們使用 動態陣列ArrayList 作為桶,桶裡放的元素也用 ArrayList 儲存。桶的數量為(max-min)/arr.length+1
* 3.遍歷陣列 arr,計算每個元素 arr[i] 放的桶
* 4.每個桶各自排序
* 5.遍歷桶陣列,把排序好的元素放進輸出陣列
* @author 李頂聖
*
*/
public class BucketSort {
public static void bucketSort(int[] arr){
int max = Integer.MIN_VALUE;
int min = Integer.MAX_VALUE;
for(int i = 0; i < arr.length; i++){
max = Math.max(max, arr[i]);
min = Math.min(min, arr[i]);
}
//桶數
int bucketNum = (max - min) / arr.length + 1;
ArrayList<ArrayList<Integer>> bucketArr = new ArrayList<>(bucketNum);
for(int i = 0; i < bucketNum; i++){
bucketArr.add(new ArrayList<Integer>());
}
//將每個元素放入桶
for(int i = 0; i < arr.length; i++){
int num = (arr[i] - min) / (arr.length);
bucketArr.get(num).add(arr[i]);
}
//對每個桶進行排序
for(int i = 0; i < bucketArr.size(); i++){
Collections.sort(bucketArr.get(i));
}
System.out.println(bucketArr.toString());
}
}
9、全排序(不屬於十大排序演算法,在這做個筆記)
//全排列問題,首先列出所有情況,在進行排序;
public class FullSort {
public static void main(String[] args) {
fullSortList();
}
public static void fullSortList(){
String A[] = new String[]{"a","b","c","d"};
List<String> list = new ArrayList<>();
Queue<String> queue = new LinkedList<>();
queue.offer("a");
queue.offer("b");
queue.offer("c");
queue.offer("d");
//列出所有情況,按照長度1,2,3...一直列舉;
for(int i = 0 ; i < 4 ; i++)
{
int n = queue.size();
while(n >= 1 && queue.peek() != null)
{
String temp = queue.poll();
for(int j = 0 ; j < 4 ; j++)
{
String temp1 = A[j];
if(!temp.contains(temp1))
{
queue.offer(temp + temp1);
}
}
list.add(temp);
}
}
Collections.sort(list);
for(int i = 0 ; i < list.size() ; i++)
{
System.out.println(list.get(i));
}
}
}