当前位置:C++技术网 > 资讯 > 关于递归在快速排序中的应用疑问

关于递归在快速排序中的应用疑问

更新时间:2017-06-23 23:41:03浏览次数:1+次


不好意思,不知道怎么上传代码,就用了图片形式


首先问一个问题,在主函数中只要出现low和high的地方,都是low=0,high=5吗

在问一下程序执行顺序的问题

1 首先low=0,high=5,所以0<5成立,先执行第28行,执行后pos=0,然后执行第29行

2 第29行调用第quicksort函数,此时low=0,high=pos-1=-1,因为0<-1不成立,所以29行的函数调用语句结束,转而去执行第30行函数调用语句

3 执行第30行又去调用quicksort函数,此时low=pos+1=1,high=5,因为1<5成立,所以转而再去执行第28行(此时还在30     行的范围内?),执行第28行后pos=3,再去执行第29行,第29行又去调用quicksort函数,此时low=0,high=pos-1=2,因   为0<2成立,所以再执行第28行,执行之后pos=0,再去执行第29行(再次调用quicksort函数)此时low=0,high=pos-   1=-1,因为0<-1不成立,所以再转而去执行第30行,此时又变成了low=pos+1=1,high=5了。    所以到这就糊涂了,怎么  又回去了,不知道哪一步出错了,所以希望您能解惑一下,谢谢



C++技术网会员解答:

    您好,感谢你对C++技术网的支持与信任。

    通过了解,知道你的疑问是什么了,即对于递归的思想和程序执行逻辑不了解。下面为您解答。

    首先来说说递归的思想原理。

    所谓递归,也就是函数自己调用自己。我用一个通俗的例子来解释一下。你说这么一句话:“如果我被自己随机打一拳,如果打到了左脸,就不再继续打,如果打到了右脸就继续再重复这一句话,也就是再随机打一拳。”

    所以,你脑子一下,然后就打了自己一拳。开始也没有想打哪一边脸,就随手打了一拳,结果打到了右脸。然后想想前面说的那句话。既然打中了右脸,就需要继续重复这个动作,随机打一拳。而这一拳要和前面一样的心态打,要随机。如果你一直打右脸,最后就会一直打下去,停不下来。而只要中间有一次打了左脸,就停下来了。

    你说的这句话,就相当于执行一个函数,在执行的过程中,如果条件满足,就继续在这个函数里面在执行一遍。下面来看一个示意图:

关于递归在快速排序中的应用疑问

    当函数执行到一个函数调用的时候,执行的流程就跑到被调用的函数里面,也就是示意图上往下执行了一层。只不过递归执行的函数调用都是自己。所以,如果函数内条件判断都满足继续执行,那么就会一层层的执行下去,停不下来。这就是死递归。最开始的例子就是不停的打右脸。但是如果任何一层的执行,让条件判断不满足,那么这层的函数执行也就完毕了,那么函数就返回到上一层的调用中,也就表示上一层的调用这个函数的执行完毕,流程继续完后走,函数也就执行完了。这样就可以一层层的退出到最开始执行函数的最外层,最后就执行完毕了。而例子中,如果其中有一次打到了左脸,也就表示本次的条件不再成立,不会继续进行下一次打脸。这样就终结了本次函数的执行,然后退回上一次的执行,执行结束。一层层回去,最终执行完毕。

    所以递归需要的一个非常重要的前提就是需要在函数内有一个终止判断条件,而且要确保这个条件会变化,才让判断在需要的时候可以不成立而让函数退出递归调用。

    那么在递归的过程中,我们调试时,会发现执行的过程反反复复的变来变去。这是因为你的代码只要一份,每一次递归调用函数自己,都会从函数最开头开始执行,一旦执行调用了自己,就会再次进入下一层的函数,又从函数开头执行。这个特点也恰好说明了是递归调用。我们在调试这个代码时,要非常清楚递归到第几层了,最好用笔记一下,很容易混乱。

    在main函数第一次调用quicksort函数,也就是第一次启动了最外层的函数执行。然后在quicksort函数里面,有一个条件判断,如果开始位置小于结尾位置,就进行递归调用。在递归调用之前,要查找一下本地的位置,然后一分为二,左边的按照同样的方法,再继续一分为二,右边的也用一分为二的方式继续执行。

    所以当quicksort函数进来后,发现判断条件不满足,说明上一层调用的时候,这个函数调用就执行完了。执行完说明这里不需要排序了。那剩余一边的需要继续用这种方式不断的排序。

    使用递归的原因就是因为,先从整体上将数组一分为二,然后再在两边都用一分为二的方式继续拆分。也就是说,我们一分为二的方式可以将左右两边不断以同样的方式细化拆分,直到所有的排序都是一个顺序(如从小到大),这样排序的一分为二就会结束。最后所有的排序就结束了。

    你对这个排序的不理解,一是因为对递归的特性不够熟悉,而是对于递归代码的执行过程和表现的现象不熟悉。不过递归确实会有点绕,需要多思考,多画画。

    而main函数里的quicksort函数需要指定要排序的数组的范围。如果你要全部排序,自然是0和5.如果你只想排序前面3个数字,你可以填写0和2。如果要排序后面两个,那么就是4和5。这里只是指定排序的范围而已。

    递归的过程,还要继续好好琢磨一下。