標籤:
快速演算法的思路就是對數組分區排序
一般的先取第一個數作為基準數,然後將整個數列按大小分成兩個區,大於基準數的在右邊,小於的在左邊。然後分別對分區按照上面的方法在進行分區排序,直到整個數組排序好。
下面以一個數組為例:
6,7,1,8,3,9,2,5,10
一般的以第一個數作為基準數,那麼怎麼才能將大於6的移到右邊,小於6的移到左邊呢?
假如用6從頭到尾比的話,6比7小不動,6比1大換位,這樣無法排序(冒泡排序是相鄰的兩個數比較換位)。
假如再建立一個一樣大的空數組,將比6小的放在左邊,大的放在右邊,剩下的一個位子就是基準數,並記錄下它的位子,這樣也很麻煩,遞迴下去需要的中間數會越來越多,而且沒有頭和尾。另外建立這麼多數組也很耗費記憶體,最好是能夠在原來的數組上面進行修改。
既然要分區,肯定有個中間位置,假定中間的指標叫middle,顯然這個Middle可以通過比較得出,那麼必須要兩個指標來表示這個區的位置,假定這個區的開始是left,結尾是right。要遞迴的分區下去,需要這樣三個參數,int[] array, int left,int right 。那麼遞迴什麼時候結束呢?當不能再分區的時候就結束了,嗎麼什麼時候不能再分區呢?left=right的時候。
這裡最重要的就是一個求分區中間值的函數,我們假定為getMiddle(int array ,int left ,int right)
排序的函數 sort(int [] array,int left ,int right)
按照上面的思路那麼這個sort函數的函數體如下
public void sort(int [] array ,int left ,int right) { if(left<right) { int middle=getMiddle(array,left,right); sort(array, left, middle-1);//對左邊的進行分區 sort(array, middle+1, right);//對右邊的進行分區 } }
現在要實現getMiddle函數,這個函數需要在分區中找到中間的位置,而且要在原數組上進行操作。
首先將該區的第一個即 left 和最後一個即right 進行比較
目的是在右邊找到一個數比left指向的數小,並把它替換掉left指向的位置,那麼這樣替換下去會不會造成left指向的數消失呢?當然持續在右邊找的話肯定會這樣的,怎麼樣才能避免這樣的問題?那就是右邊找完了,替換掉left指向的那個數,即right指向的那個數現在有重複,現在left和right指向的那個數是一樣的,就需要在right的左邊找到一個數能夠取代right的數,這樣就從left開始比較,要找到一個比基準數大的去替換掉右邊,只要left<right就不停止。當left和right相等的時候這個位置的左邊都比基準數小,右邊都比基準數大。這個位置就是Middle。
public int getMiddle(int[] list, int left, int right) { int pvoit=list[left]; while(left<right) { while(left<right && list[right]>pvoit) { right--; } list[left]=list[right]; while(left<right && list[left]<pvoit) { left++; } list[right]=list[left]; } list[left]=pvoit; return left; //返回中軸的位置 }
最後測試
public void quick(int[] str) { if (str.length > 0) { //查看數組是否為空白 sort(str, 0, str.length - 1); } }
快速排序演算法-java