瞭解一下Java經常使用排序算法

分享一下經常使用排序算法,給各位官人溫故而.....算法

經常使用排序算法共有6種:shell

交換算法:冒泡算法、快速排序算法;數組

選擇算法:選擇排序算法,堆排序算法;bash

插入算法:插入算法,shell排序算法。ui

交換算法

冒泡排序算法

冒泡排序算法:主要從頭(或從尾)依次比較相鄰兩個算法,通過一次多倫的比較交換,最小的值會優先排好。spa

static void bubbleSort(int[] data){
		int temp;
		
		for (int i = 1; i < data.length; i++) {
			for (int j = 0; j < data.length-i; j++) {
				if (data[j]>data[j+1]) {
					temp=data[j+1];
					data[j+1]=data[j];
					data[j]=temp;
				}
			}
			
			System.out.print(i+"次排序:");
			for (int j = 0; j < data.length; j++) {
				System.out.print(" "+data[j]);
			}
			System.out.println("\n");
		}
		
	}
複製代碼

假設輸入的值是:118,101,105,127,112。那麼打印結果以下:3d

1次排序: 101 105 118 112 127

2次排序: 101 105 112 118 127

3次排序: 101 105 112 118 127

4次排序: 101 105 112 118 127
複製代碼

快速排序算法

快速排序算法:取一個值(一般爲數組第一個元素或中間的元素)做爲分界值。從數組右側(尾部)依次取出元素與中間值比較,直到有小於分界值的元素i,而後從左側開始,依次取出元素與中間值比較,直到有大於中間值的元素j,交換元素i和j的位置。但元素j的位置小於元素i的位置時,以元素j的位置爲分界處重複上述操做(遞歸);code

算法實現cdn

static void quickSort(int[] data,int begin,int end){
		int left=begin,right=end;
		int temp=data[(right+left)/2],value;
		
		while (left<right) {
			while (data[right]>temp) {
				 right--;
			}
			
			while (data[left]<temp) {
				left++;
			}
			
			if (left<=right) {
				value=data[left];
				data[left]=data[right];
				data[right]=value;
				right--;
				left++;
			}
			
			for (int i = 0; i < data.length; i++) {
				System.out.print(" "+data[i] );
			}
			
			System.out.println("");
			
			if (left==right) {
				left++;
			}
			
			if (begin<right) {
				quickSort(data,begin,left-1);
			}
			
			if (left<end) {
				quickSort(data, right+1, end);
			}
		}
		
		
	}
複製代碼

假設數組元素爲:118,101,105,127,112。那麼打印結果以下:blog

105 101 118 127 112
 101 105 118 127 112
 101 105 118 112 127
 101 105 112 118 127
複製代碼

選擇排序

選擇排序

選擇排序主要思想是遍歷數組,選擇數組中最小的元素放在第一個位置,第二小放在第二個位置,依次類推。

下面是算法的實現:

static void selectSort(int[] data) {
	int temp; //用於交換數據的臨時變量
	for (int i = 0; i < data.length - 1; i++) {
	    //從i+1位置開始,與i的位置比較
		for (int j = i + 1; j < data.length; j++) {
			//若是j的位置元素小於i的值,則與i位置的元素交換
			//這樣就保持了i位置相對於後面的元素都是最小的
			if (data[i] > data[j]) {
				temp = data[i];
				data[i] = data[j];
				data[j] = temp;
			}
		}
		//將每次排序後的元素打印出來,方便查看
		System.out.print(i+": ");
		for (int j = 0; j < data.length; j++) {
			System.out.print(" "+data[j]);
		}
		System.out.println();
	}
}
複製代碼

假如排序的數據爲:118,101,105,127,112。那麼打印出來的結果以下所示:

0:  101 118 105 127 112
1:  101 105 118 127 112
2:  101 105 112 127 118
3:  101 105 112 118 127
複製代碼

堆排序

堆排序相對於選擇排序來講,比較複雜,主要是堆的構造過程(大根堆和小更堆)。而後選擇堆的根節點與最後一個葉節點交換,並輸出交換後最後一個葉節點(再也不參與後面的堆構造過程)。從新構造堆得反覆過程。

堆結構:堆結構是一種樹結構,準備說法是徹底二叉樹,由於涉及到徹底二叉樹的一些特性,假設樹有n個節點,第m個節點具備以下特性:

  • 若是2*m<=n,有左子樹,下標爲2*m+1;
  • 若是2*m+1<=n,有右子樹,下標爲2*m+2;

大根堆:若是按照從小到大的順序排序,要求非葉節點的數據要大於或等於左右子樹。

小根堆:若是按照從到到小的順序排序,要求非葉節點的數據要小於或等於子樹。

算法實現

static void headSort(int[] data,int n){
	int i,j,h,k;
	int temp;
	
	//將數組構建成大根堆
	for (i=n/2-1;i>=0;i--) {
		while (2*i+1<n) { //第i個元素有右子樹(意味着也有左子樹)
			j=2*i+1; //左子樹下標
			
			if (data[j]<data[j+1]) { //左子樹小於右子樹
				j++; //j指向右子樹
			}
			
			//i元素與左右子樹最大值進行比較,構造大根堆
			if (data[i]<data[j]) {
				temp=data[i];
				data[i]=data[j];
				data[j]=temp;
				i=j;//交換會致使子樹堆結構被破壞,須要從新構造
			}else {
				break;//子樹堆未被破壞
			}
		}
	}
	
	System.out.print("原始數據構形成的堆:");
	for (int l = 0; l < data.length; l++) {
		System.out.print(" "+data[l]);
	}
	
	System.out.println();
	
	for(i=n-1;i>0;i--){
		//堆得根第一個元素(數值最大)與最後一個元素(i元素,數值最小)交換
		temp=data[0];
		data[0]=data[i];
		data[i]=temp;
		
		k=0;
		//每一步排序後須要從新構造堆,算法與上面構造初始堆是一致的
		while (2*k+1<i) {
			j=2*k+1;
			if (data[j+1]<i) {
				j++;
			}
			if (data[k]<data[j]) {
				temp=data[k];
				data[k]=data[j];
				data[j]=temp;
				k=j;
			}else {
				break;
			}
			
		}
		
		System.out.print("第"+(n-i)+"次排序結果:");
		for (int l = 0; l < data.length; l++) {
			System.out.print(" "+data[l]);
		}
		System.out.println();
	}
}
複製代碼

假如排序的數據爲:118,101,105,127,112。那麼打印出來的結果以下所示:

原始數據構形成的堆: 127 118 105 101 112
第1次排序結果: 118 112 105 101 127
第2次排序結果: 112 101 105 118 127
第3次排序結果: 105 101 112 118 127
第4次排序結果: 101 105 112 118 127
複製代碼

歸爲選擇排序算法估計就是每次挑堆中最大(或最小)的元素輸出。

插入排序

插入排序

插入排序主要是後面元素與前面排序好的元素比較,而後插入到合適的位置。

算法實現:

static void insetSort(int[] data){
	int temp;
	for (int i = 1; i < data.length; i++) {
		temp=data[i];//保存i元素,下面元素後移會覆蓋數組i下標的值
		int j=i-1;
		
		while(j>=0&&temp<data[j]){//i元素與依次與前面比較,直到大於前面元素爲止
			data[j+1]=data[j];//前面元素後移,方便i元素插入
			j--;
		}
		data[j+1]=temp;
	
		System.out.print("第"+i+"次排序結果:");
		for (int l = 0; l < data.length; l++) {
			System.out.print(" "+data[l]);
		}
		System.out.println();
	}
}
複製代碼

假如排序的數據爲:118,101,105,127,112。那麼打印出來的結果以下所示:

第1次排序結果: 101 118 105 127 112
第2次排序結果: 101 105 118 127 112
第3次排序結果: 101 105 118 127 112
第4次排序結果: 101 105 112 118 127
複製代碼

Shell排序算法

主要是將有n個元素的數組分紅n/2個數字序列,第1個數據和第n/2+1數據組成一對,一對數據進行比較,後者大則調換位置進行排序。而後n/4,n/8..重複排序,直到最後n/(2*k)=1,進行插入排序算法進行排序。Shell排序比較適合數組元素比較多狀況。

算法實現

static void shellSort(int[] data){
	int x=0;
	int temp;
	
	for (int n = data.length/2; n >=1; n/=2) {//解決序列問題,即分組
		
		int j;
		
		for (int i = n; i < data.length; i++) {
			temp=data[i];
			j=i-n;//j座標所在元素與i座標所在元素成對
			
			while (j>=0&&temp<data[j]) {
				data[j+n]=data[j];
				j-=n;
			}
			data[j+n]=temp;
			
			
			System.out.print("第"+(x++)+"次排序結果:");
			for (int l = 0; l < data.length; l++) {
				System.out.print(" "+data[l]);
			}
			System.out.println();
		}
	}

}

}
複製代碼

這裏特地將打印信息,放到第一個循環內,能夠清楚看出序列排序。假設屬於數組爲:118,121,105,127,112,30。 則打印結果以下:

//由於共分紅6/2=3對序列,因此下標三、0,四、1,五、2一塊兒組成3對序列,進行比較交換
//105-127
第0次排序結果: 118 121 105 127 112 30
//121-112
第1次排序結果: 118 112 105 127 121 30
//102-30
第2次排序結果: 118 112 30 127 121 105
//此時。6/4=1對序列,採用插入排序算法
第3次排序結果: 112 118 30 127 121 105
第4次排序結果: 30 112 118 127 121 105
第5次排序結果: 30 112 118 127 121 105
第6次排序結果: 30 112 118 121 127 105
第7次排序結果: 30 105 112 118 121 127
複製代碼

複雜度以下

本文參考《Java經常使用算法手冊》

相關文章
相關標籤/搜索