快速排序(C++實現、遞歸、非遞歸)

(本博客旨在個人總結回顧)

1.概括

        快速排序由C. A. R. Hoare在1962年提出。它的基本思想是:通過一趟排序將要排序的數據分割成獨立的兩部分,其中一部分的所有數據都比另外一部分的所有數據都要小,然後再按此方法對這兩部分數據分別進行快速排序,整個排序過程可以遞歸進行,以此達到整個數據變成有序序列。

2.實現

C++遞歸和非遞歸實現:(一般遞歸轉爲非遞歸,可以使用stack實現)

// quickSort.cpp : 定義控制檯應用程序的入口點。
//
//個人博客:https://blog.csdn.net/qq_23903863
#include "stdafx.h"
#include <iostream>
#include <ctime>
#include <stack>
using namespace std;


/*
* @name   PartSort
* @brief  以第一個數組元素爲基準
大於等於該基準的值放置組數右側
小於該基準的值放置數組左側
最後該基準放置於中間位置
* @param  [in] int * pArray	待排序數組
* @param  [in] int nLeft		最左側下標
* @param  [in] int nRight		最右側下標
* @return int	                中間位置下標
*/
int PartSort(int* pArray, int nLeft, int nRight)
{
    int nKey = pArray[nLeft];
    while (nLeft < nRight)
    {
        while (pArray[nRight] >= nKey && nRight > nLeft)
        {
            nRight--;
        }
        pArray[nLeft] = pArray[nRight];
        while (pArray[nLeft] < nKey && nLeft < nRight)
        {
            nLeft++;
        }
        pArray[nRight] = pArray[nLeft];
    }
    pArray[nLeft] = nKey;
    return nLeft;
}

/*
 * @name   QuickSortRecursion
 * @brief  快速排序遞歸實現
 * @param  [in] int * pArray 待排序的數組
 * @param  [in] int nLeft	 數組左下標
 * @param  [in] int nRight	 數組右下標
 * @return void
 */
void QuickSortRecursion(int* pArray, int nLeft, int nRight)
{
	if (NULL == pArray)
	{
		return;
	}
	if (nLeft >= nRight)
	{
		return;
	}

    int nMid = PartSort(pArray, nLeft, nRight);
    QuickSortRecursion(pArray, nLeft, nMid - 1);
    QuickSortRecursion(pArray, nMid + 1, nRight);
}


/*
 * @name   QuickSortUnrecursion
 * @brief  快速排序非遞歸實現
 * @param  [in] int * pArray	待排序數組
 * @param  [in] int nLeft		起始下表
 * @param  [in] int nRight		終止下表
 * @return void
 */
void QuickSortUnrecursion(int* pArray, int nLeft, int nRight)
{
	if (NULL == pArray && nLeft >= nRight)
	{
		return;
	}
    stack<int> stackIndex;
    stackIndex.push(nLeft);
    stackIndex.push(nRight);
    int nBegin = 0;
    int nEnd = 0;
    int nMid = 0;
    while (!stackIndex.empty())
    {
        nEnd = stackIndex.top();
        stackIndex.pop();
        nBegin = stackIndex.top();
        stackIndex.pop();
        nMid = PartSort(pArray, nBegin, nEnd);
        if (nBegin < nMid - 1)
        {
            stackIndex.push(nBegin);
            stackIndex.push(nMid - 1);
        }
        if (nEnd > nMid + 1)
        {            
            stackIndex.push(nMid + 1);
            stackIndex.push(nEnd);
        }
    }
}


int _tmain(int argc, _TCHAR* argv[])
{
	//測試例子
	//①空指針;
	//②1個元素;
	//③2個元素;
	//④3個元素;
	//⑤100個元素;
	//⑥100萬個元素 在本人(vs2013)默認開發環境下,(遞歸)4000個元素髮生棧溢出 (非遞歸)300000個元素髮生棧溢出
	int array1[15] = {};//修改數組大小就可改變元素個數,實現升序排序測試
	int nLength = sizeof(array1) / sizeof(array1[0]);
	int nUn = -1;
	srand(time(0));
	for (int i = 0; i < nLength; i++)
	{
		nUn *= -1;
		array1[i] = rand() * nUn;
	}

	cout << "排序前:" << endl;
	for (int i = 0; i < nLength; i++)
	{
		cout << array1[i] << "  ";
	}
	QuickSortUnrecursion(array1, 0, nLength - 1);
	cout << endl << "排序後" << endl;
	for (int i = 0; i < nLength; i++)
	{
		cout << array1[i] << "  ";
	}
	cout << endl;
	system("pause");
	return 0;
}

運行結果:

注意:

在遞歸太深的情況下會導致棧溢出,原因是因爲系統棧空間有限,當遞歸函數中一般需要用到局部變量,局部變量存在棧中,所以在遞歸太深的情況下就會導致棧溢出。

當然在上面的例子中,只要組數足夠大,你總能體驗棧溢出的提示,上面的例子,數組空間也是在棧中的。

 

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