排序算法 ---選擇排序(直排,堆排)(java)

排序是在程序開發中常用的操作,也是個大公司面試的時候檢驗一個人編程能力的一個必考題,排序就是涉及到了算法了,今天下午就想着來搞一下排序的算法,算是對其有一個初步的瞭解吧,後天期中考了,掛科可就不是排序算法能夠解決的問題了。

衡量一個算法優劣的標準:

1.時間複雜度,完成這個任務,算法所需要的時間。

2.空間複雜度,完成該任務,算法所需要的佔用的內存空間,或者是所需要的外部輔助空間。

3.穩定性,完成任務後,對原始數據的影響大不大,會不會產生了一些不必要的操作,導致了原始數據發生了錯誤。

 現在的排序方式分爲兩種:1.內部排序2.外部排序

內部排序就是整個排序操作都在內存中執行不藉助於外部,外部排序就是需要藉助外部的存儲,大多是數據量比較大的一些排序,對於外部排序常用的方式就是多路歸併操作,將原始文件分成多個可以一次性裝進內存的子文件,執行排序,排序後,將其輸出到外部程序中。

我們所說的排序大多指的是內部排序,內部排序分爲以下幾類:選擇排序(直接選擇排序,堆排序),交換排序(冒泡排序,快速排序),插入排序(直接插入排序,折半插入排序,Sheel排序),歸併排序,桶式排序,基數排序。

選擇排序 

1.直接選擇排序

//直接選擇排序
    public int[] sort(int[] a) {
	for (int i = 0; i < a.length - 1; i++) {
	    int max = a[i];
	    for (int j = i + 1; j < a.length; j++) {
		if (a[j] > max) {
		    max = a[j];
		    a[j] = a[i];
		    a[i] = max;
		}
	    }

	}
	return a;

    }

思路:兩個嵌套的for循環,通過第一個循環找到第一個元素,通過一個值記錄這個元素,然後進入下一個循環,通過這個循環找到該數組中當前元素值要大的數,然後將兩者的值進行交換。上面的排序中當找出來符合值之後要進行多次值的交換,比較影響程序性能的,下面這種通過記錄其下標值來對較大的值做一個記錄,然後最後再對其進行交換,如果數據大的話,明顯的可以提升程序的性能。

 public int[] sort(int[] a) {
	for (int i = 0; i < a.length - 1; i++) {
	    int index = i;
	    for (int j = i + 1; j < a.length; j++) {
		if (a[j] > a[index]) {
		    index = j;
		}
	    }
	    if(index != i)
	    {
//		不借助第三變量將連個數的值進行交換
		a[i] = a[index]+a[i];
		a[index] = a[i]- a[index];
		a[i] = a[i] - a[index];
	    }

	}
	return a;

    }

2.堆排序

堆排序,首先就是要建堆,堆在這裏又分爲大頂堆和小頂堆,根據堆,堆在本質上就是一個二叉樹,大頂堆就是二叉樹的根節點是樹中最大的值,小頂堆就是根節點爲最小的二叉樹,利用堆進行排序的時候,首先是將所有數據建堆,將最大數或者最小數選擇出來,然後放在所有數據的最後面,然後將剩餘的數據執行上一次操作。

 public void buildHeap(int [] a){
	for(int i = 0;i<a.length-1;i++){
	    buildMaxHeap(a,a.length-1-i);
	    a[0] = a[0]+a[a.length-1-i];
	    a[a.length-1-i] =a[0]-a[a.length-1-i];
		    a[0]=a[0]-a[a.length-1-i];
	}
    }
    
    public void buildMaxHeap (int []a,int lastIndex){
	for(int i = (lastIndex-1)/2 ; i >= 0 ; i--){
	    int k = i;
	    while(k*2+1 <= lastIndex){
		int biggerIndex = 2*k+1;
		if(biggerIndex<lastIndex){
		    if(a[biggerIndex]<a[biggerIndex+1]){
			biggerIndex++;
		    }
		}
		if(a[k]>a[biggerIndex]){
		    a[k] = a[k]+a[biggerIndex];
		    a[biggerIndex] = a[k] - a[biggerIndex];
		    a[k] = a[k]-a[biggerIndex];
		}
		else
		    break;
	    }
	}
    }

對原來的數組進行抽象化,將其抽象成一棵二叉樹,數組中的首位元素是二叉樹的根結點,首先我們找到該數組的最後一位元素的下標,然後建立大頂堆,找到最後一個元素的父結點,判斷左右結點的大小,然後記錄下數值較大的數的座標,然後將其和其父節點進行數值上的交換,然後繼續向和其父節點處在同一層的元素的大小判斷,最中產生

了一個大頂堆,然後我們將這個頂端的值保存在數組的最後一個元素的位置,然後將之前的記錄的最後一個位置座標向前移動一位,然後接着進行循環。

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