C++易忽略点学习递归函数的调用超清晰分析(二)
来源:互联网 发布:学历网络教育报考时间 编辑:程序博客网 时间:2024/04/30 03:00
递归函数学习。
窃以为,在我接触的C语言程序中,递归函数是最复杂的。递归函数看似简单,通过函数自身调用实现无限光明的功能,但是往往调试起来,错误百出,而且在某一环稍微出错,结果千差万别,因此,在写递归函数时,思路必须十分清晰,否则,中枪的肯定是你!
被誉为“算法圣经”的Introduction to Algorithms, Thomas H. Cormen中第二章讲述了归并排序的函数,是使用递归函数的经典例子。看完该例后,我跃跃欲试想把它用C语言实现。该书中,所有的数组都是A[1...n],是从下标为1开始的。
1、假设A[p...q], A[q+1...r]是两个分别排好序的数组,进行合并即可得排好序的A[p...r].
2、使用递归函数的归并排序:
使用这两个函数,就能实现复杂度为O(nlgn)的排序。
具体步骤如下:
算法的描述非常清晰,我本想实现之应该很轻松,但是结果让我大为惊讶,竟然调试了两个多小时之久。
下面描述我的做法:
1、写好程序整个框架。
做算法和写程序是完全的两码事,光会算法还不足以产生生产力,它只解决了理论上的问题,要把它付之实现还有很长的路要走。所以必须先写好程序的框架,如如何从文件中输入整型数组,如何实现算法中的∞。
输入整型数组的问题在写insert_sort.c(插入排序)时就已经研究出来了(见2013.4.15 1、求整形数组的长度),而∞的表示该如何呢,记得最近在看的一本书The Standard C Library,P.J.Plauger中讲解了<limits.h>的使用,有一个INT_MAX的宏定义,其含义为整型变量的最大值。可以使用这个宏来代替∞。
2、实现merge_sort(),merge()函数。
由于算法导论中描述的算法中数组的小标均是从1开始,所以用C实现必须考虑下标的问题。
下面后面备注了change的说明某些值和原算法中有1的改变。
void merge(int *A, int p, int q, int r)
{
int n, m;
int i, j;
int L[SIZE], R[SIZE];
static int k;
n = q - p + 1;
m = r - q;
for(i=0; i< n; i++)//change
L[i] = A[p+i];//change
for(j=0; j<m; j++)
R[j] = A[q+j+1];//change
L[n] = INT_MAX;
R[m] = INT_MAX;
i = 0;
j = 0;
for(k=p; k<r+1; k++)
{
if(L[i]<R[j])
{
A[k] = L[i];
i ++;
}
else
{
A[k] = R[j];
j ++;
}
}
};
void merge_sort(int *A, int p, int r)
{
int q;
if(p<r)
{
q = (p+r)/2;
merge_sort(A, p, q);
merge_sort(A, q+1, r);
merge(A, p, q, r);
}
};
3、调试
上面的代码时调试正确后的表示。开始有一处有问题,但是隐藏的较深,我仔细分析了整个递归函数的过程才发现问题所在。
在merge_sort()中,我这样定义q,
static int q = 0;
结果导致了每次调用merge_sort()都会定义一次q=0,然而我曾经看过一本书,书上写道
static int n = 0
只会定义一次n,可是这里竟然出现了问题。static这个问题下次一定要解决!!
虽然将代码改为
int q;
即可。但是为了找到这个隐藏的错误我花了近两个小时的时间,可见Debug是一门很深的学问。值得欣慰的是,我首先写框架时就将代码测试了一遍,所以我可以迅速锁定错误是merge_sort()和merge(),首先将下标问题解决了,但是还是出现了错误,我又画了一张递归函数调用的步骤图,
第一次如此清晰的描述递归函数的过程,原来抽象的递归函数现在十分的具体了。我按照这些步骤一步一步调试代码,终于找出了q这个值的问题,因为在第2步时,q应为1,但是它显示为0,所以我就怀疑是初始化的问题,结果还真是。务必记住:千万不要在递归函数中初始化值为0,除非它每次都必须是0,不然每次调用时都会把它初始化为0,这不是我们的初衷。
- C++易忽略点学习递归函数的调用超清晰分析(二)
- 函数的递归调用二
- C语言函数的递归和调用实例分析
- C函数的调用-----递归调用
- C代码分析器(二)单文件函数调用分析
- C语言实现:函数的递归调用
- C++:函数的递归调用相关
- C语言函数的递归和调用
- C语言函数的递归调用
- C语言函数的递归调用
- C语言下的函数递归调用
- C语言函数的递归调用
- C语言的函数,还有递归调用
- C语言函数的递归调用
- c语言:函数的递归调用
- 78 C语言函数的递归调用
- C语言函数的递归调用
- c语言:函数的递归调用
- 【11】Delete a node in the middle of a single linked list
- mfc工具条上简单添加下拉框
- 请求发送者与接收者解耦——命令模式(四)
- 第18天的交易(2013-4-15)(+100) (2763.4) (疯狂的一天)
- POJ 并查集 题目汇总 ——czyuan原创
- C++易忽略点学习递归函数的调用超清晰分析(二)
- hdu 1711 (Number Sequence)
- Ubuntu 下UFW防火墙简单设置攻略
- 6行代码抓取网页
- 多线程6:线程封闭与ThreadLocal
- The Logger in Java and Android
- JSP,servlet容器,Tomcat,servlet容器之间的关系
- 黑马程序员-分散的知识点
- 【昊昊带你学】算法概述