递归是一种数学上分而自治的思想
-将原问题分解为规模较小的问题进行处理
·分解后的问题与原问题的类型完全相同,单规模较小
·通过小规模问题的解,能够轻易求得原问题的解
-问题的分解是有限的(递归不能无限进行)
·当边界条件不满足时,分解问题(递归继续进行)
·当边界条件不满足时,直接求解(递归结束)
递归在程序设计中的应用
-递归函数
·函数体中存在自我调用的函数
·递归函数必须有递归出口(边界条件)
·函数的无限递归将导致程序崩溃
递归思想的应用
-求解:Sum(n) = 1 + 2 + 3 + ... + n
unsigned int sum(unsigned int n)
{
if( n > 1 )
{
return n + sum(n - 1);
}
else
{
return 1;
}
}
斐波拉契数列
-数列自身递归定义:1,1,2,3,5,8,13,21,...
unsigned int fac(unsigned int n)
{
if( n > 2 )
{
return fac(n - 1) + fac(n - 2);
}
if((n == 2) || (n == 1))
{
return 1;
}
return 0;
}
用递归的方法编写函数求字符串长度
unsigned int _strlen_(const char* s)
{
return s ? (*s ? (1 + _strlen_(s + 1)) : 0) : 0;
}
单项链表的转置
struct Node
{
int value;
Node* next;
};
Node* create_list(int v,int len)
{
Node* ret = NULL;
Node* slider = NULL;
for(int i = 0;i < len ; i++)
{
Node* n = new Node();
n->value = v++;
n->next = NULL;
if(slider == NULL)
{
slider = n;
ret = n;
}
else
{
slider->next = n;
slider = n;
}
}
return ret;
}
void destroy_list(Node* list)
{
while(list)
{
Node* del = list;
list = list->next;
delete del;
}
}
void print_list(Node* list)
{
while(list)
{
cout << list->value << "->";
list = list->next;
}
cout << "NULL" << endl;
}
Node* reverse(Node* list)
{
if( (list == NULL) || (list->next == NULL))
{
return list;
}
else
{
Node* guard = list->next;
Node* ret = reverse(list->next);
guard->next = list;
list->next = NULL;
return ret;
}
}
单向排序链表的合并
Node* merge(Node* list1,Node* list2)
{
if(list1 == NULL)
{
return list2;
}
else if(list2 == NULL)
{
return list1;
}
else if(list1->value < list2->value)
{
return (list1->next = merge(list1->next,list2),list1);
}
else
{
return (list2->next = merge(list1,list2->next),list2);
}
}
汉诺塔问题
-将木块借助B柱由A柱移动到C柱
-每次只能移动一个木块
-只能出现小木块在大木块之上
void HanoiTower(int n,char a,char b,char c)
{
if(n == 1)
{
cout << a << "-->" << c << endl;
}
else
{
HanoiTower(n - 1,a,c,b);
HanoiTower(1,a,b,c);
HanoiTower(n-1,b,a,c);
}
}
全排列问题
void permutation(char* s,char* e)
{
if(*s == '\0')
{
cout << e << endl;
}
else
{
int len = strlen(s);
for(int i = 0;i < len;i++)
{
if( ( i == 0) || (s[0] != s[i]))
{
swap(s[0],s[i]);
permutation(s+1,e);
swap(s[0],s[i]);
}
}
}
}
函数调用过程回顾
-程序运行后有一个特殊的内存区供函数调用
·用于保存函数中的实参,局部变量,临时变量,等
·从开始地址开始往一个方向增长(如:高地址==>底地址)
·有一个专用的“指针”,表示当前已使用内存的“顶部”
void r_print_even(Node* list)
{
if(list != NULL)
{
r_print_even(list->next);
if((list->value % 2) == 0)
{
cout << list->value << endl;
}
}
}
八皇后问题
template <int SIZE>
class QueueSolution : public Object
{
protected:
enum { N = SIZE + 2};
struct Pos : public Object
{
Pos(int px = 0,int py = 0) : x(px),y(py){}
int x;
int y;
};
int m_chessboard[N][N];
Pos m_direction[3];
LinkList<Pos> m_solution;
int m_count;
void init()
{
m_count = 0;
for(int i = 0; i<N; i +=(N-1))
{
for(int j = 0;j<N;j++)
{
m_chessboard[i][j] = 2;
m_chessboard[j][i] = 2;
}
}
for(int i =1;i<=SIZE;i++)
{
for(int j = 1;j<=SIZE;j++)
{
m_chessboard[i][j] = 0;
}
}
m_direction[0].x = -1;
m_direction[0].y = -1;
m_direction[1].x = 0;
m_direction[1].y = -1;
m_direction[2].x = 1;
m_direction[2].y = -1;
}
void print()
{
for(m_solution.move(0); !m_solution.end();m_solution.next())
{
cout << "(" << m_solution.current().x << ", " << m_solution.current().y<<") ";
}
cout << endl;
for(int i = 0;i<N;i++)
{
for(int j = 0;j<N;j++)
{
switch(m_chessboard[i][j])
{
case 0:cout << " " ;break;
case 1: cout << " #" ;break;
case 2:cout << " *" ;break;
}
}
cout << endl;
}
cout << endl;
}
bool check(int x,int y,int d)
{
bool flag = true;
do
{
x += m_direction[d].x;
y += m_direction[d].y;
flag = flag && (m_chessboard[x][y] == 0);
//cout << flag;
}
while(flag);
return (m_chessboard[x][y] == 2);
}
void run(int j)
{
if(j <= SIZE)
{
for(int i = 1;i<=SIZE;i++)
{
if(check(i,j,0) && check(i,j,1) && check(i,j,2))
{
m_chessboard[i][j] = 1;
m_solution.insert(Pos(i,j));
run(j + 1);
m_chessboard[i][j] = 0;
m_solution.remove(m_solution.length() - 1);
}
}
}
else
{
m_count++;
print();
}
}
public:
QueueSolution()
{
init();
}
void run()
{
run(1);
cout << "Total : " << m_count <<endl;
}
};
总结:
-程序运行后的栈存储区专供函数调用使用
-栈存储区用于保存实参,局部变量,临时变量,等
-利用栈存储区能够方便的实现回溯算法