1. 程式人生 > >交換排序(氣泡排序~快速排序~)+插入排序(直接插入排序~希爾排序~)

交換排序(氣泡排序~快速排序~)+插入排序(直接插入排序~希爾排序~)

一、氣泡排序

1、基本概念

依次比較相鄰的兩個數,將小數放在前面,大數放在後面。

第一趟:首先比較第1個數和第2個數,將小數放前,大數放後;然後比較第2個數和第3個數,將小數放前,大數放後;如此繼續,直至比較最後兩個數,將小數放前,大數放後;至此第一趟結束,使得最後一個數字是最大的了!

第二趟:仍從第一對數開始比較,將小數放前,大數放後,一直比較到倒數第二個數字,(倒數第一的位置已經是最大的了),第二趟結束,在倒數第二個位置上得到了一個新的最大的數字(整個陣列當中第二大數字)!

如此過程,重複進行下去,直達最終完成排序。

2、實現思路

使用二重迴圈實現,外變數設為i,內部變數設為j。假如有n個數據要進行排序,則外迴圈重複n-1次,內部迴圈依次重複n-1,n-2,......1次,外部迴圈控制執行的趟數,內部迴圈控制比較的數字,每次比較的兩個數字都是與j有關,分別可以用a[j]和a[j+1]來識別,i的值依次為1,2,......,n-1,對於每一個i,j的值依次為1,2,......,n-i。

舞蹈之氣泡排序:http://v.youku.com/v_show/id_XMzMyOTAyMzQ0.html?from = s1.8-1-1.2

時間複雜度:最壞情況:O(n ^ 2)、最好情況:O(n)

空間複雜度:O(1)

程式碼演示:

     /*
	 * 氣泡排序
	 */
	public static<T> void Swap(T [] arr,int i,int j){
		T temp=arr[i];
		arr[i]=arr[j];
		arr[j]=temp;
	}
     public static<T extends Comparable<T>> void ButtleSort(T[] arr){
    	 int len=arr.length;
    	 for(int i=0;i<len;i++){
    		 for(int j=0;j<len-i-1;j++){
    			 if(arr[j].compareTo(arr[j+1])>0){
    				 Swap(arr,j,j+1);
    			 }
    		 }
    	 }
     }

二、快速排序(對氣泡排序的一種改進)

1、演算法思想

首先從陣列當中選擇出一個數字作為基準數字;分割槽過程,將比基準大的數字全部放在基準的右邊,比基準小的數字放在基準的左邊;再對左右區間重複第二步,直到各區間只有一個數字為止!

2、時間複雜度:O(n * logn)

      最壞:O(n ^ 2)

     空間複雜度:O(n * logn)

舞蹈之快速排序:http://v.youku.com/v_show/id_XMzMyODk4NTQ4.html?from = s1.8-1-1.2

程式碼演示:

     /*
	 * 快速排序
	 */
	public static<T extends Comparable<T>> int quickSort(T[] arr,int low,int high){
		T temp=arr[low];  //將陣列中的第一個數字作為基準
		while(low<high){
			while(low<high && arr[high].compareTo(temp)>=0){
				high--;
			}
			arr[low]=arr[high];  //找到比基準小的數字挪動到左邊
			while(low<high && arr[low].compareTo(temp)<0){
				low++;
			}
			arr[high]=arr[low]; //找到比基準大的數字挪動到右邊
		}
		arr[low]=temp;  //最後將基準放到空出來的位置
		return low;  //返回基準的最終位置
	}
	public static<T extends Comparable<T>> void quick(T[] arr,int low,int high){
		if(low < high){//將陣列一分為二,進行遞迴呼叫
		int pos=quickSort(arr,low,high);
			quick(arr,low,pos-1);
			quick(arr,pos+1,high);
		}
	}

三、直接插入排序

1、演算法思想

直接插入排序演算法的思想是將一個記錄插入到已經排好序的表中,從而得到一個新的、記錄數增1的有序表。對於給定的一組記錄,初始時假定第一個資料自成一個有序序列,其餘記錄為無序的序列。接著從第二個記錄開始,按照記錄的大小依次將當前處理的記錄插入到其之前的有序序列中,直到最後一個記錄插入到有序的序列中為止。

2、演算法步驟

首先從第一個元素開始,該元素被假定為有序的;取出下一個元素,在已經排好序的陣列中從前往後遍歷;如果該元素(已排序)大於新元素,則將該元素移到下一個位置;重複上一步,直到找到已排序的元素小於或者大於新元素的位置;將新元素插入到該位置;重複進行下去。

舞蹈之插入排序:http://v.youku.com/v_show/id_XMzMyODk3NjI4.html?from = s1.8-1-1.2

時間複雜度:最好的情況:O(n)、最壞的情況:O(n ^ 2)

空間複雜度:O(1)

程式碼演示:

/*
	 * 插入排序
	 */
	public static<T extends Comparable<T>> void insertSort(T[] arr){
		int i,j;
		T NoteNumber;//要插入的資料
		for(i=1;i<arr.length;i++){
			NoteNumber=arr[i];//迴圈將陣列中的資料作為要插入的新元素
			j=i-1;
			while(j>=0 && arr[j].compareTo(NoteNumber)>0){//插入的資料小於第j個元素,將資料進行向後挪動
				arr[j+1]=arr[j];
				j--;
			}
			arr[j+1]=NoteNumber;//直到插入的資料小於第j個元素,進行插入!
		}
	}

四、希爾排序

1、演算法思想

希爾排序是一種插入排序,又被稱為縮小增量排序。希爾排序的演算法思想就是:將資料進行分組,然後對每一組資料進行排序,在每一組資料有序後,就可以對所有的分組利用插入排序進行最後一次的排序,這樣可以達到減少交換的次數,達到加速的目的。

2、演算法演練

假定待排序的陣列有10條記錄,其分別為40、38、65、97、76、13、27、49、55、4。

步長取值分別為5,3,1

時間複雜度:最好的情況:O(n)  最壞的情況下:O(n ^ 2)

空間複雜度:O(1)

舞蹈之希爾排序:http://v.youku.com/v_show/id_XMzMyODk5MzI4.html?from = s1.8-1-1.2

排序過程如下:

程式碼演示:

/*
	 * 希爾排序
	 */
	public static<T extends Comparable<T>> void shellSort(T[] arr){
		T temp;
		int step=arr.length;
		while(true){
			step=step/2; //預設步長為陣列的長度除以2
			for(int i=0;i<step;i++){//確定分組數
				for(int j=i+step;j<arr.length;j=j+step){//對分組的資料進行直接插入排序
					temp=arr[j];
					int k=0;
					for(k=j-step;k>=0;k=k-step){
						if(arr[k].compareTo(temp)>0){
							arr[k+step]=arr[k];
						}else{
							break;
						}
					}
					arr[k+step]=temp;
				}
			}
			if(step==1){
				break;
			}
		}