排序算法的c++實現——快速排序

    快速排序是分治思想的又一典型表明,是應用最廣的排序算法。分治思想就是把原問題的解分解爲兩個或多個子問題解,求解出子問題的解以後再構造出原問題的解。ios

    在快速排序算法中,它的思想是把一個待排序的數組分紅前半部分和後半部分,而且要求前半部分的值都大於等於或都小於等於後半部分的解, 當前半部分與後半部分都變成有序(經過遞歸調用快速排序來實現)後,咱們就不須要合併兩個子問題的解就已經獲得了原問題的解。這也是爲何要求前半部分都大於等於或都小於等於後半部分的緣由。因此呢,快速排序的核心在於如何把一個待排序的數組分紅兩部分!git


說明幾點:
1. 如何把待排序的數組劃分爲符合要求的兩部分!
2. 指望的時間複雜度爲O(NlogN), 最壞的時間複雜度爲O(N*N)
 3. 快速排序爲原址排序,不須要額外的內存空間.
 4. 快速排序不是穩定排序, 在交換過程當中會破壞穩定性。

github

代碼以下:redis

  1 /***********************************************************************
  2   *   Copyright (C) 2019  Yinheyi. <chinayinheyi@163.com>
  3   *   
  4   * This program is free software; you can redistribute it and/or modify it under the terms
  5   * of the GNU General Public License as published by the Free Software Foundation; either 
  6   * version 2 of the License, or (at your option) any later version.
  7   
  8   *   Brief:    
  9   *   Author: yinheyi
 10   *   Email: chinayinheyi@163.com
 11   *   Version: 1.0
 12   *   Created Time: 2019年05月08日 星期三 21時54分04秒
 13   *   Modifed Time: 2019年05月10日 星期五 22時16分17秒
 14   *   Blog: http://www.cnblogs.com/yinheyi
 15   *   Github: https://github.com/yinheyi
 16   *   
 17   ***********************************************************************/
 18   
 19   
 20   // 1. 快速排序是分治思想的又一典型表明,是應用最廣的排序算法。
 21   // 2. 分治思想就是把原問題的解分解爲兩個或多個子問題解,求解出子問題的解以後再構造出原
 22   // 問題的解。
 23   // 3. 在快速排序算法中,它的思想是把一個待排序的數組分紅前半部分和後半部分,而且要求
 24   // 前半部分的值都大於等於或都小於等於後半部分的解, 當前半部分與後半部分都變成有序(通
 25   // 過遞歸調用快速排序來實現)後,咱們就不須要合併兩個子問題的解就已經獲得了原問題的解。
 26   // 這也是爲何要求前半部分都大於等於或都小於等於後半部分的緣由。
 27   // 4.因此呢,快速排序的核心在於如何把一個待排序的數組分紅兩部分!
 28   //
 29   // 核心點:
 30   // 1. 如何把待排序的數組劃分爲符合要求的兩部分!
 31   // 2. 指望的時間複雜度爲O(NlogN), 最壞的時間複雜度爲O(N*N)
 32   // 3. 快速排序爲原址排序,不須要額外的內存空間.
 33   // 4. 快速排序不是穩定排序, 在交換過程當中會破壞穩定性。
 34   //
 35   #include<cassert>
 36   #include <stdexcept>
 37   #include <iostream>
 38   static inline void swap(int&, int&);
 39   bool less(int lhs, int rhs);
 40   bool greate(int lhs, int rhs);
 41   static void PrintArray(int array[], int nLength_);
 42   typedef bool (*Compare)(int, int);
 43   
 44   /****************  版本一:使用數組的長度做爲參數        ***************/
 45   // 該函數實現對數組數列的劃分;
 46   // 輸入值爲數組指針/數組的長度/比較函數指針,
 47   // 返回值爲劃分點的下標, 也就是後半部分第一個元素的下標;
 48   int Partition(int array[], int nLength_, Compare CompFunc)
 49   {
 50       if (array == nullptr || nLength_ <= 0 || CompFunc == nullptr)
 51       { 
 52           assert(false);
 53           throw std::invalid_argument("參數不合法!");
 54       }       
 55   
 56       int _nBoundValue = array[0];        // 劃分區間的邊界值
 57       int _nBoundIndex = 0;               // 指向邊界的下標, 即第二部分第一個元素的下標;
 58       for (int i = 1; i < nLength_; ++i)      
 59       {   
 60           if (CompFunc(array[i], _nBoundValue))
 61           {
 62               swap(array[i], array[_nBoundIndex]);
 63               ++_nBoundIndex;
 64           }       
 65       }  
 66   
 67       // 若是第一個元素正好是最大或最小元素時,把返回值加1, 也就是把數組劃分爲第一個元素
 68       // 和剩餘的其它元素兩部分。
 69       if (0 == _nBoundIndex)
 70           return _nBoundIndex + 1;
 71       else
 72           return _nBoundIndex;
 73   }
 74   
 75   // 快速排序的功能函數
 76   void QuickSort(int array[], int nLength_, Compare CompFunc)
 77   {
 78       if (array == nullptr || nLength_ <=1 || CompFunc == nullptr)
 79           return;
 80   
 81       int _nPartionIndex = Partition(array, nLength_, CompFunc);
 82       QuickSort(array, _nPartionIndex, CompFunc);
 83       QuickSort(array + _nPartionIndex, nLength_ - _nPartionIndex, CompFunc);
 84   }
 85   
 86   /****************  版本二:使用數組的下標區間做爲參數        ***************/
 87   // 該函數實現對數組的劃分。
 88   // 輸入參數爲數組指針/半閉半開區間[start, end)表示的數組範圍/比較謂詞
 89   // 返回值爲劃分點的下標, 也即後半部分第一個元素的下標。
 90   int Partition_Version2(int array[], int nStart_, int nEnd_, Compare CompFunc)
 91   {
 92       if (array == nullptr || nEnd_ - nStart_ <= 0 || CompFunc == nullptr)
 93       {
 94           assert(false);
 95           throw std::invalid_argument("參數不合法!");
 96       }
 97   
 98       int _nBoundValue = array[nStart_];      // 劃分區間的邊界值
 99       int _nBoundIndex = nStart_;             // 指向邊界的下標, 即第二部分第一個元素的下標;
100       for (int i = nStart_ + 1; i < nEnd_; ++i)
101       {
102           if (CompFunc(array[i], _nBoundValue))
103           {
104               swap(array[i], array[_nBoundIndex]);
105               ++_nBoundIndex;
106           }
107       }
108   
109       // 若是第一個元素正好是最大或最小元素時,把返回值加1, 也就是把數組劃分爲第一個元素
110       // 和剩餘的其它元素兩部分。
111       if (_nBoundIndex == nStart_)
112           return _nBoundIndex + 1;
113       else
114           return _nBoundIndex;
115   }
116   
117   void QuickSort_Version2(int array[], int nStart_, int nEnd_, Compare CompFunc)
118   {
119       if (array == nullptr || nEnd_ - nStart_ <= 1 || CompFunc ==nullptr)
120           return;
121   
122       int _nPartionIndex = Partition_Version2(array, nStart_, nEnd_, CompFunc);
123       QuickSort_Version2(array, nStart_, _nPartionIndex, CompFunc);
124       QuickSort_Version2(array, _nPartionIndex, nEnd_, CompFunc);
125   }
126   
127   // 測試函數
128   /***************    main.c     *********************/
129   int main(int argc, char* argv[])
130   {
131       int array[10] = {-12, 23, 443, 112, 12, -9098, 3432, 0, 0, 0};
132       std::cout << "原數組的順序爲:" << std::endl;
133       PrintArray(array, 10);
134       std::cout << "版本一的快速排序:" << std::endl;
135       std::cout << "從小到大:" << std::endl;
136       QuickSort(array, 10, less);
137       PrintArray(array, 10);
138       std::cout << "從大到小:" << std::endl;
139       QuickSort(array, 10, greate);
140       PrintArray(array, 10);
141       std::cout << std::endl;
142   
143   
144       int array2[10] = {-12, 23, 443, 112, 12, -9098, 3432, 0, 0, 0};
145       std::cout << "版本二的快速排序:" << std::endl;
146       std::cout << "從小到大:" << std::endl;
147       QuickSort_Version2(array2, 0, 10, less);
148       PrintArray(array2, 10);
149       std::cout << "從大到小:" << std::endl;
150       QuickSort_Version2(array2, 0, 10, greate);
151       PrintArray(array2, 10);
152   
153       return 0;
154   }
155   
156   
157   inline void swap(int& lhs, int& rhs)
158   {
159       int _nTemp = lhs;
160       lhs = rhs;
161       rhs = _nTemp;
162   }
163   
164   // 小於比較函數
165   bool less(int lhs, int rhs)
166   {
167       return lhs < rhs;
168   }
169   
170   // 大於比較函數
171   bool greate(int lhs, int rhs)
172   {
173       return lhs > rhs;
174   }
175   
176   // 打印數組函數
177   static void PrintArray(int array[], int nLength_)
178   {
179       if (nullptr == array || nLength_ <= 0)
180           return;
181   
182       for (int i = 0; i < nLength_; ++i)
183       {
184           std::cout << array[i] << " ";
185       }
186   
187       std::cout << std::endl;
188   }
相關文章
相關標籤/搜索