中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

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

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

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

林周县| 扶沟县| 青海省| 上栗县| 思南县| 锦屏县| 灵川县| 临武县| 乐陵市| 莒南县| 新源县| 青铜峡市| 通州区| 泾源县| 兴仁县| 太康县| 玉田县| 凌云县| 平潭县| 麟游县| 虎林市| 丹寨县| 吴忠市| 文水县| 长沙县| 庆阳市| 长白| 新民市| 长葛市| 从化市| 临高县| 云和县| 甘南县| 讷河市| 武安市| 冀州市| 玉田县| 合水县| 紫金县| 调兵山市| 特克斯县|