快速排序的递归方法在之前的博客之中已经讲过,接下来给大家介绍非递归的方法。将递归方法转换为非递归的方法时,一般会想到使用循环,但是一些算法仅仅靠循环是非常难的。这时可以考虑使用各种数据结构,比如栈,二叉树,堆等。快速排序非递归的方法则可以通过栈来实现。
我之前写的关于快速排序递归方法的讲解:
https://mp.csdn.net/mp_blog/creation/editor/123786370
关于栈的基本操作:
typedef int STDataType;
typedef struct Stack
{
STDataType* _a;
int _top; // 栈顶
int _capacity; // 容量
}Stack;
void StackInit(Stack* ps) {
ps->_a = (STDataType*)malloc(sizeof(STDataType) * 3);
ps->_top = 0;
ps->_capacity = 3;
}
//检查栈是否还有空间
void CheckCapacity(Stack* ps) {
if (ps->_capacity == ps->_top) {
int newcapacity = ps->_capacity * 2;
STDataType* temp = (STDataType*)malloc(newcapacity * sizeof(STDataType));
if (NULL == temp) {
return;
}
memcpy(temp, ps->_a, sizeof(STDataType) * ps->_capacity);
free(ps->_a);
ps->_a = temp;
}
}
// 检测栈是否为空,如果为空返回非零结果,如果不为空返回0
int StackEmpty(Stack* ps) {
assert(ps);
if (ps->_top == 0) {
return 1;
}
return 0;
}
// 入栈
void StackPush(Stack* ps, STDataType data) {
CheckCapacity(ps);
ps->_a[ps->_top] = data;
ps->_top++;
}
// 出栈
void StackPop(Stack* ps) {
if (StackEmpty(ps))
return;
ps->_top--;
}
// 获取栈顶元素
STDataType StackTop(Stack* ps) {
if (StackEmpty(ps))
return 0;
return ps->_a [ps->_top - 1];
}
根据之前将过的,快速排序的三种方法:
// 快速排序hoare版本
int PartSort1(int* a, int left, int right) {
int begin = left;
int end = right-1;
int key = a[left];//关键字的取值为a[dir]即a[begin],最左侧的元素
while (begin < end) {
while (begin<end&&a[end] >= key) {
end--;
}
while (begin<end&&a[begin] <=key) {
begin++;
}
if (begin != end) {
int temp = a[begin];
a[begin] = a[end];
a[end] = temp;
}
}
int tem = a[begin];
a[begin] = a[left];
a[left]= tem;
return begin;//返回关键字的下标
}
// 快速排序挖坑法
int PartSort2(int* a, int left, int right) {
int begin = left;
int end = right-1;
int key = a[left];
while (begin < end) {
while (begin < end && a[end] >= key) {
end--;
}
if (begin < end) {
a[begin] = a[end];
begin++;
}
while (begin < end && a[begin] <= key)
begin++;
if (begin < end) {
a[end] = a[begin];
end--;
}
}
a[begin] = key;
return begin;
}
// 快速排序前后指针法,基准值取值为最右侧元素
int PartSort3(int* a, int left, int right) {
int cur = left;
int prev = cur - 1;
int key = a[right-1];
while (cur < right) {
if (a[cur] < key && ++prev != cur) {
int temp = a[cur];
a[cur] = a[prev];
a[prev] = temp;
}
cur++;
}
if (++prev != right - 1) {
int temp = a[prev];
a[prev] = a[right-1];
a[right-1] = temp;
}
return prev;
}
下面是具体实现快速排序非递归的代码:
void QuickSortNonR(int* a, int left, int right) {
Stack st;
StackInit(&st);
StackPush(&st, left);
StackPush(&st, right-1);
while (StackEmpty(&st)!=1) {
int _end = StackTop(&st);
StackPop(&st);
int _begin = StackTop(&st);
StackPop(&st);
int div = PartSort1(a, _begin, _end+1);
if (_begin < div ) {
StackPush(&st, _begin);
StackPush(&st, div);
}
if (div + 1 < _end) {
StackPush(&st, div + 1);
StackPush(&st, _end);
}
}
}
使用时直接调用即可,举例:
void main() {
int a[] = {5,6,4,3,7,2,8,1,9,0};
int n = sizeof(a) / sizeof(a[0]);
QuickSortNonR(a, 0, n );
//打印排序好的数组
for (int i = 0; i < n; i++) {
printf("%d ", a[i]);
}
printf("\n");
}