91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

c語言快速排序實現方法

發布時間:2020-05-29 15:03:12 來源:億速云 閱讀:232 作者:鴿子 欄目:編程語言
  • 快排
  • 原理:
    • 從待排序區間選擇一個數,作為基準值(pivot)
    • Partition: 遍歷整個待排序區間,將比基準值小的(可以包含相等的)放到基準值的左邊,將比基準值大的(可以包含相等的)放到基準值的右邊
    • 采用分治思想,對左右兩個小區間按照同樣的方式處理,直到小區間的長度等于1,代表已經有序,或者小區間的長度等于0,代表沒有數據。
  • 快排是一個不穩定的排序
實現方式
  1. 快排的邏輯其實很簡單,

    • 遞歸分治
    • 代碼如下:

      public static void quickSort(int[] array) {
              //待排序區間為[0, array.length - 1]
              quickSortIternal(array, 0, array.length - 1);
      }
      
      private static void quickSortIternal(int[] array, int left, int right) {
              if(left >= right)
                      return;
      
              //這里的就選擇最左邊的元素作為基準值來操作
              //index表示基準值停留的下標
              int index = partition(array, left, right);
      
              quickSortIternal(array, left, index - 1);
              quickSortIternal(array, index + 1, right);
      }
    • 非遞歸分治
    • 通過使用棧實現,將數組的左右下標放入棧中
    • 每次取出判斷left和right的關系,如果left >= right 表示該小區間排序完畢
    • 存入每個區間的左右兩下標,依次循環,當棧為空時,表示排序結束
    • 代碼如下:

      public static void quickSort2(int[] array) {
                  Stack<Integer> stack = new Stack<>();
                  stack.push(array.length - 1);
                  stack.push(0);
      
                  while(!stack.isEmpty()) {
                          int left = stack.pop();
                          int right = stack.pop();
      
                          if(left >= right) {
                                  continue;
                          }
      
                          int index = partition(array, left, right);
      
                          stack.push(right);
                          stack.push(index + 1);
      
                          stack.push(index - 1);
                          stack.push(left);
                  }
          }
  2. 重點是partition的實現

    • 實現方法一: Hoare法
    • 使用雙引用的的方式,一個指向區間的最左邊,一個指向區間的最右邊,兩個引用向中間遍歷的靠攏
    • 如果左引用指向的值小于等于基準值就移動
    • 如果右引用指向的值大于等于基準值就移動
    • 當左引用遇到大于基準值的數據且右引用遇到小于基準值的數據時,交換這兩個引用處的數據
    • 當兩個引用相遇時說明本次partition結束,返回基準值的下標
    • 代碼如下:

      public int partition(int[] array, int left, int right) {
                  int pivot = array[left];
                  int l = left;
                  int r = right;
      
                  while(l < r) {
                          while(l < r && array[r] >= pivot) {
                                  r--;
                          }
                          while(l < r && array[l] <= pivot) {
                                  l++;
                          }
                          swap(array, l, r);
                  }
                  swap(array, left, l);
                  return l;
          }
      
          private static void swap(int[] array, int i, int j) {
                  int tmp = array[i];
                  array[i] = array[j];
                  array[j] = tmp;
          }
    • 實現方法二:填坑法
    • 同樣需要雙引用,指定一個變量保存基準值,假象基準值的位置是一個“坑”
    • 右引用遇到大于等于基準值的數值就向左移動,直到遇到第一個小于基準值的數值,將該數值填到“坑”中,此處的位置是一個新的“坑”
    • 開始移動左引用,只有遇到一個大于基準值的數值時,填到“坑”中
    • 直到左引用和右引用相遇時說明只剩最后一個坑了,將基準值填到“坑”中,返回基準值的下標,本次partition結束
    • 代碼如下:

      public int partition(int[] array, int left, int right) {
          int pivot = array[left];
          int l = left;
          int r = right;
      
          while(l < r) {
                  while(l < r && array[r] >= pivot) {
                          r--;
                  }
                  array[l] = array[r];
                  while(l < r && array[l] <= pivot) {
                          l++;
                  }
                  array[r] = array[l];
          }
          array[l] = pivot;
          return l;
      }
    • 實現方法三:前后遍歷法
    • 同樣是使用雙引用slow和fast,起初同時指向基準值的后一個元素left + 1
    • 引用fast向后遍歷,如果遍歷到的數值大于基準值就向后移動
    • 遇到小于基準值的數值時,交換slow引用和fast引用指向的值,slow向后移動一位
    • 始終保證slow之前的值都是小于基準值的數值,slow和fast之間的是大于等于基準值的數值,當fast移動到區間最右端right時,遍歷結束
    • 此時show - 1處的數值為最遍歷結束后最后一個小于基準值的數值
    • 交換left和slow - 1兩位置處的數值,slow - 1表示下標即是基準值的下標,返回slow - 1
    • 代碼如下:

      private int partition(int[] array, int left, int right) {
                  int pivot = array[left];
                  int slow = left + 1;
                  int fast = left + 1;
      
                  while(fast <= right) {
                          if(array[fast] < pivot) {
                                  swap(array, slow, fast);
                                  slow++;
                          }
                          fast++;
                  }
                  swap(array, left, slow - 1);
                  return slow - 1;
          }
  3. 基準值的選擇
    • 兩邊取其一(左或者右)
    • 隨機選擇
    • 幾數取中(例三數取中:array[left], array[mid], array[right] 大小是中間的為基準值 )
性能分析
  • 時間復雜度:
    • 最好的情況:O(N*logN)
    • 平均情況:O(N*logN)
    • 最壞的情況:O(N^2)
  • 空間復雜度:O(1)
    • 最好的情況:O(logN)
    • 平均情況:O(logN)
    • 最壞的情況:O(N)
  • 穩定性:不穩定

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

古蔺县| 昌吉市| 休宁县| 门源| 芷江| 油尖旺区| 阳原县| 山阴县| 湾仔区| 北海市| 和顺县| 布拖县| 蓝山县| 阿巴嘎旗| 宜兰县| 五常市| 洪江市| 疏附县| 嘉荫县| 大竹县| 车致| 南平市| 镇康县| 社会| 固安县| 浙江省| 来安县| 大丰市| 饶河县| 双城市| 东港市| 新晃| 德庆县| 天峨县| 通河县| 河西区| 沐川县| 鱼台县| 启东市| 巧家县| 乌海市|