先序遍历的非递归算法
- 格式:doc
- 大小:41.50 KB
- 文档页数:6
图的深度优先遍历(DFS)c++⾮递归实现深搜算法对于程序员来讲是必会的基础,不仅要会,更要熟练。
ACM竞赛中,深搜也牢牢占据着很重要的⼀部分。
本⽂⽤显式栈(⾮递归)实现了图的深度优先遍历,希望⼤家可以相互学习。
栈实现的基本思路是将⼀个节点所有未被访问的“邻居”(即“⼀层邻居节点”)踹⼊栈中“待⽤”,然后围绕顶部节点猛攻,每个节点被访问后被踹出。
读者可以⾃⼰画图分析⼀下,难度并不⼤。
代码写的⽐较随意,仅供参考。
~#include <iostream>#include <stack>using namespace std;#define MaxNode 20#define MAX 2000#define StartNode 1int map[MaxNode+1][MaxNode+1];void dfs_stack(int start, int n){int visited[MaxNode],s_top;for(int i = 0;i <= MaxNode; i++){visited[i] = 0;}visited[start] = 1;stack <int> s;cout<<start<<"";for(int i = 1; i <= n; i++){if(map[i][start] == 1 && !visited[i] ){visited[i] = 1;s.push(i);}}while(!s.empty()){s_top = s.top();visited[s_top] = 1;cout<<s_top<<"";s.pop();for(int i = 1; i <= n; i++){if(map[i][s_top] == 1 && !visited[i] ){visited[i] = 1;s.push(i);}}}}int main(int argc, const char * argv[]) {int num_edge,num_node;int x,y;cout<<"Input number of nodes and edges >"<<endl;cin>>num_node>>num_edge;for(int i =0;i<num_node;i++){for(int j=0;j<num_node;j++){map[i][j] = 0;}}for(int i = 1; i <= num_edge; i++){cin>>x>>y;map[x][y] = map[y][x] = 1;}dfs_stack(StartNode, num_node);return0;}。
二叉树的遍历算法1 先序遍历(T、p、S()、top)\*先序遍历的非递归算法,T为根指针,p为指针,指向当前结点。
使用一个栈S()、top为栈顶指针*\1.if(T=NULL)2.Printf( “这是一棵空二叉树”);3.else{△△p=T;top=0;4. While(top≠0)||(p≠NULL){△while(p≠NULL){﹡Visit(p→data); \﹡访问结点﹡\top=top+1;if (top>n) 调用栈满else{S(top)=p→rchild;P=P→lchild;}}﹡if (top≠0){p= S(top);top--;}}△}△△{算法结束}算法2 中序遍历(T、p、S()、top)\*{中序遍历的非递归算法,使用栈S(),top为栈顶指针,T指向根,p为指针,指向当前结点*\top=0,p=TWhile(top≠0)||(P≠NULL){While(P≠NULL){Top=top+1if (top>n) 调用栈满else{S(top)=p, p=p→lchied;}}If (top≠null){p=S(top);top=top-1;Visit(p→data); \﹡访问结点﹡\p=p→rchild;}}{算法结束}算法3 后序遍历(T、p、S()、top)\*后序遍历的非递归算法,T指向根,P为指标指向当前结点,使用堆栈S(),栈顶指针为top,*\1、if (t=NIL)2、then { 输出“这是一棵空树”go 22 \* 结束 *\3、else { p=t;top=0;4、 while (top≠0)||(p≠NIL) {5、 while (p≠NIL){6、 top=top+1;7、 if (top﹥n)8、调用栈满9、 else{S(top)=p;10、 p=p→lchild;}11、 }12、 if (top≠0){13、 p=S(top);top=top-114、 if (p﹤0){15、 p=-p;16、 Visit(p→data); \﹡访问结点﹡\17、 p=NIL;〕18、 else {top=top+1;19、 S(top)=-P;20、 p=p→rchild;}21、 }22、{算法结束}算法4 二叉树后序遍历(t、p、S()、top、h)\*后序遍历的非递归算法,T指向根,使用堆栈S(),top为栈顶指针,P为指针,指向当前结点,h为指针,指向刚被访问结点*\1、if (T=Nil){ 输出“这是一棵空树”go 20}2、else{﹡p=t,top=03、 if (p→lchild=Nil)&&(P→rchild=Nil)4、 then go 125、 else{△△top=top+1;S(top)=p;6、 if (p→lchild=Nil)7、 {p= p→rchild; go 3;}8、 else {△if (p→rchild=Nil)9、 go 1110、 else {top=top+1; S(top)= p→rchild;}11、 P=p→lchil; go 3}△}△△12、 Visit(p→data); \﹡访问结点﹡\13、 h=p14、 if (top=0){15、输出“栈空” go 20;}16、 else {p= S(top);top=top-1;17、 if(p→Lchild=h)OR(p→rchild=h)18、 then go 12;19、 else go 3;}}﹡20、{算法结束}。
广度优先遍历非递归算法
广度优先遍历(BFS)是一种图的遍历算法,用来遍历图中所有的节点。
以下是广度优先遍历的非递归算法:
1. 创建一个队列,用来存放待访问的节点。
2. 将起始节点放入队列中。
3. 创建一个集合,用来存放已经访问过的节点。
4. 将起始节点加入到已访问节点的集合中。
5. 循环执行以下步骤,直到队列为空为止:
5.1. 从队列中取出一个节点。
5.2. 访问该节点。
5.3. 获取该节点的所有相邻节点。
5.4. 对于每个相邻节点,如果它没有被访问过,则将其加入到队列和已访问节点的集合中。
通过以上步骤,可以按广度优先的顺序遍历整个图。
这种非递归算法利用队列的先进先出(FIFO)特性,保证了相邻节点的访问顺序是按照它们与起始节点的距离逐渐增加的顺序进行的,从而实现了广度优先遍历。
数据结构1、先序遍历的非递归算法。
用c语言写。
void PreOrderUnrec(Bitree t){SqStack s;StackInit(s);p=t;while (p!=null || !StackEmpty(s)){while (p!=null) //遍历左子树{visite(p->data);push(s,p);p=p->lchild;}//endwhileif (!StackEmpty(s)) //通过下一次循环中的内嵌while实现右子树遍历{ p=pop(s);p=p->rchild;}//endif}//endwhile}//PreOrderUnrec/////////////////////////////////#include "stdio.h"#include "stdlib.h"#include "string.h"#define null 0struct node{char data;struct node *lchild;struct node *rchild;};//先序,中序建树struct node *create(char *pre,char *ord,int n){struct node * head;int ordsit;head=null;if(n<=0){return null;}else{head=(struct node *)malloc(sizeof(struct node)); head->data=*pre;head->lchild=head->rchild=null;ordsit=0;while(ord[ordsit]!=*pre){ordsit++;}head->lchild=create(pre+1,ord,ordsit);head->rchild=create (pre+ordsit+1,ord+ordsit+1,n-ordsit-1); return head;}}//中序递归遍历void inorder(struct node *head){if(!head)return;else{inorder(head->lchild );printf("%c",head->data );inorder(head->rchild );}}//中序非递归遍历void inorder1(struct node *head) {struct node *p;struct node *stack[20];int top=0;p=head;while(p||top!=0){while (p){stack[top++]=p;p=p->lchild ;}p=stack[--top];printf("%c ",p->data );p=p->rchild ;}}/////////////////////////////////////////////////////////////////// ////////////////////二叉树前序、中序、后序三种遍历的非递归算法1.先序遍历非递归算法void PreOrderUnrec(Bitree *t){Stack s;StackInit(s);Bitree *p=t;while (p!=NULL || !StackEmpty(s)){while (p!=NULL) //遍历左子树{visite(p->data);push(s,p);p=p->lchild;}if (!StackEmpty(s)) //通过下一次循环中的内嵌while实现右子树遍历{p=pop(s);p=p->rchild;}//endif}//endwhile}2.中序遍历非递归算法void InOrderUnrec(Bitree *t){Stack s;StackInit(s);Bitree *p=t;while (p!=NULL || !StackEmpty(s)){while (p!=NULL) //遍历左子树{push(s,p);p=p->lchild;}if (!StackEmpty(s)){p=pop(s);visite(p->data); //访问根结点p=p->rchild; //通过下一次循环实现右子树遍历}//endif }//endwhile}3.后序遍历非递归算法typedef enum{L,R} tagtype;typedef struct{Bitree ptr;tagtype tag;}stacknode;typedef struct{stacknode Elem[maxsize];int top;}SqStack;void PostOrderUnrec(Bitree t) {SqStack s;stacknode x;StackInit(s);p=t;do{while (p!=null) //遍历左子树{x.ptr = p;x.tag = L; //标记为左子树push(s,x);p=p->lchild;}while (!StackEmpty(s) && s.Elem[s.top].tag==R){x = pop(s);p = x.ptr;visite(p->data); //tag为R,表示右子树访问完毕,故访问根结点} if (!StackEmpty(s)){s.Elem[s.top].tag =R; //遍历右子树p=s.Elem[s.top].ptr->rchild;}}while (!StackEmpty(s));}//PostOrderUnrec二。
数据结构实验报告知识范畴:树实验题目:二叉树的基本算法二(三叉链表的建立、非递归遍历)实验内容及要求:设二叉树采用三叉链表存储结构,结点数据域为字符类型,从键盘输入先序遍历字符序列(用#字符表示NULL指针域)建立三叉链表存储结构。
对先序、中序、后序遍历分别定义各自的求第一访问结点地址first(bt)以及下一访问结点地址next(p)函数,然后用三种遍历的first(bt)和next(p)函数实现非递归遍历。
实验目的:掌握二叉树的三叉链表存储结构及其非递归遍历算法。
数据结构设计简要描述:采用双向链表,每个结点包括字符类型的数据域和一个指针域。
链表结点结构如下:typedef struct node{ElemTp data; //字符数据域struct node *lchild; //左儿子指针struct node *rchild; //右儿子指针struct node *parent; //双亲指针}算法设计简要描述:采用三叉链表的存储结构,双亲指针指向根结点,左右指针指向左右儿子构造双向链表的二叉树。
每一次遍历时先用该遍历的first函数获取第一个访问的结点地址,调用next函数获取下一个访问的结点地址,当结点为空为循环的结束条件。
获取下一个访问的结点地址时需要判断是否需要回溯,需要回溯时通过双亲指针获取根节点地址,再判断是否需要再回溯。
回溯的结束条件为根节点地址为空。
输入/输出设计简要描述:从键盘输入二叉树的数据域,用#表示空。
按先序遍历的顺序依次构建二叉树。
输出三种遍历的遍历结果,并有文字提示。
编程语言说明:使用Visual C++编程。
主要代码采用C语言实现;动态存储分配采用C的malloc操作符实现;输入与输出采用C的printf和scanf流;程序注释采用C/C++规范。
主要函数说明:void InitTrT(TrT bt) //初始化二叉树void crtTrT(TrT *bt) //创建三叉结构的二叉树void destroyTrT(TrT *bt) //销毁二叉树Status emptyTrT(TrT bt) //判断二叉树是否为空int depthTrT(TrT bt) //求二叉树的深度TrT prefirst(TrT bt) //找出先序遍历的第一个结点TrT prenext(TrT bt) //找出先序遍历的下一结点void preorder(TrT bt) //先序非递归遍历TrT midfirst(TrT bt,int &mark) //查找中序遍历的第一个结点TrT midnext(TrT bt,int &mark) //查找中序遍历的下一个结点void midorder(TrT bt) //中序非递归遍历TrT lastfirst(TrT bt,int &mark) //查找后序遍历的第一个结点TrT lastnext(TrT bt,int &mark) //查找后序遍历的下一个结点void lasorder(TrT bt) //后序非递归遍历程序测试简要报告:输入:ABC#F##D##E##输出:程序输出结果与期望输出结果相符。
⼆叉树的遍历及相关题⽬⼆叉树的遍历及相关题⽬1.1⼆叉树遍历的概念⼆叉树结构体的定义:typedef struct node{ ElemType data; struct node * lchild; struct node * rchild;}⼆叉树的遍历是指按照⼀定的次序访问⼆叉树中的所有的节点,并且每个节点仅访问⼀次的过程。
若规定先遍历左⼦树,后遍历右⼦树,则对于⾮空⼆叉树,可得到如下3种递归的遍历⽅法:(1)先序遍历访问根节点,先序遍历左⼦树,先序遍历右⼦树。
(根,左,右)(2)中序遍历中序遍历左⼦树,访问根节点,中序遍历右⼦树。
(左,根,右)(3)后序遍历后序遍历左⼦树,后序遍历右⼦树,访问根节点。
(左,右,根)除此之外也有层次遍历。
先访问根节点,在从左到右访问第⼆层的所有节点,从左到右访问第三层的所有节点......1.2⼆叉树遍历递归算法先序遍历递归算法:void PreOrder(BTNode * b){ if(n != NULL) { cout<<b->data; PreOrder(b->lchild); PreOrder(b->rchild); }}中序遍历递归算法void InOrder(BTNode * b){ if(n != NULL) { InOrder(b->lchild); cout<<b->data; InOrder(b->rchild); }}后序遍历递归算法:void PostOrder(BTNode * b){ if(b != NULL) { PostOrder(b->lchild); PostOrder(b->rchild); cout<<b->data; }}题⽬1:输出⼀个给定⼆叉树的所有的叶⼦节点:void DispLeaf(BTNode * b){ if(b != NULL) { if(b->lchild == NULL && b->rchild == NULL) cout<<b->data; DispLeaf(b->lchild); DispLeaf(b->rchild); }}以上算法采⽤先序遍历输出了所有的叶⼦节点,所以叶⼦节点是从左到右输出的。
计算机专业基础综合数据结构(树和二叉树)历年真题试卷汇编11(总分:60.00,做题时间:90分钟)一、填空题(总题数:24,分数:48.00)1.二叉树按某种顺序线索化后,任一结点均有指向前驱和后继的线索,这种说法是正确的么?__________【南京理工大学2005二、9(1分)】__________________________________________________________________________________________ 正确答案:(正确答案:说法错误。
只有空指针处才能加线索,左指针指向前驱(遍历的第一个结点无前驱),右指针指向后继(遍历的最后一个结点无后继)。
)2.线索二元树的左线索指向其__________,右线索指向其__________。
【哈尔滨工业大学2000二、3 (2分)】__________________________________________________________________________________________ 正确答案:(正确答案:(1)前驱 (2)后继)3.将一棵树转换成二叉树后,根结点没有__________子树。
【电子科技大学2005二、2(1分)】__________________________________________________________________________________________ 正确答案:(正确答案:右)4.哈夫曼树是__________。
【北京理工大学200l七、4(2)】【长沙铁道学院1998二、3(2分)】__________________________________________________________________________________________ 正确答案:(正确答案:带权路径长度最小的二叉树,又称最优二叉树)5.若以{4,5,6,7,8}作为叶子结点的权值构造哈夫曼树,则其带权路径长度是__________。
树的三种遍历方式树是一种非常重要的数据结构,它在计算机科学中应用广泛。
树可以用于搜索、排序、数据表、文件系统等诸多领域。
而树的遍历方式,则是在树中搜索数据的一种方法。
树的遍历方式有三种,分别是前序遍历、中序遍历和后序遍历。
这三种遍历方式在树的数据结构中有着重要的作用,它们可以用来检索所有节点的信息。
下面我们将对它们一一进行介绍。
1.前序遍历前序遍历也称为先序遍历,它的顺序是根节点->左子树->右子树。
它的算法描述如下:前序遍历的递归算法实现:void PreOrderTraversal(TraversalNode T){ if (T) { visit(T); PreOrderTraversal(T->left); PreOrderTraversal(T->right); } }前序遍历的非递归算法实现:void PreOrderTraversal(TraversalNode T){ while (T || !StackIsEmpty(S)) { while (T) { visit(T); push(Stack,T); T = T->left; } if(!StackIsEmpty(S)) { T = pop(Stack);T = T->right; } } }2.中序遍历中序遍历的顺序是左子树->根节点->右子树。
它的算法描述如下:中序遍历的递归算法实现:void InOrderTraversal(TraversalNode T) { if(T) { InOrderTraversal(T->left);visit(T);InOrderTraversal(T->right); } }中序遍历的非递归算法实现:void InOrderTraversal(TraversalNode T){ while (T || !StackIsEmpty(S)) { while(T) { push(Stack, T); T =T->left; } if (!StackIsEmpty(S)){ T = pop(Stack); visit(T); T = T->right; } } }3.后序遍历后序遍历的顺序是左子树->右子树->根节点。
二叉树的前序、后序的递归、非递归遍历算法学生姓名:贺天立指导老师:湛新霞摘要本课程设计主要解决树的前序、后序的递归、非递归遍历算法,层次序的非递归遍历算法的实现。
在课程设计中,系统开发平台为Windows 2000,程序设计设计语言采用Visual C++,程序运行平台为Windows 98/2000/XP。
用除递归算法前序,后续,中序遍历树外还通过非递归的算法遍历树。
程序通过调试运行,初步实现了设计目标,并且经过适当完善后,将可以应用在商业中解决实际问题。
关键词程序设计;C++;树的遍历;非递归遍历1 引言本课程设计主要解决树的前序、后序的递归、非递归遍历算法,层次序的非递归遍历算法的实现。
1.1课程设计的任务构造一棵树并输入数据,编写三个函数,非别是树的前序递归遍历算法、树的后序递归遍历算法、树的非递归中序遍历算法(这里的非递归以中序为例)。
在主程序中调用这三个函数进行树的遍历,观察用不同的遍历方法输出的数据的顺序和验证递归与非递归输出的数据是否一样。
1.2课程设计的性质由要求分析知,本设计主要要求解决树的前序、后序的递归、非递归遍历算法,层次序的非递归遍历算法的实现。
所以设计一个良好的前序、后序的递归、非递归遍历算法非常重要。
1.3课程设计的目的在程序设计中,可以用两种方法解决问题:一是传统的结构化程序设计方法,二是更先进的面向对象程序设计方法[1]。
利用《数据结构》课程的相关知识完成一个具有一定难度的综合设计题目,利用C语言进行程序设计。
巩固和加深对线性表、栈、队列、字符串、树、图、查找、排序等理论知识的理解;掌握现实复杂问题的分析建模和解决方法(包括问题描述、系统分析、设计建模、代码实现、结果分析等);提高利用计算机分析解决综合性实际问题的基本能力。
树的遍历分为前序、中序和后序,可以用递归算法实现树的三种遍历。
除了递归外还可以构造栈,利用出栈和入栈来实现树的前序遍历、中序遍历和后序遍历。
先序遍历二叉树的算法非递归算法一、引言二叉树是一种常见的数据结构,其遍历方式包括先序遍历、中序遍历和后序遍历。
先序遍历是一种常用的遍历方式,它按照根节点-左子树-右子树的顺序访问每个节点。
在递归实现先序遍历二叉树的基础上,非递归算法的出现使得算法的实现更为简洁和高效。
二、非递归算法原理非递归算法的实现原理基于栈数据结构。
我们首先将根节点入栈,然后不断弹出栈顶元素并访问,同时将右子树和左子树分别入栈。
当栈为空时,表示遍历完成。
这种方法避免了递归调用可能导致的堆栈溢出问题,同时提高了算法的效率。
三、非递归算法实现以下是用Python实现的非递归先序遍历二叉树的算法:```pythondefpreorder_traversal_non_recursive(node):ifnodeisNone:return#将当前节点入栈stack.append(node)#当栈不为空时,不断弹出栈顶元素并访问whilestack:curr=stack.pop()#弹出栈顶元素print(curr.value)#访问当前节点#将右子节点入栈ifcurr.right:stack.append(curr.right)#将左子节点入栈ifcurr.left:stack.append(curr.left)```四、算法应用与讨论非递归算法的应用范围广泛,不仅可以应用于二叉树的遍历,还可以应用于二叉树的创建、插入、删除等操作。
在实际应用中,我们可以通过Python中的列表或者类来实现栈数据结构,进而实现非递归算法。
此外,非递归算法还可以与其他算法结合,如深度优先搜索(DFS)和广度优先搜索(BFS),以实现更复杂的数据处理任务。
五、总结非递归先序遍历二叉树的算法是一种实用的技术,它能够简化代码、提高效率并避免堆栈溢出问题。
通过使用栈数据结构,我们可以轻松地实现非递归算法,并将其应用于各种二叉树操作中。
这种技术对于理解和应用二叉树数据结构具有重要的意义。
先序遍历的非递归算法C语言先序遍历是二叉树遍历的一种方式,它的遍历顺序是根节点、左子树、右子树。
非递归算法利用栈的数据结构来实现。
具体算法步骤如下:1.定义一个栈,用于存储节点。
2.将根节点入栈。
3.当栈不为空时,执行步骤4-6,否则结束遍历。
4.弹出栈顶节点,并访问该节点。
5.若该节点有右孩子,将右孩子入栈。
6.若该节点有左孩子,将左孩子入栈。
7.返回步骤3下面是使用C语言实现先序遍历的非递归算法的示例代码:```c#include <stdio.h>#include <stdlib.h>//定义二叉树节点结构typedef struct TreeNodeint data;struct TreeNode* left;struct TreeNode* right;} TreeNode;//定义栈结构typedef struct StackTreeNode* data[100]; // 栈的最大容量int top; // 栈顶指针} Stack;Stack* createStacStack* stack = (Stack*)malloc(sizeof(Stack)); stack->top = -1;return stack;void push(Stack* stack, TreeNode* node)stack->data[++stack->top] = node;TreeNode* pop(Stack* stack)return stack->data[stack->top--];int isEmpty(Stack* stack)return stack->top == -1;//先序遍历的非递归算法void preorderTraversal(TreeNode* root)if (root == NULL)return;}Stack* stack = createStack(; // 创建栈push(stack, root); // 根节点入栈while (!isEmpty(stack))TreeNode* node = pop(stack); // 弹出栈顶节点printf("%d ", node->data); // 访问节点//右孩子先入栈,保证左孩子会在右孩子之前被访问if (node->right != NULL)push(stack, node->right);}//左孩子入栈if (node->left != NULL)push(stack, node->left);}}free(stack); // 释放栈的内存int mai//构建二叉树TreeNode* root = (TreeNode*)malloc(sizeof(TreeNode)); root->data = 1;TreeNode* node2 = (TreeNode*)malloc(sizeof(TreeNode)); node2->data = 2;TreeNode* node3 = (TreeNode*)malloc(sizeof(TreeNode)); node3->data = 3;TreeNode* node4 = (TreeNode*)malloc(sizeof(TreeNode)); node4->data = 4;TreeNode* node5 = (TreeNode*)malloc(sizeof(TreeNode)); node5->data = 5;root->left = node2;root->right = node3;node2->left = node4;node2->right = NULL;node3->left = NULL;node3->right = node5;node4->left = NULL;node4->right = NULL;node5->left = NULL;node5->right = NULL;//先序遍历printf("先序遍历结果:");preorderTraversal(root);//释放二叉树的内存free(root);free(node2);free(node3);free(node4);free(node5);return 0;```以上代码实现了二叉树先序遍历的非递归算法。
(转载)图的深度优先遍历⾮递归算法纠结图的深度优先搜索算法好久,⾮递归算法需要⽤到栈来记录上⼀次访问的结果,但是⼤脑中反应不出来。
这⾥做⼀个记录:栈的⽤处:在这⼀步执⾏完成之后,下⼀步需要⽤到上⼀步执⾏的结果,⽤栈来实现往往是最有效的。
以下是转载的内容:深度优先遍历算法的⾮递归实现需要了解深度优先遍历的执⾏过程,设计⼀个栈来模拟递归实现中系统设置的⼯作栈,算法的伪代码描述为:假设图采⽤邻接矩阵作为存储结构,具体算法如下:[cpp]1. 深度优先遍历算法的⾮递归实现需要了解深度优先遍历的执⾏过程,设计⼀个栈来模拟递归实现中系统设置的⼯作栈,算法的伪代码描述为:2.3.4. 假设图采⽤邻接矩阵作为存储结构,具体算法如下:5.6.7. <PRE class=cpp name="code">#include<iostream>8. #include <queue>9. using namespace std;10. #define MAX_NODE 1211. bool visited[MAX_NODE] ;12. int stack[ MAX_NODE] ;13. queue<int> q;14. int Matric[MAX_NODE][MAX_NODE] =15. {16. {-1,1,1,0,0,0,0,0,0,0,0,0},17. {1,-1,1,0,1,1,0,0,0,0,0,0},18. {1,1,-1,1,0,0,0,0,0,0,0,0},19. {0,0,1,-1,1,0,0,0,0,0,1,1},20. {0,1,0,1,-1,0,0,0,0,0,0,0},21. {0,1,0,0,0,-1,0,0,0,0,1,0},22. {0,0,0,0,0,0,-1,1,1,1,0,0},23. {0,0,0,0,0,0,1,-1,0,0,0,0},24. {0,0,0,0,0,0,1,0,-1,1,1,0},25. {0,0,0,0,0,0,1,0,1,-1,0,1},26. {0,0,0,1,0,1,0,0,1,0,-1,0},27. {0,0,0,1,0,0,0,0,0,1,0,-1},28. };29. void DFS( int v)30. {31. cout << " v"<< v ;32. int top = -1 ;33. visited[v] = true ;34. stack[++top] = v ;35. while ( top != -1)36. {37. v = stack[top] ;38. for (int i = 0 ; i < MAX_NODE ; i++)39. {40. if (Matric[v][i] == 1 &&!visited[i])41. {42. cout << " v" << i ;43. visited[i] = true ;44. stack[ ++top ] = i ;45. break ;46. }47. }48. if( i == MAX_NODE)49. {50. top -- ;51. }52. }53.54. }55.56.57. void BFS( int v)58. {59. int node = 0;60. q.push(v);61. visited[v] = true;62. while( !q.empty())63. {64. node = q.front();65. for ( int i = 0; i < MAX_NODE; i++ )66. {67. if ( Matric[node][i] == 1 && !visited[i])68. {69. visited[i] = true;70. q.push(i);71. }72. }73. cout <<" v" << node;74. q.pop();75. }76.77.78. }79. void Init()80. {81.82. int i = 0;83. for ( i = 0; i < MAX_NODE; i++)84. {85. visited[i] = false;86. }87. }88. int main()89. {90. Init();91. DFS( 1 ) ;92. cout << endl ;93. Init();94. BFS( 1 );95. cout << endl;96. Init();97. DFS( 6 );98. cout <<endl;99. return 0 ;100. }</PRE>101. <PRE></PRE>102. <PRE class=cpp name="code"></PRE> 深度优先遍历算法的⾮递归实现需要了解深度优先遍历的执⾏过程,设计⼀个栈来模拟递归实现中系统设置的⼯作栈,算法的伪代码描述为: 假设图采⽤邻接矩阵作为存储结构,具体算法如下:[cpp]1. #include<iostream>2. #include <queue>3. using namespace std;4. #define MAX_NODE 125. bool visited[MAX_NODE] ;6. int stack[ MAX_NODE] ;7. queue<int> q;8. int Matric[MAX_NODE][MAX_NODE] =9. {10. {-1,1,1,0,0,0,0,0,0,0,0,0},11. {1,-1,1,0,1,1,0,0,0,0,0,0},12. {1,1,-1,1,0,0,0,0,0,0,0,0},13. {0,0,1,-1,1,0,0,0,0,0,1,1},14. {0,1,0,1,-1,0,0,0,0,0,0,0},15. {0,1,0,0,0,-1,0,0,0,0,1,0},16. {0,0,0,0,0,0,-1,1,1,1,0,0},17. {0,0,0,0,0,0,1,-1,0,0,0,0},18. {0,0,0,0,0,0,1,0,-1,1,1,0},19. {0,0,0,0,0,0,1,0,1,-1,0,1},20. {0,0,0,1,0,1,0,0,1,0,-1,0},21. {0,0,0,1,0,0,0,0,0,1,0,-1},22. };23. void DFS( int v)24. {25. cout << " v"<< v ;26. int top = -1 ;27. visited[v] = true ;28. stack[++top] = v ;29. while ( top != -1)30. {31. v = stack[top] ;32. for (int i = 0 ; i < MAX_NODE ; i++)33. {34. if (Matric[v][i] == 1 &&!visited[i])35. {36. cout << " v" << i ;37. visited[i] = true ;38. stack[ ++top ] = i ;39. break ;40. }41. }42. if( i == MAX_NODE)43. {44. top -- ;45. }46. }47.48. }49.50.51. void BFS( int v)52. {53. int node = 0;54. q.push(v);55. visited[v] = true;56. while( !q.empty())57. {58. node = q.front();59. for ( int i = 0; i < MAX_NODE; i++ )60. {61. if ( Matric[node][i] == 1 && !visited[i])62. {63. visited[i] = true;64. q.push(i);65. }66. }67. cout <<" v" << node;68. q.pop();69. }70.71.72. }73. void Init()74. {75.76. int i = 0;77. for ( i = 0; i < MAX_NODE; i++)78. {79. visited[i] = false;80. }81. }82. int main()83. {84. Init();85. DFS( 1 ) ;86. cout << endl ;87. Init();88. BFS( 1 );89. cout << endl;90. Init();91. DFS( 6 );92. cout <<endl;93. return 0 ;94. }。
先序遍历的非递归算法先序遍历是二叉树的一种遍历方式,它的步骤是先访问根节点,然后递归地先序遍历左子树,最后递归地先序遍历右子树。
在非递归算法中,我们使用栈来辅助实现遍历。
首先,我们创建一个空栈,将根节点压入栈中。
然后进入循环,循环条件是栈不为空。
在循环中,首先将栈顶元素出栈并访问,然后将其右子节点(如果存在)压入栈中,再将其左子节点(如果存在)压入栈中。
这样可以保证在遍历的过程中,左子树总是先于右子树被访问。
详细的步骤如下:1.创建一个空栈,将根节点压入栈中。
2.进入循环,循环条件为栈不为空。
在循环中执行以下步骤:1.弹出栈顶元素并访问。
2.如果存在右子节点,将右子节点压入栈中。
3.如果存在左子节点,将左子节点压入栈中。
3.循环结束后,遍历完成。
下面是使用非递归算法实现先序遍历的代码:```pythonclass TreeNode:def __init__(self, val=0, left=None, right=None):self.val = valself.left = leftself.right = rightdef preorderTraversal(root):if not root:return []stack = [] # 创建空栈result = [] # 用于存储遍历结果stack.append(root) # 将根节点压入栈中while stack: # 当栈不为空时循环node = stack.pop( # 弹出栈顶元素并访问result.append(node.val)if node.right: # 如果存在右子节点,将右子节点压入栈中stack.append(node.right)if node.left: # 如果存在左子节点,将左子节点压入栈中stack.append(node.left)return result#测试代码#创建二叉树root = TreeNode(1)root.left = TreeNode(2)root.right = TreeNode(3)root.left.left = TreeNode(4)root.left.right = TreeNode(5)#执行先序遍历并输出结果result = preorderTraversal(root)print(result)```运行上述代码可以得到先序遍历的结果:[1,2,4,5,3]。
非递归算法什么是非递归算法?非递归算法是指在计算机程序开发过程中,不使用递归的算法。
递归是指一个自身定义中包含对自身的引用的函数或过程,它可以方便地处理某些问题,但也有缺点,例如产生许多不必要的重复计算,当递归深度过大时容易导致栈溢出等等。
非递归算法常用于对较大数据集的处理,以及在处理树和图等数据结构时。
非递归算法的特点非递归算法具有以下几个特点:1. 显式地控制计算过程非递归算法通过自己的堆栈管理计算过程,这为程序员提供了明确的控制,可以在需要的时候随时中断和恢复计算过程,以及对计算过程进行调试和分析。
这使得非递归算法具有更好的可读性和可维护性。
2. 避免了递归深度过大的问题在递归算法中,深度过大的调用链常导致栈内存的耗尽,从而导致程序的崩溃。
而在非递归算法中,由于递归调用被替换成了循环结构,因此不会产生调用链太长的问题。
3. 速度更快在含有大量数据的情况下,递归算法的效率通常低于循环算法。
而在非递归算法中,通过循环结构的重复执行,可以更快地完成计算。
非递归算法的应用非递归算法适用于解决一些常见问题,例如查找、排序、遍历和优化等等。
下面将对一些常见的应用进行介绍。
1. 查找在查找算法中,非递归算法广泛用于二分查找。
二分查找是一种思想简单、效率高的查找算法。
它的原理是:在一个已排好序的数组中,首先确定一个中间值,再将待查找数据与中间值比较,如果相等就返回,如果小于中间值就查找左半边,否则查找右半边。
通过不断缩小查找的区间,最终可以找到目标元素。
2. 排序在排序算法中,非递归算法可以使用迭代实现快速排序、归并排序以及选择排序,这些算法在大数据集上效果显著。
相比递归算法,非递归算法能够避免频繁的函数调用、内存占用增多的问题,同时也能更好地控制算法的执行。
3. 遍历树和图是数据结构中的两个经典问题,需要对其进行遍历。
遍历算法中,深度优先搜索(DFS)和广度优先搜索(BFS)是两种常见的算法。
在处理大规模图像等需要处理大量节点和连通性的情况下,非递归算法可以更好地应对,而递归算法则容易栈溢出。
数据结构
1、先序遍历的非递归算法。
用c语言写。
void PreOrderUnrec(Bitree t)
{
SqStack s;
StackInit(s);
p=t;
while (p!=null || !StackEmpty(s))
{
while (p!=null) //遍历左子树
{
visite(p->data);
push(s,p);
p=p->lchild;
}//endwhile
if (!StackEmpty(s)) //通过下一次循环中的内嵌while实现右子树遍历{
p=pop(s);
p=p->rchild;
}//endif
}//endwhile
}//PreOrderUnrec
/////////////////////////////////
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#define null 0
struct node
{
char data;
struct node *lchild;
struct node *rchild;
};
//先序,中序建树
struct node *create(char *pre,char *ord,int n)
{
struct node * head;
int ordsit;
head=null;
if(n<=0)
{
return null;
}
else
{
head=(struct node *)malloc(sizeof(struct node));
head->data=*pre;
head->lchild=head->rchild=null;
ordsit=0;
while(ord[ordsit]!=*pre)
{
ordsit++;
}
head->lchild=create(pre+1,ord,ordsit);
head->rchild=create (pre+ordsit+1,ord+ordsit+1,n-ordsit-1); return head;
}
}
//中序递归遍历
void inorder(struct node *head)
{
if(!head)
return;
else
{
inorder(head->lchild );
printf("%c",head->data );
inorder(head->rchild );
}
}
//中序非递归遍历
void inorder1(struct node *head)
{
struct node *p;
struct node *stack[20];
int top=0;
p=head;
while(p||top!=0)
{
while (p)
{
stack[top++]=p;
p=p->lchild ;
}
p=stack[--top];
printf("%c ",p->data );
p=p->rchild ;
}
}
///////////////////////////////////////////////////////////////////////////////////////
二叉树前序、中序、后序三种遍历的非递归算法
1.先序遍历非递归算法
void PreOrderUnrec(Bitree *t)
{
Stack s;
StackInit(s);
Bitree *p=t;
while (p!=NULL || !StackEmpty(s))
{
while (p!=NULL) //遍历左子树
{
visite(p->data);
push(s,p);
p=p->lchild;
}
if (!StackEmpty(s)) //通过下一次循环中的内嵌while实现右子树遍历
{
p=pop(s);
p=p->rchild;
}//endif
}//endwhile
}
2.中序遍历非递归算法
void InOrderUnrec(Bitree *t)
{
Stack s;
StackInit(s);
Bitree *p=t;
while (p!=NULL || !StackEmpty(s))
{
while (p!=NULL) //遍历左子树
{
push(s,p);
p=p->lchild;
}
if (!StackEmpty(s))
{
p=pop(s);
visite(p->data); //访问根结点
p=p->rchild; //通过下一次循环实现右子树遍历}//endif
}//endwhile
}
3.后序遍历非递归算法
typedef enum{L,R} tagtype;
typedef struct
{
Bitree ptr;
tagtype tag;
}stacknode;
typedef struct
{
stacknode Elem[maxsize];
int top;
}SqStack;
void PostOrderUnrec(Bitree t)
SqStack s;
stacknode x;
StackInit(s);
p=t;
do
{
while (p!=null) //遍历左子树
{
x.ptr = p;
x.tag = L; //标记为左子树
push(s,x);
p=p->lchild;
}
while (!StackEmpty(s) && s.Elem[s.top].tag==R)
{
x = pop(s);
p = x.ptr;
visite(p->data); //tag为R,表示右子树访问完毕,故访问根结点}
if (!StackEmpty(s))
{
s.Elem[s.top].tag =R; //遍历右子树
p=s.Elem[s.top].ptr->rchild;
}
}while (!StackEmpty(s));
}//PostOrderUnrec
二。
前序最简洁算法
void PreOrderUnrec(Bitree *t)
{
Bitree *p;
Stack s;
s.push(t);
while (!s.IsEmpty())
{
s.pop(p);
visit(p->data);
if (p->rchild != NULL) s.push(p->rchild);
if (p->lchild != NULL) s.push(p->lchild);
}
三。
后序算法之二
void BT_PostOrderNoRec(pTreeT root)
{
stack<treeT *> s;
pTreeT pre=NULL;
while ((NULL != root) || !s.empty())
{
if (NULL != root)
{
s.push(root);
root = root->left;
}
else
{
root = s.top();
if (root->right!=NULL && pre!=root->right){ root=root->right;
}
else{
root=pre=s.top();
visit(root);
s.pop();
root=NULL;
}
}
}
}。