1. 程式人生 > >排序演算法-JAVA程式碼

排序演算法-JAVA程式碼

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


}