“挖坑填坑”理解快速排序

    快速排序的基本思路:找一個基準元素,對數組進行調整,調整的標準是,這個基準元素的左邊存放的都是比這個元素小的,右邊都是比這個元素大的。然後分而治之,對左右兩邊的子數組利用同樣的規則調整,調整到每一個子數組中都只有一個元素時結束。

    基本思想很簡單,主要是理解如何在確定基準元素之後,對數組(子數組)進行調整,下面舉個例子,用“挖坑填坑”(拆了東牆補西牆)的比喻來理解一次調整的過程。

一個無序數組:[4, 3, 7, 5, 10, 9, 1, 6, 8, 2]

1.      隨便先挖個坑,就在第一個元素(基準元素)挖坑,挖出來的“蘿蔔”(第一個元素4)在“籃子”(臨時變量)裏備用。挖完之後的數組是這樣:[ , 3, 7, 5, 10, 9, 1, 6, 8,2]

2.      挖右坑填左坑:從右邊開始,找個比“蘿蔔”(元素4)小的元素,挖出來,填到前一個坑裏面。填坑之後:[ 2, 3, 7, 5, 10, 9, 1, 6, 8,]

3.      挖左坑填右坑:從左邊開始,找個比“蘿蔔”(元素4)大的元素,挖出來,填到右邊的坑裏面。填坑之後:[ 2, 3,, 5, 10, 9, 1, 6, 8, 7]

4.      挖右坑填左坑:從右邊開始,找個比“蘿蔔”(元素4)小的元素,挖出來,填到前一個坑裏面填坑之後:[ 2, 3, 1, 5, 10, 9,, 6, 8, 7]

5.      挖左坑填右坑:從左邊開始,找個比“蘿蔔”(元素4)大的元素,挖出來,填到右邊的坑裏面填坑之後:[ 2, 3, 1,, 10, 9, 5, 6, 8, 7]

6.      挖右坑填左坑:從右邊開始,找個比“蘿蔔”(元素4)小的元素,挖出來,填到前一個坑裏面,這一次找坑的過程中,找到了上一次挖的坑了,說明可以停了,用籃子裏的的蘿蔔,把這個坑填了就行了,並且返回這個坑的位置,作爲分而治之的中軸線。填坑之後:[ 2, 3, 1, 4, 10, 9, 5, 6, 8, 7]

上面的步驟中,第2,4, 6其實都是一樣的操作,3和5的操作也是一樣的。

代碼如下:

int _qucikly_sort(int arr[], int low, int high) {
  int pivot = arr[low]; //挖第一個坑,把“蘿蔔”放進籃子
  while(low<high) { //開始循環挖坑填坑
    //如果low等於high,說明找坑的過程中,找到了上一次挖的坑,因此可以停止了
    while(low<high && arr[high]>=pivot) //從右邊往左邊找填坑的元素(比pivot小的元素)。 2,4,6的過程
      --high;
    arr[low] = arr[high]; //將找到之後,挖出來,填到左邊的坑裏
    while(low<high && arr[low]<=pivot) //從左邊往右邊找填坑的(比pivot大的元素)。3,5的過程
      ++low;
arr[high] = arr[low];//找到之後,填到右邊的坑裏
  }
  arr[low] = pivot; //籃子裏的“蘿蔔”填到坑裏
  return low;//返回這個坑的位置,作爲分而治之的中軸
}


分而治之的代碼:

void quickly_sort(int arr[], int low, int high) {
  if (low < high) {
    int pivot = _qucikly_sort(arr, low, high);  
    quickly_sort(arr, low, pivot-1);
    quickly_sort(arr, pivot + 1, high);
  }
}


測試代碼:

#include <stdio.h>
#include <stdlib.h>

void display(int arr[], int len) {
  for(int i = 0; i < len;i++)
    printf("%d ", arr[i]);
  printf("\n");
}

int main() {
  int arr[] = {4, 3, 7, 5, 10, 9, 1, 6, 8, 2};
  quickly_sort(arr, 0, sizeof(arr)/sizeof(int) - 1);
  display(arr, sizeof(arr)/sizeof(int));
  return 0;
}








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