456数据结构C语言版_递归求解迷宫问题

456数据结构C语言版_递归求解迷宫问题
456数据结构C语言版_递归求解迷宫问题

#include

// 迷宫坐标位置类型

struct PosType

{

int x; // 行值

int y; // 列值

};

#define MAXLENGTH 25 // 设迷宫的最大行列为25

typedef int MazeType[MAXLENGTH][MAXLENGTH]; // [行][列]

// 全局变量

struct PosType end; // 迷宫终点位置

MazeType m; // 迷宫数组

int x, y; // 迷宫行数,列数

// 定义墙元素值为0,可通过路径为-1,通过路径为足迹

// 输出解

void Print(int x,int y)

{

int i,j;

for(i=0;i

{

for(j=0;j

printf("%3d",m[i][j]);

printf("\n");

}

printf("\n");

}

// 由当前位置cur、当前步骤curstep试探下一点

void Try(struct PosType cur,int curstep)

{

int i;

struct PosType next; // 下一个位置

// {行增量,列增量}

struct PosType direc[4]={{0,1},{1,0},{0,-1},{-1,0}};

// 移动方向,依次为东南西北

for(i=0;i<=3;i++) // 依次试探东南西北四个方向

{

next.x=cur.x+direc[i].x;

next.y=cur.y+direc[i].y;

if(m[next.x][next.y] == -1) // 是通路

{

m[next.x][next.y]=++curstep;

if(next.x != end.x || next.y != end.y) // 没到终点

Try(next,curstep); // 试探下一点(递归调用)

else

Print(x,y); // 输出结果

m[next.x][next.y]=-1; // 恢复为通路,试探下一条路

curstep--;

}

}

}

// 0为墙,-1为通道

int main()

{

struct PosType begin; //起点

int i,j,x1,y1;

printf("请输入迷宫的行数,列数(包括外墙):(空格隔开)");

scanf("%d%d",&x,&y);

for(i=0;i

{

m[0][i]=0; // 迷宫上面行的周边即上边墙

m[x-1][i]=0;// 迷宫下面行的周边即下边墙

}

for(j=1;j

{

m[j][0]=0; // 迷宫左边列的周边即左边墙

m[j][y-1]=0;// 迷宫右边列的周边即右边墙

}

for(i=1;i

for(j=1;j

m[i][j]=-1; // 定义通道初值为-1

printf("请输入迷宫内墙单元数(即墙的个数):");

scanf("%d",&j);

if(j)

printf("请依次输入迷宫内墙每个单元的行数,列数:(空格隔开)\n");

for(i=1;i<=j;i++)

{

scanf("%d%d",&x1,&y1);

m[x1][y1]=0;

}

printf("迷宫结构如下:\n");

Print(x,y);

printf("请输入起点的行数,列数:(空格隔开)");

scanf("%d%d",&begin.x,&begin.y);

printf("请输入终点的行数,列数:(空格隔开)");

scanf("%d%d",&end.x,&end.y);

m[begin.x][begin.y]=1;

Try(begin,1); // 由第一步起点试探起

system("pause");

return 0;

}

/*

输出效果:

请输入迷宫的行数,列数(包括外墙):(空格隔开)4 4 请输入迷宫内墙单元数(即墙的个数):1

请依次输入迷宫内墙每个单元的行数,列数:(空格隔开)1 2

迷宫结构如下:

0 0 0 0

0 -1 0 0

0 -1 -1 0

0 0 0 0

请输入起点的行数,列数:(空格隔开)1 1

请输入终点的行数,列数:(空格隔开)2 2

0 0 0 0

0 1 0 0

0 2 3 0

0 0 0 0

请按任意键继续. . .

*/

数据结构二叉树的递归算法实验报告

齐鲁工业大学实验报告成绩 课程名称数据结构指导教师单健芳实验日期 院(系)信息学院专业班级计科(嵌入)14-1 实验地点 学生姓名高晨悦学号 201403071007 同组人无 实验项目名称二叉树的递归算法 一、实验目的和要求 1.实现二叉树的先序,中序与后序遍历的递归算法与非递归算法。 2.求二叉树的结点个数,叶子结点个数,二叉树的高度,度为2的结点个数。 二、实验环境 微型计算机vc 6.0 三、实验内容 1.实现二叉树的先序,中序与后序遍历的递归算法与非递归算法。 2.求二叉树的结点个数,叶子结点个数,二叉树的高度,度为2的结点个数。 四、实验步骤 一.实验内容 1.实现二叉树的先序,中序与后序遍历的递归算法与非递归算法。 2.求二叉树的结点个数,叶子结点个数,二叉树的高度,度为2的结点个数。 二.程序的设计思想 1实现二叉树的先序,中序与后序遍历的递归算法与非递归算法。 先构造二叉树,根据先序遍历的思想,输入根后,再输入左子树,直至左子树为空则输入上一层右字树。 (1)二叉树的非递归遍历是用显示栈来存储二叉树的结点指针,先序遍历时,按二叉树前序遍历的顺序访问结点,并将结点的指针入栈,直到栈顶指针指向结点的左指针域为空时取出栈顶指针并删除栈顶指针,访问刚取出的指针指向的结点的右指针指向的结点并将其指针入栈,如此反复执行则为非递归操作。 (2)二叉树的递归遍历:若二叉树为空,则空操作 先序遍历: (a)访问根结点; (b)先序遍历左子树; (c)先序遍历右子树。

中序遍历: (a)中序遍历左子树; (b)访问根结点; (c)中序遍历右子树 后序遍历: (a)后序遍历左子树; (b)后序遍历右子树; (c)访问根结点。 2.求二叉树的结点个数,叶子结点个数,二叉树的高度,度为2的结点个数。 (1)求二叉树的叶子结点个数:先分别求得左右子树中个叶子结点的个数,再计算出两者之和即为二叉树的叶子结点数。 (2)二叉树的结点个数之和:先分别求得左子树右子树中结点之和,再计算两者之和即为所求。 (3)二叉树的高度:首先判断二叉树是否为空,若为空则此二叉树高度为0,。否则,就先分别求出左右子树的深度进行比较,取较大的树加一即为所求。 (4)二叉树的度为2的结点个数:计算有左右孩子的结点个数,即为度为2的结点个数。 三.编程过程中遇到的问题及解决办法 (1)后续遍历的非递归函数涉及到回溯的方法,开始设计的方案想的太过于简单,所以形成了死循环,总是在最后的节点处不停地循环,后改成回溯后,该问题得到解决。 (2)计算二叉树中度为2的结点个数中,返回循环的时候不论根结点有没有左右子树,但个人设计时,根总是会将自己默认为有左右子树,自行增加1.后在同学帮助下才看到自己的这个失误。 四.程序的闪光点(自我评价) 1.程序模块化,各个函数分开描述,方便观察 2.关键处有注释 3.建立二叉树时,用先序提示输入,比较人性化。 五.程序源代码(以文件为单位提供) #include #include #define Maxsize 100 typedef struct TREE{ struct TREE *lTree;

数据结构算法背诵版

数据结构算法背诵 一、线性表 1.逆转顺序表中的所有元素 算法思想:第一个元素和最后一个元素对调,第二个元素和倒数第二个元素对调,……,依此类推。 void Reverse(int A[], int n) { int i, t; for (i=0; i < n/2; i++) { t = A[i]; A[i] = A[n-i-1]; A[n-i-1] = t; } } 2.删除线性链表中数据域为 item的所有结点 算法思想:先从链表的第 2个结点开始,从前往后依次判断链表中的所有结点是否满足条件,若某个 结点的数据域为 item,则删除该结点。最后再回过头来判断链表中的第 1个结点是否满足条件,若 满足则将其删除。 void PurgeItem(LinkList &list) { LinkList p, q = list; p = list->next; while (p != NULL) { if (p->data == item) { q->next = p->next; free(p); p = q->next;

} else { q = p; p = p->next; } } if (list->data == item) { q = list; list = list->next; free(q); } }

3.逆转线性链表 void Reverse(LinkList &list) { LinkList p, q, r; p = list; q = NULL; while (p != NULL) { r = q; q = p; p = p->next; q->next = r; } list = q; } 4.复制线性链表(递归) LinkList Copy(LinkList lista) { LinkList listb; if (lista == NULL) return NULL; else { listb = (LinkList)malloc(sizeof(LNode)); listb->data = lista->data; listb->next = Copy(lista->next); return listb; } }

数据结构利用栈实现递归

利用栈实现递归参考程序1(Turbo2.0环境): #define MAXSIZE 100 #include struct stack{ int data[MAXSIZE]; int top; }; void init(struct stack *s){ s->top=-1; } int empty(struct stack *s){ if(s->top==-1) return 1; else return 0; } void push(struct stack *s,int i){ if(s->top==MAXSIZE-1){ printf("Stack is full\n"); return; } s->top++; s->data[s->top]=i; } int pop(struct stack *s){ if(empty(s)){ printf("stack is empty"); return -1; } return(s->data[s->top--]); } void trans(int num){ struct stack s; int k; init(&s); while(num){ k=num%16; push(&s,k); num=num/16; } while(!empty(&s)){ k=pop(&s); if(k<10)

printf("%d",k); else printf("%c",k+55); } printf("\n"); } main(){ int num; clrscr(); printf("Input a num,-1 to quit:\n"); scanf("%d",&num); while(num!=-1){ trans(num); scanf("%d",&num); } } 参考程序2:(C++/VC环境) #define STACK_INIT_SIZE 100//存储空间初始分配量 #define OVERFLOW -1 #define OK 1 #define STACKINCREMENT 10//存储空间分配增量 #define ERROR 0 #define TRUE 1 #define FALSE 0 #include "stdio.h" #include "stdlib.h" #include "malloc.h" #include "iostream.h" typedef int status; typedef char SElemType; typedef struct{//顺序栈的定义 SElemType *base; SElemType *top; int stacksize; }SqStack; status InitStack(SqStack &S){//构造一个空栈S S.base=(SElemType *)malloc(STACK_INIT_SIZE*sizeof(SElemType)); if(!S.base)exit(OVERFLOW);//存储分配失败 S.top=S.base; S.stacksize=STACK_INIT_SIZE; return OK; }

全国计算机二级考试 数据结构与算法

全国计算机二级考试 第一章数据结构与算法 1.一个算法一般都可以用_____、_____ 、 _____三种控制结构组合完成。 [解析]顺序、选择(分支)、循环(重复) 一个算法通常由两种基本要素组成:一是对数据对象的运算和操作,二是________。 [解析]算法的控制结构 在一般的计算机系统中,有算术运算、逻辑运算、关系运算和________四类基本的操作和运算。 [解析]数据传输 2.常用于解决“是否存在”或“有多少种可能”等类型的问题(例如求解不定方程的问题)的算法涉及基本方法是() A.列举法 B.归纳法 C.递归法 D.减半递推法 [解析]列举就是列举出所有可能性,将所有可能性统统列举出来,然后解决问题的方法。所以A 3.根据提出的问题,列举所有可能的情况,并用问题中给定的条件检验哪些是需要的,哪些是不需要的,这是算法设计基本方法中的____。 [解析]列举法

4.通过列举少量的特殊情况,经过分析,最后找出一般的关系的算法设计思想是() A.列举法 B.归纳法 C.递归法 D.减半递推法 [解析]B 5.在用二分法求解方程在一个闭区间的实根时,采用的算法设计技术是() A.列举法 B.归纳法 C.递归法 D.减半递推法 [解析]二分法就是从一半处比较,减半递推技术也称分治法,将问题减半。所以D 6.将一个复杂的问题归结为若干个简单的问题,然后将这些较简单的问题再归结为更简单的问题,这个过程可以一直做下去,直到最简单的问题为止,这是算法设计基本方法中的___。如果一个算法P显式地调用自己则称为___。如果算法P调用另一个算法Q,而算法Q又调用算法P,则称为_____. [解析]递归法直接递归间接递归调用 7.算法中各操作之间的执行顺序称为_____。描述算法的工具通常有_____、_____ 、 _____。 [解析]控制结构传统流程图、N-S结构化流程图、算法描述语言 8.从已知的初始条件出发,逐步推出所要求的各中间结果和最后结果,这

数据结构知识点整理

数据是信息的载体,是描述客观事物的数、字符、以及所有能输入到计算机中,被计算机程序识别和处理的符号(数值、字符等)的集合。 数据元素(数据成员)是数据的基本单位。在不同的条件下,数据元素又可称为元素、结点、顶点、记录等 数据对象具有相同性质的数据元素(数据成员)的集合 数据结构由某一数据对象及该对象中所有数据成员之间的关系组成。记为Data_Structure = {D, R}其中,D是某一数据对象,R是该对象中所有数据成员之间的关系的有限集合。 数据类型是指一种类型,以及定义在这个值集合上的一组操作的总称。 判断一个算法的优劣主要标准:正确性、可使用性、可读性、效率、健壮性、简单性。 算法效率的衡量方法:后期测试,事前估计 算法分析是算法的渐进分析简称 数据结构包括“逻辑结构”和“物理结构”两个方面(层次): 逻辑结构是对数据成员之间的逻辑关系的描述,它可以用一个数据成员的集合和定义在此集合上的若干关系来表示物理结构是逻辑结构在计算机中的表示和实现,故又称“存储结构” 线性表的定义:n(3 0)个表项的有限序列L =(a1, a2, …, an)ai是表项,n是表长度。第一个表项是表头,最后一个是表尾。 线性表的特点:表中元素的数据类型相同;线性表中,结点和结点间的关系是一对一的,有序表和无序表线性表的存储方式。一,顺序存储方式,二,链表存储方式。 顺序表的存储表示有2种方式:静态方式和动态方式。 顺序表的定义是:把线性表中的所有表项按照其逻辑顺序依次存储到从计算机存储中指定存储位置开始的一块连续的存储空间中。 顺序表的特点:用地址连续的一块存储空间顺序存放各表项,各表项的逻辑顺序与物理顺序一致,对各个表项可以顺序访问,也可以随机访问。 单链表是一种最简单的链表表示,也叫线性链表,用她来表示线性表时,用指针表示结点间的逻辑关系。特点:是长度可以很方便地进行扩充。 连续存储方式(顺序表)特点:存储利用率高,存取速度快缺点:插入、删除等操作时需要移动大量数据: 链式存储方式(链表)特点:适应表的动态增长和删除。缺点:需要额外的指针存储空间

c语言数据结构总结

数据结构大全 一、概论 二、线性表 三、栈和队列 四、串 五、多维数组和广义表 十、文件 六、树 七、图 八、排序 九、查找

一、概论 1、评价一个算法时间性能的主要标准是( 算法的时间复杂度)。 2、算法的时间复杂度与问题的规模有关外,还与输入实例的( 初始状态)有关。 3、一般,将算法求解问题的输入量称为( 问题的规模)。 4、在选择算法时,除首先考虑正确性外,还应考虑哪三点? 答:选用的算法首先应该是"正确"的。此外,主要考虑如下三点:①执行算法所耗费的时间;②执行算法所耗费的存储空间,其中主要考虑辅助存储空间;③算法应易于理解,易于编码,易于调试等等。 6、下列四种排序方法中,不稳定的方法是( D ) A、直接插入排序 B、冒泡排序 C、归并排序 D、直接选择排序 7、按增长率由小至大的顺序排列下列各函数: 2100, (3/2)n,(2/3)n,n n,n0.5 , n! ,2n,lgn ,n lgn, n3/2 答:常见的时间复杂度按数量级递增排列,依次为: 常数0(1)、对数阶0(log2n)、线形阶0(n)、线形对数阶0(nlog2n)、平方阶0(n2)立方阶0(n3)、…、k次方阶0(n k)、指数阶0(2n)。显然,时间复杂度为指数阶0(2n)的算法效率极低,当n值稍大时就无法应用。先将题中的函数分成如下几类: 常数阶:2100 对数阶:lgn K次方阶:n0.5、n3/2 指数阶(按指数由小到大排):n lgn、(3/2)n、2n、n!、n n 注意:(2/3)n由于底数小于1,所以是一个递减函数,其数量级应小于常数阶。 根据以上分析按增长率由小至大的顺序可排列如下: (2/3)n <2100 < lgn < n0.5< n3/2 < n lgn <(3/2)n < 2n < n! < n n 8、常用的存储表示方法有哪几种? 常用的存储表示方法:顺序存储方法、链接存储方法、索引存储方法、散列存储方法。 9、设有两个算法在同一机器上运行,其执行时间分别为100n2和2n,要使前者快于后者,n至少要(15)。 二、线性表 1、以下关于线性表的说法不正确的是( C )。 A、线性表中的数据元素可以是数字、字符、记录等不同类型。 B、线性表中包含的数据元素个数不是任意的。 C、线性表中的每个结点都有且只有一个直接前趋和直接后继。 D、存在这样的线性表:表中各结点都没有直接前趋和直接后继。 2、线性表是一种典型的( 线性)结构。 3、线性表的逻辑结构特征是什么? 答:对于非空的线性表:①有且仅有一个开始结点A1,没有直接前趋,有且仅有一个直接后继A2; ②有且仅有一个终结结点AN,没有直接后继,有且仅有一个直接前趋AN-1;③其余的内部结点AI (2≤I≤N-1)都有且仅有一个直接前趋AI-1和一个AI+1。 4、线性表的顺序存储结构是一种( 随机存取)的存储结构。线性结构的顺序存储结构是一种随机存取的存储结构,线性表的链式存储结构是一种顺序存取的存储结构。线性表若采用链式存储表示时所有结点之间的存储单元地址可连续可不连续 5、在顺序表中,只要知道( 基地址和结点大小),就可在相同时间内求出任一结点的存储地址。 6、在等概率情况下,顺序表的插入操作要移动( 一半)结点。

数据结构与算法—递归与非递归转换

递归与非递归转换的基础知识是能够正确理解三种树的遍历方法:前序,中序和后序,第一篇就是关于这三种遍历方法的递归和非递归算法。 一、为什么要学习递归与非递归的转换的实现方法? 1>并不是每一门语言都支持递归的。 2>有助于理解递归的本质。 3>有助于理解栈,树等数据结构。 二、三种遍历树的递归和非递归算法 递归与非递归的转换基于以下的原理:所有的递归程序都可以用树结构表示出来。需要说明的是,这个”原理”并没有经过严格的数学证明,只是我的一个猜想,不过在至少在我遇到的例子中是适用的。学习过树结构的人都知道,有三种方法可以遍历树:前序,中序,后序。理解这三种遍历方式的递归和非递归的表达方式是能够正确实现转换的关键之处,所以我们先来谈谈这个。需要说明的是,这里以特殊的二叉树来说明,不过大多数情况下二叉树已经够用,而且理解了二叉树的遍历,其它的树遍历方式就不难了。 1>前序遍历 a>递归方式: void preorder_recursive(Bitree T> /* 先序遍历二叉树的递归算法 */ { if (T> { visit(T>。 /* 访问当前结点 */ preorder_recursive(T->lchild>。 /* 访问左子树 */ preorder_recursive(T->rchild>。 /* 访问右子树 */ } } b>非递归方式 void preorder_nonrecursive(Bitree T> /* 先序遍历二叉树的非递归算法 */

initstack(S>。 push(S,T>。 /* 根指针进栈 */ while(!stackempty(S>> { while(gettop(S,p>&&p> { /* 向左走到尽头 */ visit(p>。 /* 每向前走一步都访问当前结点 */ push(S,p->lchild>。 } pop(S,p>。 if(!stackempty(S>> { /* 向右走一步 */ pop(S,p>。 push(S,p->rchild>。 } } } 2>中序遍历 a>递归方式 void inorder_recursive(Bitree T> /* 中序遍历二叉树的递归算法 */ { if (T> { inorder_recursive(T->lchild>。 /* 访问左子树 */ visit(T>。 /* 访问当前结点 */ inorder_recursive(T->rchild>。 /* 访问右子树 */

数据结构课程总结

课程总结(提要) 一、数据结构和抽象数据类型ADT 定义:一个数学模型以及定义在该模型上的一组操作。 构成一个抽象数据类型的三个要素是: 数据对象、数据关系、基本操作 数据结构(非数值计算程序设计问题中的数学模型) ·逻辑结构(描述数据元素之间的关系) 线性结构——线性表、栈、队列、串、数组、广义表 非线性结构——树和森林、二叉树、图 集合结构——查找表、文件 ·存储结构(逻辑结构在存储器中的映象) 按“关系”的表示方法不同而分: 顺序结构—以数据元素在存储器中的一个固定的相对位置来表示“关系” 链式结构—以指针表示数据元素的“后继”或“前驱” ·基本操作(三类) 结构的建立和销毁 查找——引用型操作(不改变元素间的关系) 按“关系”进行检索 按给定值进行检索 遍历——访问结构中的每一个数据元素,且对每个元素只访问一次修改——加工型操作(改变元素间的关系) 插入 删除 更新(删除+插入)

二、线性结构 ·线性表和有序表 ——不同存储结构的比较 顺序表:可以实现随机存取;O(1) 插入和删除时需要移动元素;O(n) 需要预分配存储空间; 适用于“不常进行修改操作、表中元素相对稳定”的场合。 链表:只能进行顺序存取;O(n) 插入和删除时只需修改指针; O(1) 不需要预分配存储空间; 适用于“修改操作频繁、事先无法估计最大表长”的场合。 ——应用问题的算法时间复杂度的比较 例如,以线性表表示集合进行运算的时间复杂度为O(n2), 而以有序表表示集合进行运算的时间复杂度为O(n) ·栈和队列——数据类型的特点及其应用范畴 ·串——和线性表的差异: 数据对象不同(数据元素限定为单个字符)、基本操作集不同(串整体作为操作对象)、存储结构不同 ??串的模式匹配算法 ·数组——只有引用型的操作,∴只需要顺序存储结构 多维到一维的不同映象方法: 以行序为主序(低下标优先) 以列序为主序(高下标优先) ·广义表——多层次的线性结构 特性:次序性、长度、层次性、深度、递归等 独有的特性:共享 存储结构的特点

数据结构习题

树和二叉树习题(39) 1.请编写一个判别给定二叉树是否为二叉排序树的算法,设二叉树用llink-rlink 法存储。2.假设K1,…,Kn 是n 个关键词,试解答: (1) 试用二叉查找树的插入算法建立一棵二叉查找树,即当关键词的插入次序为K1, K2,…,Kn 时,用算法建立一棵以LLINK / RLINK 链接表示的二叉查找树。 (2) 设计一个算法,打印出该二叉查找树的嵌套括号表示结构。例如,K1=B,K2=A,K3=D,K4=C,K5=E,则用二叉查找树的插入算法建立的二叉查找树为: 该二叉查找树的嵌套括号表示结构为:B(A,D(C,E)) 3.写出在二叉排序树中删除一个结点的算法,使删除后仍为二叉排序树。设删除结点由指针p 所指,其双亲结点由指针 f 所指,并假设被删除结点是其双亲结点的右孩子。用类PASCAL(或C)语言将上述算法写为过程形式。 4. 已知二叉树排序树中某结点指针p,其双亲结点指针为fp,p 为fp 的左孩子,试编写算法,删除p 所指结点。 5.二叉排序树采用二叉链表存储。写一个算法,删除结点值是X 的结点。要求删除该结点后,此树仍然是一棵二叉排序树,并且高度没有增长(注:可不考虑被删除的结点是根的情况)。 6. 设记录R1,R2,…,Rn 按关键字值从小到大顺序存储在数组r[1..n]中,在r[n+1]处设立一个监督哨,其关键字值为+∞; 试写一查找给定关键字k 的算法;并画出此查找过程的判定树, 求出在等概率情况下查找成功时的平均查找长度。 7.设计算法以求解编号为i和j的两个结点的最近的公共祖先结点的编号。 8.元素集合已存入整型数组A[1..n]中,试写出依次取A 中各值A[i](1<=i<=n)构造一棵二叉排序树T 的非递归算法:CSBT(T,A) 9.写出折半查找的算法,并要求它返回整型值i,当查找成功时,返回查找位置,查找不成功时返回0。 10.请编写算法:键树,又称数字查找树。它是一棵度为>=2 的树,树中的每个结点中不

数据结构与算法分析论文(递归的讨论)

数据结构与算法分析论文 递归算法的讨论 学号 1415211013 姓名李莉姗 班级 14电子1班 华侨大学电子工程系

递归算法的讨论 所谓递归算法是把问题转化为规模缩小了的同类问题的子问题。然后递归调用函数(或过程)来表示问题的解。一个过程(或函数)直接或间接调用自己本身,这种过程(或函数)叫递归过程(或函数)。递归过程一般通过函数或子过程来实现。递归方法:在函数或子过程的内部,直接或者间接地调用自己的算法。递归算法是一种直接或者间接地调用自身算法的过程。在计算机编写程序中,递归算法对解决一大类问题是十分有效的,它往往使算法的描述简洁而且易于理解。递归算法解决问题的特点: (1) 递归就是在过程或函数里调用自身。 (2) 在使用递归策略时,必须有一个明确的递归结束条件,称为递归出口。 (3) 递归算法解题通常显得很简洁,但递归算法解题的运行效率较低。 (4) 在递归调用的过程当中系统为每一层的返回点、局部量等开辟了栈来存储。递归次数过多容易造成栈溢出等。所以一般不提倡用递归算法设计程序。下面就让我们结合例子详细讨论一下递归算法。 一、递归算法的原理 递归算法简单的说就是在函数中调用函数自身,不断调用,直到满足函数得出计算结果(某个条件)。因为其需要不断循环的调用自身,所以称为递归调用。递归的原理,其实就是一个栈(stack), 比如求5的阶乘,要知道5的阶乘,就要知道4的阶乘,4又要是到3的,以此类推,所以递归式就先把5的阶乘表示入栈, 在把4的入栈,直到最后一个,之后呢在从1开始出栈, 看起来很麻烦,确实很麻烦,他的好处就是写起代码来,十分的快,而且代码简洁,其他就没什么好处了,运行效率出奇的慢。还有一个十分形象的例子:从前有座山,山里有个庙,庙里有个老和尚正在讲故事:从前有座山,山里有个庙,庙里有个老和尚正在讲故事:从前有座山,山里有个庙,庙里有个老和尚正在讲故事……如此循环往复

数据结构(递归、数组、矩阵)练习题与答案

1、有一个三维数组A[-2..2][-4..5][2..6],其中元素个数是 ()。 A.144 B.250 C.396 D.60 正确答案:B 解析: B、A的第1维长度为5,第2维长度为10,第3维长度为5,元素个数=5×10×5=250。 2、设C/C++二维数组a[m][n],每个数组元素占用k个存储单元, 第一个数组元素的存储地址是LOC(a[0][0]),求按行优先顺序存放 的数组元素a[i][j](0≤i≤m-1,0≤j≤n-1)的存储地址为()。 A.LOC(a[0][0])+[(j-1)×m+i-1]×k B.LOC(a[0][0])+[i×n+j]×k C.LOC(a[0][0])+[(i-1)×n+j-1]×k D.LOC(a[0][0])+[j×m+i]×k 正确答案:B 解析: B、a[i][j]前面有0~i-1行,计i×n个元素,第i行前 面有j个元素,则a[i][j]前面有i×m+ j个元素,所以a[i][j]的 存储地址=LOC(a[0][0])+[i×n+j]×k。 3、设二维数组a[1..5][1..8],若按行优先的顺序存放数组的元素,则a[4][6]元素的前面有()个元素。 A.6 B.40 C.28

D.29 正确答案:D 解析: D、m=5,n=8,a[4][6]元素的前面的元素个数=(4-1) ×8+(6-1)=29。 4、设C/C++二维数组a[6][10],每个数组元素占用4个存储单元,若按行优先顺序存放所有数组元素,a[3][5]的存储地址为1000,则a[0][0]的存储地址是()。 A.864 B.868 C.860 D.872 正确答案:C 解析: C、C/C++二维数组下标从0开始。a[3][5]前面的元素个数=(3-0)×10+(5-0)=35。所以1000=LOC(a[0][0])+35×4, LOC(a[0][0])=860。 5、一个n阶对称矩阵A采用压缩存储方式,将其下三角部分(含主对角线元素)按行优先存储到一维数组B中,则B中元素个数是()。 A.n(n+1)/2 B.n*n C.n(n+1)/2+1 D.n 正确答案:A

数据结构与算法课后习题答案

课后习题解答 判断题 1.线性表的逻辑顺序与存储顺序总是一致的。(×) 2.顺序存储的线性表可以按序号随机存取。(√) 3.顺序表的插入和删除操作不需要付出很大的时间代价,因为每次操作平均只有近一半的元素需要移动。(×) 4.线性表中的元素可以是各种各样的,但同一线性表中的数据元素具有相同的特性,因此属于同一数据对象。(√) 5.在线性表的顺序存储结构中,逻辑上相邻的两个元素在物理位置上并不一定相邻。(×) 6.在线性表的链式存储结构中,逻辑上相邻的元素在物理位置上不一定相邻。(√)7.线性表的链式存储结构优于顺序存储结构。(×) 8.在线性表的顺序存储结构中,插入和删除时移动元素的个数与该元素的位置有关。(√) 9.线性表的链式存储结构是用一组任意的存储单元来存储线性表中数据元素的。(√)10.在单链表中,要取得某个元素,只要知道该元素的指针即可,因此,单链表是随机存取的存储结构。(×) 11.静态链表既有顺序存储的优点,又有动态链表的优点。所以它存取表中第i个元素的时间与i无关。(×) 12.线性表的特点是每个元素都有一个前驱和一个后继。(×) 算法设计题 1.设线性表存放在向量A[arrsize]的前elenum个分量中,且递增有序。试写一算法,将x 插入到线性表的适当位置上,以保持线性表的有序性,并且分析算法的时间复杂度。【提示】直接用题目中所给定的数据结构(顺序存储的思想是用物理上的相邻表示逻辑上的相邻,不一定将向量和表示线性表长度的变量封装成一个结构体),因为是顺序存储,分配的存储空间是固定大小的,所以首先确定是否还有存储空间,若有,则根据原线性表中元素的有序性,来确定插入元素的插入位置,后面的元素为它让出位置,(也可以从高下标端开始一边比较,一边移位)然后插入x ,最后修改表示表长的变量。 int insert (datatype A[],int *elenum,datatype x) /*设elenum为表的最大下标*/ {if (*elenum==arrsize-1) return 0; /*表已满,无法插入*/ else {i=*elenum; while (i>=0 && A[i]>x) /*边找位置边移动*/ {A[i+1]=A[i]; i--; } A[i+1]=x; /*找到的位置是插入位的下一位*/ (*elenum)++; return 1; /*插入成功*/ }

数据结构复习重点归纳笔记[清华严蔚敏版]

一、数据结构的章节结构及重点构成 数据结构学科的章节划分基本上为:概论,线性表,栈和队列,串,多维数组和广义表,树和二叉树,图,查找,内排,外排,文件,动态存储分配。 对于绝大多数的学校而言,“外排,文件,动态存储分配”三章基本上是不考的,在大多数高校的计算机本科教学过程中,这三章也是基本上不作讲授的。所以,大家在这三章上可以不必花费过多的精力,只要知道基本的概念即可。但是,对于报考名校特别是该校又有在试卷中对这三章进行过考核的历史,那么这部分朋友就要留意这三章了。 按照以上我们给出的章节以及对后三章的介绍,数据结构的章节比重大致为: 概论:内容很少,概念简单,分数大多只有几分,有的学校甚至不考。 线性表:基础章节,必考内容之一。考题多数为基本概念题,名校考题中,鲜有大型算法设计题。如果有,也是与其它章节内容相结合。 栈和队列:基础章节,容易出基本概念题,必考内容之一。而栈常与其它章节配合考查,也常与递归等概念相联系进行考查。 串:基础章节,概念较为简单。专门针对于此章的大型算法设计题很少,较常见的是根据KMP进行算法分析。 多维数组及广义表:基础章节,基于数组的算法题也是常见的,分数比例波动较大,是出题的“可选单元”或“侯补单元”。一般如果要出题,多数不会作为大题出。数组常与“查找,排序”等章节结合来作为大题考查。 树和二叉树:重点难点章节,各校必考章节。各校在此章出题的不同之处在于,是否在本章中出一到两道大的算法设计题。通过对多所学校的试卷分析,绝大多数学校在本章都曾有过出大型算法设计题的历史。 图:重点难点章节,名校尤爱考。如果作为重点来考,则多出现于分析与设计题型当中,可与树一章共同构成算法设计大题的题型设计。 查找:重点难点章节,概念较多,联系较为紧密,容易混淆。出题时可以作为分析型题目给出,在基本概念型题目中也较为常见。算法设计型题中可以数组结合来考查,也可以与树一章结合来考查。 排序:与查找一章类似,本章同属于重点难点章节,且概念更多,联系更为紧密,概念之间更容易混淆。在基本概念的考查中,尤爱考各种排序算法的优劣比较此类的题。算法设计大题中,如果作为出题,那么常与数组结合来考查。 二、数据结构各章节重点勾划: 第0章概述 本章主要起到总领作用,为读者进行数据结构的学习进行了一些先期铺垫。大家主要注意以下几点:数据结构的基本概念,时间和空间复杂度的概念及度量方法,算法设计时的注意事项。本章考点不多,只要稍加注意理解即可。

数据结构课程设计分类题目

线性表 顺序表: 1、设有一元素为整数的线性表L=(a1,a2,a3,…,a n),存放在一维数组A[N]中,设计一个算法,以表中a n作为参考元素,将该表分为左、右两部分,其中左半部分每个元素小于等于a n,右半部分每个元素都大于a n, a n位于分界位置上(要求结果仍存放在A[N]中)。 2、设线性表存于A[1..size]的前num各分量中,且递增有序。请设计一个算法,将x插入到线性表的适当位置上,以保持线性表的有序性。 3、线性表(a 1,a2,a3,…,a n)中元素递增有序且按顺序存储于计算机内。要求设计一算法完成: (1)用最少时间在表中查找数值为x的元素。 (2)若找到将其与后继元素位置相交换。 (3)若找不到将其插入表中并使表中元素仍递增有序。 4、已知数组A[0:n-1]的元素类型为int,试设计算法将其调整为左右两个部分,左边所有元素为奇数,右边所有元素为偶数。 5、设计一个算法从顺序表L中删除所有值为x的元素 6、设计一个算法从顺序表L中删除所有值为x到y之间(x<=y)的元素 链表: 1、假设有两个按元素值递增次序排列的线性表,均以单链表形式存储。请编写算法将这两个单链表归并为一个按元素值递减次序排列的单链表,并要求利用原来两个单链表的结点存放归并后的单链表。 2、已知L1、L2分别为两循环单链表的头结点指针,m,n分别为L1、L2表中数据结点个数。要求设计一算法,用最快速度将两表合并成一个带头结点的循环单链表。 3、设L为单链表的头结点地址,其数据结点的数据都是正整数且无相同的,设计一个将该链表整理成数据递增的有序单链表的算法。 5、设计算法将一个带头结点的单链表A分解为两个具有相同结构的链表B、C,其中B表的结点为A表中值小于零的结点,而C表的结点为A表中值大于零的结点(链表A的元素类型为整型,要求B、C表利用A表的结点)。 6、试编写在带头结点的单链表中删除(一个)最小值结点的(高效)算法。 7、设L为单链表的头结点地址,请写一算法,将链表中数据域值最小的那个链结点移到链表的最前面。要求:不得额外申请新的链结点。 8、已知两个单链表A和B,其头指针分别为heada和headb,编写一个过程从单链表A中删除自第i个元素起的共len个元素,然后将单链表A插入到单链表B的第j个元素之前。9、已知递增有序的单链表A,B分别存储了一个集合,请设计算法以求出两个集合A和B 的差集A-B(即仅由在A中出现而不在B中出现的元素所构成的集合),并以同样的形式存储,同时返回该集合的元素个数。 10、已知一个单链表中每个结点存放一个整数,并且结点数不少于2,请设计算法以判断该链表中第二项起的每个元素值是否等于其序号的平方减去其前驱的值,若满足则返回ture,否则返回false. 11、两个整数序列A=a1,a2,a3,…,am和B=b1,b2,b3,…,bn已经存入两个单链表中,设计一个算法,判断序列B是否是序列A的子序列。

《数据结构》考研必须掌握的知识点与算法

《数据结构》必须掌握的知识点与算法 第一章绪论 1、算法的五个重要特性(有穷性、确定性、可行性、输入、输出) 2、算法设计的要求(正确性、可读性、健壮性、效率与低存储量需求) 3、算法与程序的关系: (1)一个程序不一定满足有穷性。例操作系统,只要整个系统不遭破坏,它将永远不会停止,即使没有作业需要处理,它仍处于动态等待中。因此,操作系统不是一个算法。 (2)程序中的指令必须是机器可执行的,而算法中的指令则无此限制。算法代表了对问题的解,而程序则是算法在计算机上的特定的实现。 (3)一个算法若用程序设计语言来描述,则它就是一个程序。 4、算法的时间复杂度的表示与计算(这个比较复杂,具体看算法本身,一般关心其循环的次数与N的关系、函数递归的计算) 第二章线性表 1、线性表的特点: (1)存在唯一的第一个元素;(这一点决定了图不是线性表) (2)存在唯一的最后一个元素; (3)除第一个元素外,其它均只有一个前驱(这一点决定了树不是线性表) (4)除最后一个元素外,其它均只有一个后继。 2、线性表有两种表示:顺序表示(数组)、链式表示(链表),栈、队列都是线性表,他们都可以用数组、链表来实现。 3、顺序表示的线性表(数组)地址计算方法: (1)一维数组,设DataType a[N]的首地址为A0,每一个数据(DataType 类型)占m个字节,则a[k]的地址为:A a[k]=A0+m*k(其直接意义就是求在数据a[k]的前面有多少个元素,每个元素占m个字节) (2)多维数组,以三维数组为例,设DataType a[M][N][P]的首地址为A000,每一个数据(DataType类型)占m个字节,则在元素a[i][j][k]的前面共有元素个数为:M*N*i+N*j+k,其其地址为: A a[i][j][k]=A000+m*(M*N*i+N*j+k); 4、线性表的归并排序: 设两个线性表均已经按非递减顺序排好序,现要将两者合并为一个线性表,并仍然接非递减顺序。可见算法2.2 5、掌握线性表的顺序表示法定义代码,各元素的含义; 6、顺序线性表的初始化过程,可见算法2.3 7、顺序线性表的元素的查找。 8、顺序线性表的元素的插入算法,注意其对于当原来的存储空间满了后,追加存储空间(就是每次增加若干个空间,一般为10个)的处理过程,可见算法2.4

数据结构实验----大一下

实验1:单链表实验 一、实验目的 1.学会定义单链表的结点类型,实现对单链表的一些基本操作和具体 的函数定义,了解并掌握单链表的类定义以及成员函数的定义与调用。 2.掌握单链表基本操作及两个有序表归并、单链表逆置等操作的实现。 二、实验要求 1.预习C语言中结构体的定义与基本操作方法。 2.对单链表的每个基本操作用单独的函数实现。 3.编写完整程序完成下面的实验内容并上机运行。 三、实验内容 1.编写程序完成单链表的下列基本操作: (1) 初始化单链表La。 (2) 在La中插入一个新结点。 (3) 删除La中的某一个结点。 (4) 在La中查找某结点并返回其位置。 (5) 打印输出La中的结点元素值。 2.构造两个带有表头结点的有序单链表La、Lb,编写程序实现将La、Lb合并成一个有序单链表Lc。 合并思想是:程序需要3个指针:pa、pb、pc,其中pa,pb分别指向La表与Lb表中当前待比较插入的结点,pc 指向Lc表中当前最后一个结点。 依次扫描La和Lb中的元素,比较当前元素的值,将较小者链接到*pc之后,如此重复直到La或Lb结束为止,再将另一个链表余下的内容链接到pc所指的结点之后。 3.构造一个单链表L,其头结点指针为head,编写程序实现将L逆置。 (即最后一个结点变成第一个结点,原来倒数第二个结点变成第二个结点,如此等等。) 四、思考与提高 1.如果上面实验内容2中合并的表内不允许有重复的数据该如何操作? 2.如何将一个带头结点的单链表La分解成两个同样结构的单链表Lb,Lc,使得Lb中只含La表中奇数结点,Lc中含有La表的偶数结点?

实验2:栈的操作实验 一、实验目的 1.熟悉并能实现栈的定义和基本操作。 2.了解和掌握栈在递归和非递归算法的应用。 二、实验要求 1.进行栈的基本操作时要注意栈“后进先出”的特性。 2.编写完整程序完成下面的实验内容并上机运行。 三、实验内容 1.编写程序任意输入栈长度和栈中的元素值,构造一个顺序栈,对其进行清空、销毁、入栈、出栈以及取栈顶元素操作。 2.编写程序实现表达式求值,即验证某算术表达式的正确性,若正确,则计算该算术表达式的值。 主要功能描述如下: 1、从键盘上输入表达式。 2、分析该表达式是否合法: (1) 是数字,则判断该数字的合法性。若合法,则压入数据到堆栈 中。 (2) 是规定的运算符,则根据规则进行处理。在处理过程中,将计 算该表达式的值。 (3) 若是其它字符,则返回错误信息。 3、若上述处理过程中没有发现错误,则认为该表达式合法,并打印 处理结果。 程序中应主要包含下面几个功能函数: void initstack():初始化堆栈 int Make_str():语法检查并计算 int push_operate(int operate):将操作码压入堆栈 int push_num(double num):将操作数压入堆栈 int procede(int operate):处理操作码 int change_opnd(int operate):将字符型操作码转换成优先级 int push_opnd(int operate):将操作码压入堆栈 int pop_opnd():将操作码弹出堆栈 int caculate(int cur_opnd):简单计算+,-,*,/ double pop_num():弹出操作数 3.已知函数t(n)=2*t(n/2)+n 其中t(0)=0,n为整数。编写程序实现: (1) 计算t(n)的递归算法。 (2) 用链式栈实现计算t(n)的非递归算法。 四、思考与提高 1.如果一个程序中要用到两个栈,为了不发生上溢错误,就必须给每个栈预先分配一个足够大的存储空间。若每个栈都预分配过大的存储空间,

数据结构课程设计报告-迷宫求解(递归与非递归)

《数据结构》课程设计 迷宫求解 班级: 学号: 姓名: 指导老师:

迷宫求解 1、问题描述 输入一个任意大小的迷宫数据,用递归和非递归两种方法求出一条走出迷宫的路径,并将路径输出。 2、设计思路 从入口出发,按某一方向向前探索,若能走通并且未走过,即某处可以到达,则到达新点,否则试探下一个方向;若所有的方向均没有通路,则沿原路返回前一点,换下一个方向再继续试探,直到找到一条通路,或无路可走又返回入口点。 在求解过程中,为了保证在到达某一点后不能向前继续行走(无路)时,能正确返回前一点以便继续从下一个方向向前试探,则需要用一个栈(递归不需要)保存所能够到达的每一点的下标及从该点前进的方向。设迷宫为m行n列,利用maze[m][n]来表示一个迷宫,maze[i][j]=0或1;其中:0表示通路,1表示不通,当从某点向下试探时,中间点有四个方向可以试探,而四个角点有两个方向,其他边缘点有三个方向,为使问题简单化,用maze[m+2][n+2]来表示迷宫,而迷宫的四周的值全部为1,这样做使问题简单了,每个点的试探方

向全部为4,不用再判断当前点的试探方向有几个。 3、数据结构设计 在上述表示迷宫的情况下,每个点有4个方向去试探,如当前点的坐标(x,y),与其相邻的4个点的坐标都可根据与该点的相邻方位而得到。因为出口在(m,n),因此试探顺序规定为:从当前位置向前试探的方向为从正东沿顺时针方向进行。为了简化问题,方便求出新点的坐标,将从正东开始沿顺时针进行的4个方向的坐标增量放在一个结构数组move[4]中,在move数组中,每个元素有两个域组成,x为横坐标增量,y为纵坐标增量。这样对move设计会很方便地求出从某点(x,y)按某一方向v(0<=v<=3)到达的新点(i,j)的坐标:i=x+move[v].x;j=y+move[v].y; 当到达了某点而无路可走时需返回前一点,再从前一点开始向下一个方向继续试探。因此,压入栈中的不仅是顺序到达的各点的坐标,而且还要有从前一点到达本点的方向。栈中元素是一个由行、列、方向组成。具体结构定义如下: #define m 3 #define n 3 typedef struct{ int x,y; }item; /*路线移动的方向坐标,x为横向,y纵向*/ item move[4];(递归只需定义到这里)

相关文档
最新文档