//传统递归方法实现
void swap(int *a , int *b)
{
int temp = *a;
*a = *b;
*b = temp;
}
//划分函数
int partition(int *arr , int left, int right)
{
int key = arr[left];
while(left<right){
while(arr[left]< key && left<right){
left++;
}
swap(&arr[left] , &key);
while(arr[right]> key && left<right){
right--;
}
swap(&arr[right] , &key);
}
return left;
}
// 递归左右子序列。
void quickSort(int *arr , int left , int right)
{
if(left<right){
int mid = partition(arr , left , right);
quickSort(arr , left , mid-1);
quickSort(arr , mid+1 , right);
}
}
/*
* 二叉树先根遍历 , 递归实现, 是不是和上面快速排序中的递归结构一样?
*/
void preOrder(BiTree T)
{
if(T!=NULL){
display(T->left);
printf(" %d",T->data);
display(T->right);
}
}
二叉树先根遍历,非递归实现。 使用一个栈消除 递归
void preOrder2(BiTree T)
{
printf("T->left->left->left=%p \n",T->left->left->left);
BiTree stack[100]={NULL};
int top = -1;
BiTree p = T;
stack[++top] = p;
p=p->left;
/*
注意这的条件,栈不为空 或者 p不为空。遍历中右转操作时,p为空。完成根和根的左子树遍历后,栈为空,但p指向右子树。
故而是 “或” 的关系,许多教科书在这里出错
*/
while(top>-1 || p!=NULL){
if(p != NULL)
{
printf(" %d " , p->data); //对节点操作函数, 这里直接输出, 在快排序中调用划分函数
stack[++top] = p;
//printf("push %d\n",p->data);
p = p->left; // 左下走到底
}
else{
p = stack[top--];
//printf("pop");
p = p->right; //右转
}
}
}
通过模仿二叉树的非递归遍历,可以非常轻松的写出快速排序非递归算法
栈元素的结构(需要入栈并回溯的信息)
#include<stdio.h>
typedef struct {
int left;
int right;
}Node;
int arr[] = {1,5,3,7,4,9,0};
int part(int left ,int right)
{
int key = arr[left];
while(left<right)
{
while(left<right && arr[right]>key)
{
right--;
}
arr[left] = arr[right];
while(left<right && arr[left]<key)
{
left++;
}
arr[right] = arr[left];
}//end while
arr[left] = key;
return left;
}
void Sort2(int left ,int right)
{
if(left<right)
{
int mid = part(left , right);
Sort2(left ,mid-1);
Sort2(mid+1,right);
}
}
void Sort()
{
Node stack[7];
int top = 0;
int mid;
Node node; //当前指针
node.left = 0;
node.right = 6;
while(top>-1 || node.left<node.right){
if(node.left < node.right)
{
stack[top++] = node;
mid = part(node.left ,node.right);
node.right = mid-1;
}
else
{
node = stack[--top];
node.left = mid+1;
}
} //end while
}
int main()
{
int i;
for(i=0;i<7;i++)
{
printf(" %d " , arr[i]);
}
//Sort2(0 , 6);
Sort();
// -------output the result of QuickSort
printf("\n\n==================\n\n");
for(i=0;i<7;i++)
{
printf(" %d " , arr[i]);
}
getchar();
return 0;
}
研究非递归快速排序的意义: 直观的学习 其空间复杂度为 log n 即辅助栈最大深度, 学习递归结构消解,掌握nlog n 时间复杂度内排序的根本原理
人工控制栈的增长。对大量数据排序,栈空间分配可以人工控制,而不是被动的依靠OS。
进一步尝试, 合并排序的非递归实现。即利用二叉树后根(后序)遍历非递归实现。
以上代码均在 gcc4.2 ub |