快速排序 递归转非递归

265 篇文章 1 订阅
120 篇文章 1 订阅

递归程序巧妙地完成了回溯,那么如何将递归程序转换成非递归呢?

一般来说,递归的时候一定要分清哪些是可以直接由顶进行到底的(不需要回溯,即手头可以处理好的事件),哪些是需要回溯的(这部分可能根据回溯的顺序来排回溯的优先级,需要标注不同的状态,即待办事件),贴网上某人的博文,觉得总结的非常好。

通用法则为:

以下是如何把快速排序由递归程序转换为非递归程序:

递归的版本为:

 

void quicksort1(int a[],int l,int r)
{//标准版
     int i=l,j=r,mid=a[(i+j)/2];
     while(i<=j){
           
           while(a[i]>mid) i++;
           while(a[j]<mid) j--;
           if(i<=j){
                 swap(a[i],a[j]);
                 i++;j--;                 
           }
     }  
     if( i<r )  quicksort1(a,i,r);
     if( j>l )  quicksort1(a,l,j); 
}


一般来说,再次调用递归存在向栈push元素的可能,但并不是绝对的。。。要弄清当前事情全部处理完,就要回溯,会从栈顶取,因此区分当前事情是否处理完特别重要。。。贴一个错误的代码:

 

 

void quicksort2(int a[],int l,int r)
{//错误版本 
	 stack<sValue> s;
	 sValue sv;
	 sv.first=l;
	 sv.second=r;
	 s.push(sv);
	 while(!s.empty()){
	 	sv=s.top();
	 	s.pop();
	 	int i=sv.first,j=sv.second,mid=a[(i+j)/2];
	    while(i<=j){
	           
           while(a[i]>mid) i++;
           while(a[j]<mid) j--;
           if(i<=j){
                 swap(a[i],a[j]);
                 i++;j--;                 
           }
	    }  	 
		if(i<r){
		   sv.first=i; sv.second=r; s.push(sv);
		}
		if(j>l){
		   sv.first=l; sv.second=j; s.push(sv);
		}
		
	 }
}


再上一个正确的代码:

void quicksort3(int a[],int l,int r)
{
     int i,j,mid;
	 stack<sValue> s;
	 sValue sv;
	 while(l<r||!s.empty()){
		 
		 while(l<r){
			 i=l;j=r;mid=a[(i+j)/2];
			 while(i<=j){          
				   while(a[i]>mid) i++;
				   while(a[j]<mid) j--;
				   if(i<=j){
						 swap(a[i],a[j]);
						 i++;j--;                 
				   }
			 }  	
			 			 	
			 if(j>l){
				   sv.first=l; sv.second=j; s.push(sv);
			 }
			 l=i; r=r;

		 }
		 if(!s.empty()){
		 	 sv=s.top();
		 	 s.pop();
		 	 l=sv.first;  r=sv.second;	 
		 }
	 }
}

用Python可以写一个更简洁的版本:

from itertools import  permutations

def partition(a, l, r):
    i, j = l, r
    pivot = a[(i+j)//2]
    while (i <= j): #Ensure i, j are not at the same position after partition, so i <=j instead of i <j
        while (a[i] < pivot):
            i = i + 1
        while (a[j] > pivot):
            j = j - 1
        if (i <= j):
            a[i], a[j] = a[j], a[i]
            i, j = (i + 1), (j - 1)
    return i, j

def q1(a, l, r):
    i, j = partition(a, l, r)
    if (i < r):
        q1(a, i, r)
    if (j > l):
        q1(a, l, j)
    return a

def q2(a, l, r):
    stack = []
    while (stack or l < r):
        while (l < r):
            i, j = partition(a, l, r)
            if (j > l):
                stack.append({'left':l, 'right':j})
            l, r = i, r

        if (stack):
            top = stack.pop()
            l, r = top['left'], top['right']
    return a


for perm in permutations([1,2,3,3,4,5,6], 7):
    y = q2(list(perm), 0, 6)
    print(y)

 

 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值