基礎排序算法總結

一:插入排序
二:選擇排序
三:交換排序
四:歸併排序
五:基數排序

插入排序:(直接插入排序,shell排序)
1:直接插入排序
     把左邊作爲已經排序好的數組,新加入的數組值和左邊的數組最右邊數值比較,直到不大於左邊的數時停止,循環完成。最優的時間複雜度爲O(n),最大時間複雜度爲O(n^2),平均時間複雜度爲O(n^2),是穩定的算法。

java實現代碼:
package com.hdw.sort;

public class InsertSort {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		int[] a = {9,2,7,6,4,8,1,3,5};
		insertSort(a);
		print(a);
	}

	private static void print(int[] a) {
		// TODO Auto-generated method stub
		for (int i : a) {
			System.out.print(i+",");
		}
	}

	private static void insertSort(int[] a) {
		// TODO Auto-generated method stub
		for(int i=1; i<a.length; i++){
			int temp;
			for(int j=i; j>=1; j--){
				if(a[j]<a[j-1]){
					temp = a[j];
					a[j] = a[j-1];
					a[j-1] = temp;
				}else{
					break;
				}
			}
		}
	}

}


2:shell排序
     是對於直接插入排序的優化,shell排序中d的選取很重要,不同的時代的人對於d的選取有不同的看法,有d=2*n-1、d=3*n+1、d=5n-1,但是不管怎麼選,d=1,必須要存在,這保證了排序的正確性,她的妙處在於把相鄰d的數排序好,改進了對於d=1的壓力,最優時間複雜度爲O(n),最壞時間複雜度爲O(n^2),平均時間複雜度爲O(n^1.3),這個1.3是科學家算出來的,爲不穩定算法。

java代碼實現
package com.hdw.sort;

public class ShellSort {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		int[] a = {9,2,7,6,4,8,1,3,5};
		print(a);
		shellSort(a);
		print(a);
	}

	private static void print(int[] a) {
		// TODO Auto-generated method stub
		for (int i : a) {
			System.out.print(i+",");
		}
		System.out.println();
	}

	private static void shellSort(int[] a) {
		// TODO Auto-generated method stub
		//第一層循環是對於d的選取
		for(int d=a.length/2; d>0; d/=2){
			//第二層循環是讓第d個數後的每一個數和前面相差d的數做插入排序
			for(int i=d; i<a.length; i++){
				int temp;
				//相差d的數做插入排序
				for(int j=i; j>=d; j-=d){
					if(a[j]<a[j-d]){
						temp = a[j];
						a[j] = a[j-d];
						a[j-d] = temp;
					}else{
						break;
					}
				}				
			}
			print(a);
		}


	}

}


選擇排序:(直接選擇排序,堆排序)
1:直接選擇排序
     把數組中最大(最小)的值,選出放在數組的開頭,後面有從2到n中選出最大(最小)數放到小標爲2的數中,最優,最壞,平均時間複雜度均爲O(n^2),不穩定算法

java代碼實現
package com.hdw.sort;

public class SelectSort {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		int[] a = {9,2,7,6,4,8,1,3,5};
		selectSort(a);
		print(a);
	}

	private static void print(int[] a) {
		// TODO Auto-generated method stub
		for (int i : a) {
			System.out.print(i+",");
		}
	}

	private static void selectSort(int[] a) {
		// TODO Auto-generated method stub
		for(int i=0; i<a.length-1; i++){
			int temp=a[i];
			int flag = i;
			for(int j=i+1; j<a.length; j++){
				if(a[j]<temp){
					temp = a[j];
					flag = j;
				}
			}
			a[flag] = a[i];
			a[i] = temp;
		}
	}

}


2:堆排序
     首先建立一個二叉樹,把數組想象成二叉樹,第一個步驟就是建立一個大頂推(小頂堆)的二叉樹,第二部就是把大頂推(小頂堆)放在數組最後面一位,接下來的數再建立大頂堆(小頂堆),循環結束,最優、最差、平均時間算法O(nlog2n),不穩定算法。

java代碼實現
package com.hdw.sort;

public class HeapSort {
	
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		int[] a = {9,2,7,6,4,8,1,3,5};
		heapSort(a);
		print(a);
	}

	private static void heapSort(int[] a) {
		// TODO Auto-generated method stub
		for(int i=a.length-1; i>0; i--){
			createMaxHeap(a,i);
			swap(a,0,i);
		}
		
		
	}

	private static void swap(int[] a, int i, int j) {
		// TODO Auto-generated method stub
		a[i] = a[i] + a[j];
		a[j] = a[i] - a[j];
		a[i] = a[i] - a[j];
	}

	private static void createMaxHeap(int[] a,int lastIndex) {
		// TODO Auto-generated method stub
		for(int i=(lastIndex-1)/2; i>=0; i--){
			int k = i;
			//對K下面的樹建立大頂推
			while(2*k+1<=lastIndex){
				//假使最大數的下標爲2*k+1
				 int maxIndex = 2*k+1;
				 //如果存在右子樹則比較,選擇較大數的下標,爲下面和父節點比較
				 if(maxIndex < lastIndex){
					 if(a[maxIndex] < a[maxIndex+1]){
						 maxIndex++;
					 }
				 }
				 //直接子節點和父節點比較,若需要交換則把k換爲最大子節點的下標,好向下遞推建立大頂推樹,否則直接退出while循環
				 if(a[k] < a[maxIndex]){
					 swap(a, k, maxIndex);
					 k = maxIndex;
				 }else{
					 break;
				 }
			}
		}
	}

	private static void print(int[] a) {
		// TODO Auto-generated method stub
		for (int i : a) {
			System.out.print(i+",");
		}
	}

}


交換排序:
1:冒泡排序
     相鄰兩個數進行比較把大的數放在右邊,循環後最大的數再數組的最右邊,對剩餘n-1個數使用同樣的方法,最優時間複雜度O(n),最差時間複雜度O(n^2),平均時間複雜度爲O(n^2),穩定算法。

java代碼實現
package com.hdw.sort;

public class BubbleSort {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		//int[] a = {9,2,7,6,4,8,1,3,5};
		int[] a = {1,2,3,4,5,6};
		print(a);
		bubbleSort(a);
		print(a);
	}

	private static void print(int[] a) {
		// TODO Auto-generated method stub
		for (int i : a) {
			System.out.print(i+",");
		}
		System.out.println();
	}

	private static void bubbleSort(int[] a) {
		// TODO Auto-generated method stub		
		for(int i=0; i<a.length-1; i++){
			boolean flag = false;
			for(int j=0; j<a.length-1-i; j++){				
				int temp=a[j];
				if(a[j]>a[j+1]){
					a[j] = a[j+1];
					a[j+1] = temp;
					flag = true;
				}
			}
			if(!flag){
				break;
			}
			print(a);
		}

	}

}


2:快速排序
     快速排序是對於冒泡排序的改進,把中間值作爲一個key,左邊放的是比key小的值,右邊是比key大的值,然後key左邊的數進行快排,右邊也進行快排,遞歸結束,最優時間複雜度爲O(nlog2n),最差時間複雜度爲O(n^2),平均時間複雜度爲O(nlog2n),不穩定算法

java代碼實現
package com.hdw.sort;

public class QuickSort {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		int[] a = {9,2,7,6,4,8,1,3,5};
		print(a);
		quickSort(a,0,a.length-1);
		print(a);
	}

	private static void print(int[] a) {
		// TODO Auto-generated method stub
		for (int i : a) {
			System.out.print(i+",");
		}
		System.out.println();
	}
	
	private static void quickSort(int[] a, int left,int right){
		//當可以進行快排時
		if(left < right){
			//把最左邊的值設爲key,把left的值賦給low,right的值賦給high
			int key = a[left];
			int low = left;
			int high = right;
			//當low<high時,循環把比key更大的放在它右邊,比key更小的值放在它的左邊
			while(low<high){
				//如果右邊的值大於key則一直向後對比
				while(low < high && a[high] >= key){
					high--;
				}
				//符合是把高位的值賦給低位的值
				a[low] = a[high];
				//如果左邊的值一直小於key則一直向前對比
				while(low < high && a[low] < key){
					low++;
				}
				//把地位的值賦值給高位
				a[high] = a[low];
			}
			//把key的值賦給指針停止的地方
			a[low] = key;
			quickSort(a,left,low-1);
			quickSort(a,low+1,right);				
		}
	}

}


歸併排序:
     把數組每兩個進行比較,比較完了以後作爲一個整體,在兩個整體之間的比較,循環下去,直到結束,我採用的是遞歸算法,真個數組分爲兩個部分,左邊歸併,右邊也歸併,最優、最差、平均時間負雜度爲O(nlog2n),需要輔助空間爲O(n),穩定算法

java代碼實現
package com.hdw.sort;

public class MergeSort {
	
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		int[] a = {9,2,7,6,4,8,1,3,5};
		int[] temp = new int[a.length];
		mergeSort(a,0,a.length-1,temp);
		print(a);
	}


	private static void mergeSort(int[] a, int first, int last, int[] temp) {
		// TODO Auto-generated method stub
		if(first < last){
			int mid = (first + last) / 2;
			mergeSort(a,first,mid,temp);
			mergeSort(a,mid+1,last,temp);
			mergeArray(a,first,mid,last,temp);
		}
	}


	private static void mergeArray(int[] a, int first, int mid, int last,
			int[] temp) {
		// TODO Auto-generated method stub
		int i = first;
		int j = mid + 1;
		int m = mid;
		int n = last;
		int k = 0;
		while(i <= m && j <= n){
			if(a[i] < a[j]){
				temp[k++] = a[i++];
			}else{
				temp[k++] = a[j++];
			}
		}
		while(i <= m){
			temp[k++] = a[i++];
		}
		while(j <= n){
			temp[k++] = a[j++];
		}
		for(i = 0; i < k; i++){
			a[first+i] = temp[i];
		}
		
	}


	private static void print(int[] a) {
		// TODO Auto-generated method stub
		for (int i : a) {
			System.out.print(i+",");
		}
	}

}


基數排序:
     d爲數組的最大位數,r爲可區分每個數的基數的位數,比如數組裏面的是整數則r=9,範圍0-9,英文字母則爲26,a-z,先把個位數排序,放在一個輔助的數組空間裏,在把輔助空間裏面值賦值給原數組,接着是百位數排序,重複,知道所有位數排序完,如果位數r比較大時,則從高位開始排序,最優時間複雜度爲O(d(r+n)),最差時間複雜度爲O(d(n+rd)),平均O(d(r+n)),需要輔助空間O(rd+n)

java代碼實現

package com.hdw.sort;

import java.util.Arrays;

public class RadixSort {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		int[] a = {1100, 192, 221, 12, 23};
		print(a);
		radixSort(a,10,4);
		print(a);
	}

	private static void print(int[] a) {
		// TODO Auto-generated method stub
		for (int i : a) {
			System.out.print(i+",");
		}
		System.out.println();
	}

	/******************************************************** 
	*函數名稱:radixSort 
	*參數說明:需要排序的數組  
	*          radix表示 基數的大小
	*          distance表示最高位數的大小
	*說明:    通過基數排序把數組排好
	*********************************************************/
	private static void radixSort(int[] a, int radix, int distance) {
		// TODO Auto-generated method stub
		//緩存數組
		int[] temp = new int[a.length];
		//存儲不同小標的個數
		int[] count = new int[radix];
		//設置每次求數組數除於的數
		int rate = 1;
		//把每一個位數的數比較		
		for(int i=0; i<distance; i++){
			//把數組a的值賦值給temp數組
			System.arraycopy(a, 0, temp, 0, a.length);
			//初始化數組count每個值爲0
			Arrays.fill(count, 0);
			
			//統計小標爲key的值的個數
			for(int j=0; j<a.length; j++){
				int key = (temp[j]/rate)%radix;
				count[key]++;
			}
			//對count的值進行相加,這裏j是小於radix,不是a.length
			for(int j=1; j<radix; j++){
				count[j] += count[j-1];
			}
			//進行數組的交換
			for(int m=a.length-1; m>=0; m--){
				int subkey = (temp[m]/rate)%radix;
				count[subkey]--;
				a[count[subkey]] = temp[m];				
			}
			//對下面一個位數排序
			rate*=radix;
			print(a);
		}
	}
		
		
		

}



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章