栈与递归的实现

  对于栈有些问题还不是很熟悉,所以暂时需要些时间去理解,需要多写些代码去体会,,栈还有一个重要应用是在程序设计语言中实现递归,所以这次主要是讲递归的实现,大家熟悉的阶乘函数,2阶Fibonacci数列和Ackerman函数等,其次还有的数据结构,如二叉树、广义表等,由于结构本身固有的递归特性,则它们的操作可递归的描述,另外还有一类问题,虽然问题本身没有明显的递归结构,但是递归求解比迭代求解更简单,如八皇后问题、Hanoi塔问题等。

  递归是一种数学上分而治之的思想,它将大型复杂问题转化为与原问题相同但规模较小的问题进行处理,数学表示如下:

      

  下面我以一个八皇后问题来说一下这儿的递归问题,在一个8X8国际象棋中,有8个皇后,每个皇后占一格,要求皇后间不会出现相互“攻击”的现象,即不能有两个皇后处在同一行,同一列或者同一对角线上。那么怎么来实现这个想法呢?下面是我的算法思路:先给两个了、变量i,j赋值为1,从第i行开始,恢复j的当前值,判断第j个位置。1、位置j可放入皇后,标记位置(i,j),i++,j = 1; 2、位置j不可放入皇后,j++,i = 1;  3、当j>8时候,j--,继续上述循环; 4、第八行有位置可以放入皇后。

  实现代码如下:

 1 #include <stdio.h>
 2 #define N 8
 3
 4 typedef struct _tag_Pos
 5 {
 6     int ios;
 7     int jos;
 8 } Pos;
 9
10 static char board[N+2][N+2];
11 static Pos pos[] = { {-1, -1}, {-1, 0}, {-1, 1} };
12 static int count = 0;
13
14 void init()
15 {
16     int i = 0;
17     int j = 0;
18     for(i=0; i<N+2; i++)
19     {
20         board[0][i] = ‘#‘;
21         board[N+1][i] = ‘#‘;
22         board[i][0] = ‘#‘;
23         board[i][N+1] = ‘#‘;
24     }
25     for(i=1; i<=N; i++)
26     {
27         for(j=1; j<=N; j++)
28         {
29             board[i][j] = ‘ ‘;
30         }
31     }
32 }
33
34 void display()
35 {
36     int i = 0;
37     int j = 1;
38     for(i=0; i<N+2; i++)
39     {
40         for(j=0; j<N+2; j++)
41         {
42             printf("%c", board[i][j]);
43         }
44         printf("\n");
45     }
46 }
47
48 int check(int i, int j)
49 {
50     int ret = 1;
51     int p = 0;
52     for(p=0; p<3; p++)
53     {
54         int ni = i;
55         int nj = j;
56         while( ret && (board[ni][nj] != ‘#‘) )
57         {
58             ni = ni + pos[p].ios;
59             nj = nj + pos[p].jos;
60             ret = ret && (board[ni][nj] != ‘*‘);
61         }
62     }
63
64     return ret;
65 }
66
67 void find(int i)
68 {
69     int j = 0;
70     if( i > N )
71     {
72         count++;
73         printf("Solution: %d\n", count);
74         display();
75         getchar();
76     }
77     else
78     {
79         for(j=1; j<=N; j++)
80         {
81             if( check(i, j) )
82             {
83                 board[i][j] = ‘*‘;
84                 find(i+1);
85                 board[i][j] = ‘ ‘;
86             }
87         }
88     }
89 }
90
91 int main()
92 {
93     init();
94     find(1);
95
96     return 0;
97 }

queen

  编译结果如下图:

当不断按Enter的时候,会陆续出现Solution一直到Solutioin92,再按Enter会退出了。如下图

小结:

  递归是一种将问题分而治之的思想,解决问题的时候首先就要建立递归的模型;

  如上图到Solution92的时候就结束了,所以解决递归问题首先要有边界条件,否则将死循环;

时间: 2024-10-12 00:41:34

栈与递归的实现的相关文章

java栈和递归的关系

最近看了Mark.Allen.Weiss的算法与数据结构,看到了里面讲述的表.栈和和队列,结合最近工程用的比较多的递归运算.所以这里讲一下递归 因为在年初的时候看了<大话数据结果>(推荐看一下),这里先讲一下概念:函数的递归调用和普通函数调用是一样的,当程序执行到某个函数时,将这个函数进行入栈操作,入栈之前主要做三件事 1.把入参,返回地址等返回给被调用函数保存 2.分配栈空间 3.准备被调用 出栈也一样: 1.保存运算结果 2.消除栈空间 3.把运算结果放到栈空间出口 所以递归这种存储某些数

算法9---二叉树的遍历不用栈和递归

二叉树的遍历不用栈和递归 转自:ACM之家 http://www.acmerblog.com/inorder-tree-traversal-without-recursion-and-without-stack-5988.html 我们知道,在深度搜索遍历的过程中,之所以要用递归或者是用非递归的栈方式,参考二叉树非递归中序遍历,都是因为其他的方式没法记录当前节点的parent,而如果在每个节点的结构里面加个parent 分量显然是不现实的,那么Morris是怎么解决这一问题的呢?好吧,他用得很巧

深度优先搜索入门:POJ1164城堡问题(递归、用栈模拟递归)

将问题的各状态之间的转移关系描述为一个图,则深度优先搜索遍历整个图的框架为:Dfs(v) {if( v 访问过)return;将v标记为访问过;对和v相邻的每个点u: Dfs(u);}int main() {while(在图中能找到未访问过的点 k) Dfs(k);} 例题: POJ1164 The Castle Description 1 2 3 4 5 6 7 ############################# 1 # | # | # | | # #####---#####---#-

15、蛤蟆的数据结构笔记之十五栈的应用之栈与递归之八皇后问题

15.蛤蟆的数据结构笔记之十五栈的应用之栈与递归之八皇后问题 本篇名言:"人的一生应当这样度过:当回忆往事的时候,他不致于因为虚度年华而痛悔,也不致于因为过去的碌碌无为而羞愧:在临死的时候,他能够说:"我的整个生命和全部精力,都已经献给世界上最壮丽的事业--为人类的解放而斗争." 继续递归问题,本次是经典的八皇后问题: 欢迎转载,转载请标明出处: 1.  八皇后问题 八皇后问题,是一个古老而著名的问题,是回溯算法的典型案例.该问题是国际西洋棋棋手马克斯·贝瑟尔于1848年提出

14、蛤蟆的数据结构笔记之十四栈的应用之栈与递归之阿克曼函数

14.蛤蟆的数据结构笔记之十四栈的应用之栈与递归之阿克曼函数 本篇名言:"今天就是生命 ----- 是唯一你能确知的生命." 继续递归应用,阿克曼函数. 欢迎转载,转载请标明出处: 1.  阿克曼函数 阿克曼函数(Ackermann)是非原始递归函数的例子.它需要两个自然数作为输入值,输出一个自然数.它的输出值增长速度非常高,仅是对于(4,3)的输出已大得不能准确计算. Ackermann函数定义如下: 若m=0,返回n+1. 若m>0且n=0,返回Ackermann(m-1,1

13、蛤蟆的数据结构笔记之十三栈的应用之栈与递归之斐波那契数列

13.蛤蟆的数据结构笔记之十三栈的应用之栈与递归之斐波那契数列 本篇名言:"人生不是一支短短的蜡烛,而是一支由我们暂时拿着的火炬,我们一定要把它燃得." 继续递归的斐波那契数列问题. 欢迎转载,转载请标明出处: 1.  斐波那契数列 斐波那契数列,又称黄金分割数列,指的是这样一个数列:0.1.1.2.3.5.8.13.21.--在数学上,斐波纳契数列以如下被以递归的方法定义:F(0)=0,F(1)=1,F(n)=F(n-1)+F(n-2)(n≥2,n∈N*)在现代物理.准晶体结构.化学

16、蛤蟆的数据结构笔记之十六栈的应用之栈与递归之汉诺塔问题

16.蛤蟆的数据结构笔记之十六栈的应用之栈与递归之汉诺塔问题 本篇名言:"人生的价值,并不是用时间,而是用深度去衡量的." 继续栈与递归应用,汉诺塔问题. 欢迎转载,转载请标明出处: 1.  汉诺塔问题 汉诺塔:汉诺塔(又称河内塔)问题是源于印度一个古老传说的益智玩具.大梵天创造世界的时候做了三根金刚石柱子,在一根柱子上从下往上按照大小顺序摞着64片黄金圆盘.大梵天命令婆罗门把圆盘从下面开始按大小顺序重新摆放在另一根柱子上.并且规定,在小圆盘上不能放大圆盘,在三根柱子之间一次只能移动一

汉诺塔(Tower of Hanoi)问题的求解——利用栈与递归

汉诺塔(Tower of Hanoi)问题的求解--利用栈与递归 1. 汉诺塔问题的提法 汉诺塔问题是使用递归解决问题的经典范例. 传说婆罗门庙里有一个塔台,台上有3根标号为A.B.C的用钻石做成的柱子,在A柱上放着64个金盘,每一个都比下面的略小一点.把A柱上的金盘全部移到C柱上的那一天就是世界末日. 移动的条件是:一次只能移动一个金盘,移动过程中大金盘不能放在小金盘上面.庙里的僧人一直在移个不停,移动的最少总次数是264?1次,如果每秒移动一次的话,需要500亿年. 2. 求解汉诺塔问题的算

栈与递归

今天说的是栈与递归的关系,函数的递归调用和普通函数调用是一样的.当程序执行到某个函数时,将这个函数进行入栈操作,在入栈之前,通常需要完成三件事. 1.将所有的实参.返回地址等信息传递给被调函数保存.(输入参数和标记返回值地址) 2.为被调函数的局部变量分配存储区.(分配局部变量地址空间) 3.将控制转移到北调函数入口.(给予控制权) 当一个函数完成之后会进行出栈操作,出栈之前同样要完成三件事. 1.保存被调函数的计算结果.(返回值) 2.释放被调函数的数据区.(释放局部变量地址空间) 3.依照被

3.4.4 利用栈将递归转换成非递归的方法

在函数执行时系统需要设立一个“递归工作栈”存储第一层递归所需的信息,此工作栈是递归函数执行的辅助空间,所以可以看出,递归程序在执行时需要系统提供隐式栈这种数据结构来实现,对于一般的递归过程,仿照递归算法执行过程中递归工作栈的状态变化可直接写出相应的非递归算法.这种利用栈消除递归过程的步骤如下. (1)设置一个工作栈存放递归工作记录(包括实参.返回地址及局部变量等) (2)进入非递归调用入口(即被调用程序开始处)将调用程序传来的实在参数和返回地址入栈(递归程序不可以作为主程序,因而可认为初始是被某