前面讲了最常规的快速排序算法实现,常规实现中使用了递归进行不断分治递归出最后的区间,虽然书写容易,但是递归终究需要递归栈空间的支持,在数据量达到一定程度时,递归将进一步的限制算法的效率。这里我们将递归换做一个栈结构来替代实现非递归版本的快速排序。
code:
<span style="font-family:Comic Sans MS;font-size:14px;">// 划分区间 返回基准值的位置
int Partition(int arr[], int left, int right)
{
int key = arr[left]; // 将一个数作为基准值
int i = left, j = right;
while(i < j)
{
// 从最右边找第一个小于基准值的数字
while(i < j && arr[j] >= key) j--;
arr[i] = arr[j]; // 放在基准值左边
// 从最左边找第一个大于基准值的数字
while(i < j && arr[i] <= key) i++;
arr[j] = arr[i]; // 放在基准值的右边
}
arr[i] = key; // 确定基准值的位置
return i; // 返回基准值的位置
}
void QuickSort1(int arr[], int n)
{
if (n <= 1) return;
stack<int> SStack;
// 将最大的区间压入栈
SStack.push(0);
SStack.push(n-1);
int left, right, mid;
while(!SStack.empty())
{ // 注意按相反的顺序取出两边大小
right = SStack.top();
SStack.pop();
left = SStack.top();
SStack.pop();
// 计算基准值的位置进行新子区间划分
mid = Partition(arr, left, right);
// 将左边新区间入栈
if (mid-1 > left)
{
SStack.push(left);
SStack.push(mid-1);
}
//将右边新区间入栈
if (mid+1 < right)
{
SStack.push(mid+1);
SStack.push(right);
}
}
}</span>
根据排序过程中借助的主要操作,我们将内排序分为:插入排序、交换排序、选择排序和归并排序四类。之后介绍的七种排序法,就分别是各种分类的代表算法。其中:插入排序类(插入排序, 希尔排序);选择排序类(选择排序, 堆排序);交换排序(冒泡排序, 快速排序); 归并排序类(归并排序)