快排算法(遞歸/非遞歸)

最近看了一篇文章,介紹遞歸轉非遞歸的方法,主要是通過stack的數據結構模擬遞歸函數堆棧的層次調用(後進先出,最裏層–>最外層,層層彈出),排序算法很多是通過遞歸來實現的,這裏照葫蘆畫瓢,實現一下非遞歸的快排算法。

先附上快排的遞歸用法,用於對比

/* 快速排序:從數組中選出一個值flag,通過一輪比較,將比flag大的置於一側,比flag小的置於另一側,再依照此法,對這兩部分做同樣的比較 */
/* 複雜度:最壞情況,每次選取flag爲最大或最小元素,退化成線性比較,O(n^2) 
           最好情況,每次選取的flag爲中間值時,類似平衡樹,每次都對半分,性能爲O(nlogn) */
void Test_Init::quickSort(std::vector<int>& sortArray, int begin, int end)
{
	if (begin >= end)
	{
		return;
	}
	int i = begin;
	int j = end;
	int flag = sortArray[j];//標誌位,以flag爲界限,大於flag置於右邊,小於flag的置於左邊
	while(i < j)
	{
		while ((sortArray[i] <= flag) && ((i < j)))
		{
			i++;
		}
		sortArray[j] = sortArray[i];
		while((sortArray[j] >= flag)&& (i < j))
		{
			j--;
		}
		sortArray[i] = sortArray[j]; 
	}
	sortArray[i]=flag;
	/* 經過一輪比較,以flag爲界限,分爲左右兩邊,左邊比flag小,右邊比flag大然後遞歸進行下一輪比較 */
	quickSort(sortArray, begin, i - 1);
	quickSort(sortArray, i + 1, end);
}

再看一下非遞歸的寫法

void Test_Init::quickSortNoRecursive(std::vector<int>& sortArray)
{
	struct SnapShot
	{
		int start;
		int end;			
	};
		
	SnapShot shot;
	shot.start = 0;
	shot.end = sortArray.size() - 1;
	std::stack<SnapShot> shotStack;
	shotStack.push(shot);
		
	while(!shotStack.empty())
	{
		/* 每次彈出棧頂元素 */
		SnapShot cur = shotStack.top();
		shotStack.pop();
		if (cur.start >= cur.end)
		{
			/* 僅有一個元素時,不必比較 */
			continue;
		}
		int i = cur.start;
		int j = cur.end;
		int flag = sortArray[j];
		while(i < j)
		{
			while ((sortArray[i] <= flag) && ((i < j)))
			{
				i++;
			}
			sortArray[j] = sortArray[i];
			while((sortArray[j] >= flag)&& (i < j))
			{
				j--;
			}
			sortArray[i] = sortArray[j]; 
		}
		/* flag右側進棧 */
		sortArray[i]=flag;			
		int tmp = cur.start;
		cur.start = j + 1;
		shotStack.push(cur);
			
		/* flag左側進棧,先出 */
		SnapShot next;
		next.end = j - 1;
		next.start = tmp;			
		shotStack.push(next);					
	}
	return;
}

点赞