用递归和非递归算法实现二叉树的三种遍历
数据结构实验五(二叉树的建立及遍历)题目和源程序

实验5:二叉树的建立及遍历(第十三周星期三7、8节)一、实验目的1.学会实现二叉树结点结构和对二叉树的基本操作。
2.掌握对二叉树每种操作的具体实现,学会利用递归方法编写对二叉树这种递归数据结构进行处理的算法。
二、实验要求1.认真阅读和掌握和本实验相关的教材内容。
2.编写完整程序完成下面的实验内容并上机运行。
3.整理并上交实验报告。
三、实验内容1.编写程序任意输入二叉树的结点个数和结点值,构造一棵二叉树,采用三种递归遍历算法(前序、中序、后序)对这棵二叉树进行遍历并计算出二叉树的高度。
2 .编写程序生成下面所示的二叉树,并采用中序遍历的非递归算法对此二叉树进行遍历。
四、思考与提高1.如何计算二叉链表存储的二叉树中度数为1的结点数?2.已知有—棵以二叉链表存储的二叉树,root指向根结点,p指向二叉树中任一结点,如何求从根结点到p所指结点之间的路径?/*----------------------------------------* 05-1_递归遍历二叉树.cpp -- 递归遍历二叉树的相关操作* 对递归遍历二叉树的每个基本操作都用单独的函数来实现* 水上飘2009年写----------------------------------------*/// ds05.cpp : Defines the entry point for the console application.//#include "stdafx.h"#include <iostream>typedef char ElemType;using namespace std;typedef struct BiTNode {ElemType data;//左右孩子指针BiTNode *lchild, *rchild;}BiTNode, *BiTree;//动态输入字符按先序创建二叉树void CreateBiTree(BiTree &T) {char ch;ch = cin.get();if(ch == ' ') {T = NULL;}else {if(ch == '\n') {cout << "输入未结束前不要输入回车,""要结束分支请输入空格!" << endl;}else {//生成根结点T = (BiTNode * )malloc(sizeof(BiTNode));if(!T)cout << "内存分配失败!" << endl;T->data = ch;//构造左子树CreateBiTree(T->lchild);//构造右子树CreateBiTree(T->rchild);}}}//输出e的值ElemType PrintElement(ElemType e) { cout << e << " ";return e;}//先序遍历void PreOrderTraverse(BiTree T) { if (T != NULL) {//打印结点的值PrintElement(T->data);//遍历左孩子PreOrderTraverse(T->lchild);//遍历右孩子PreOrderTraverse(T->rchild);}}//中序遍历void InOrderTraverse(BiTree T) {if (T != NULL) {//遍历左孩子InOrderTraverse(T->lchild);//打印结点的值PrintElement(T->data);//遍历右孩子InOrderTraverse(T->rchild);}}//后序遍历void PostOrderTraverse(BiTree T) { if (T != NULL) {//遍历左孩子PostOrderTraverse(T->lchild);//遍历右孩子PostOrderTraverse(T->rchild);//打印结点的值PrintElement(T->data);}}//按任一种遍历次序输出二叉树中的所有结点void TraverseBiTree(BiTree T, int mark) {if(mark == 1) {//先序遍历PreOrderTraverse(T);cout << endl;}else if(mark == 2) {//中序遍历InOrderTraverse(T);cout << endl;}else if(mark == 3) {//后序遍历PostOrderTraverse(T);cout << endl;}else cout << "选择遍历结束!" << endl;}//输入值并执行选择遍历函数void ChoiceMark(BiTree T) {int mark = 1;cout << "请输入,先序遍历为1,中序为2,后序为3,跳过此操作为0:";cin >> mark;if(mark > 0 && mark < 4) {TraverseBiTree(T, mark);ChoiceMark(T);}else cout << "此操作已跳过!" << endl;}//求二叉树的深度int BiTreeDepth(BiTNode *T) {if (T == NULL) {//对于空树,返回0并结束递归return 0;}else {//计算左子树的深度int dep1 = BiTreeDepth(T->lchild);//计算右子树的深度int dep2 = BiTreeDepth(T->rchild);//返回树的深度if(dep1 > dep2)return dep1 + 1;elsereturn dep2 + 1;}}int _tmain(int argc, _TCHAR* argv[]){BiTNode *bt;bt = NULL; //将树根指针置空cout << "输入规则:" << endl<< "要生成新结点,输入一个字符,""不要生成新结点的左孩子,输入一个空格,""左右孩子都不要,输入两个空格,""要结束,输入多个空格(越多越好),再回车!"<< endl << "按先序输入:";CreateBiTree(bt);cout << "树的深度为:" << BiTreeDepth(bt) << endl;ChoiceMark(bt);return 0;}/*----------------------------------------* 05-2_构造二叉树.cpp -- 构造二叉树的相关操作* 对构造二叉树的每个基本操作都用单独的函数来实现* 水上飘2009年写----------------------------------------*/// ds05-2.cpp : Defines the entry point for the console application.//#include "stdafx.h"#include <iostream>#define STACK_INIT_SIZE 100 //栈的存储空间初始分配量#define STACKINCREMENT 10 //存储空间分配增量typedef char ElemType; //元素类型using namespace std;typedef struct BiTNode {ElemType data; //结点值BiTNode *lchild, *rchild; //左右孩子指针}BiTNode, *BiTree;typedef struct {BiTree *base; //在栈构造之前和销毁之后,base的值为空BiTree *top; //栈顶指针int stacksize; //当前已分配的存储空间,以元素为单位}SqStack;//构造一个空栈void InitStack(SqStack &s) {s.base = (BiTree *)malloc(STACK_INIT_SIZE * sizeof(BiTree));if(!s.base)cout << "存储分配失败!" << endl;s.top = s.base;s.stacksize = STACK_INIT_SIZE;}//插入元素e为新的栈顶元素void Push(SqStack &s, BiTree e) {//栈满,追加存储空间if ((s.top - s.base) >= s.stacksize) {s.base = (BiTree *)malloc((STACK_INIT_SIZE+STACKINCREMENT) * sizeof(BiTree));if(!s.base)cout << "存储分配失败!" << endl;s.top = s.base + s.stacksize;s.stacksize += STACK_INIT_SIZE;}*s.top++ = e;}//若栈不空,则删除s的栈顶元素,并返回其值BiTree Pop(SqStack &s) {if(s.top == s.base)cout << "栈为空,无法删除栈顶元素!" << endl;s.top--;return *s.top;}//按先序输入字符创建二叉树void CreateBiTree(BiTree &T) {char ch;//接受输入的字符ch = cin.get();if(ch == ' ') {//分支结束T = NULL;} //if' 'endelse if(ch == '\n') {cout << "输入未结束前不要输入回车,""要结束分支请输入空格!(接着输入)" << endl;} //if'\n'endelse {//生成根结点T = (BiTNode * )malloc(sizeof(BiTree));if(!T)cout << "内存分配失败!" << endl;T->data = ch;//构造左子树CreateBiTree(T->lchild);//构造右子树CreateBiTree(T->rchild);} //Create end}//输出e的值,并返回ElemType PrintElement(ElemType e) {cout << e << " ";return e;}//中序遍历二叉树的非递归函数void InOrderTraverse(BiTree p, SqStack &S) {cout << "中序遍历结果:";while(S.top != S.base || p != NULL) {if(p != NULL) {Push(S,p);p = p->lchild;} //if NULL endelse {BiTree bi = Pop(S);if(!PrintElement(bi->data))cout << "输出其值未成功!" << endl;p = bi->rchild;} //else end} //while endcout << endl;}int _tmain(int argc, _TCHAR* argv[]){BiTNode *bt;SqStack S;InitStack(S);bt = NULL; //将树根指针置空cout << "老师要求的二叉树序列(‘空’表示空格):""12空空346空空空5空空,再回车!"<< endl << "请按先序输入一个二叉树序列(可另输入,但要为先序),""无左右孩子则分别输入空格。
二叉树遍历(前序、中序、后序、层次、广度优先、深度优先遍历)

⼆叉树遍历(前序、中序、后序、层次、⼴度优先、深度优先遍历)⽬录转载:⼆叉树概念⼆叉树是⼀种⾮常重要的数据结构,⾮常多其他数据结构都是基于⼆叉树的基础演变⽽来的。
对于⼆叉树,有深度遍历和⼴度遍历,深度遍历有前序、中序以及后序三种遍历⽅法,⼴度遍历即我们寻常所说的层次遍历。
由于树的定义本⾝就是递归定义,因此採⽤递归的⽅法去实现树的三种遍历不仅easy理解并且代码⾮常简洁,⽽对于⼴度遍历来说,须要其他数据结构的⽀撑。
⽐⽅堆了。
所以。
对于⼀段代码来说,可读性有时候要⽐代码本⾝的效率要重要的多。
四种基本的遍历思想前序遍历:根结点 ---> 左⼦树 ---> 右⼦树中序遍历:左⼦树---> 根结点 ---> 右⼦树后序遍历:左⼦树 ---> 右⼦树 ---> 根结点层次遍历:仅仅需按层次遍历就可以⽐如。
求以下⼆叉树的各种遍历前序遍历:1 2 4 5 7 8 3 6中序遍历:4 2 7 5 8 1 3 6后序遍历:4 7 8 5 2 6 3 1层次遍历:1 2 3 4 5 6 7 8⼀、前序遍历1)依据上⽂提到的遍历思路:根结点 ---> 左⼦树 ---> 右⼦树,⾮常easy写出递归版本号:public void preOrderTraverse1(TreeNode root) {if (root != null) {System.out.print(root.val+" ");preOrderTraverse1(root.left);preOrderTraverse1(root.right);}}2)如今讨论⾮递归的版本号:依据前序遍历的顺序,优先訪问根结点。
然后在訪问左⼦树和右⼦树。
所以。
对于随意结点node。
第⼀部分即直接訪问之,之后在推断左⼦树是否为空,不为空时即反复上⾯的步骤,直到其为空。
若为空。
则须要訪问右⼦树。
注意。
在訪问过左孩⼦之后。
二叉树前中后序遍历做题技巧

二叉树前中后序遍历做题技巧在计算机科学中,二叉树是一种重要的数据结构,而前序、中序和后序遍历则是二叉树遍历的三种主要方式。
下面将分别对这三种遍历方式进行解析,并提供一些解题技巧。
1.理解遍历顺序前序遍历顺序是:根节点->左子树->右子树中序遍历顺序是:左子树->根节点->右子树后序遍历顺序是:左子树->右子树->根节点理解每种遍历顺序是解题的基础。
2.使用递归或迭代二叉树的遍历可以通过递归或迭代实现。
在递归中,每个节点的处理函数会调用其左右子节点的处理函数。
在迭代中,可以使用栈来模拟递归过程。
3.辨析指针指向在递归或迭代中,需要正确处理指针的指向。
在递归中,通常使用全局变量或函数参数传递指针。
在迭代中,需要使用栈或其他数据结构保存指针。
4.学会断点续传在处理大规模数据时,为了避免内存溢出,可以采用断点续传的方式。
即在遍历过程中,将中间结果保存在文件中,下次遍历时从文件中读取上一次的结果,继续遍历。
5.识别循环和终止条件在遍历二叉树时,要识别是否存在循环,并确定终止条件。
循环可以通过深度优先搜索(DFS)或广度优先搜索(BFS)避免。
终止条件通常为达到叶子节点或达到某个深度限制。
6.考虑边界情况在处理二叉树遍历问题时,要考虑边界情况。
例如,对于空二叉树,需要进行特殊处理。
又如,在处理二叉搜索树时,需要考虑节点值的最小和最大边界。
7.优化空间使用在遍历二叉树时,需要优化空间使用。
例如,可以使用in-place排序来避免额外的空间开销。
此外,可以使用懒加载技术来延迟加载子节点,从而减少内存占用。
8.验证答案正确性最后,验证答案的正确性是至关重要的。
可以通过检查输出是否符合预期、是否满足题目的限制条件等方法来验证答案的正确性。
如果可能的话,也可以使用自动化测试工具进行验证。
二叉树遍历(前中后序遍历,三种方式)

⼆叉树遍历(前中后序遍历,三种⽅式)⽬录刷题中碰到⼆叉树的遍历,就查找了⼆叉树遍历的⼏种思路,在此做个总结。
对应的LeetCode题⽬如下:,,,接下来以前序遍历来说明三种解法的思想,后⾯中序和后续直接给出代码。
⾸先定义⼆叉树的数据结构如下://Definition for a binary tree node.struct TreeNode {int val;TreeNode *left;TreeNode *right;TreeNode(int x) : val(x), left(NULL), right(NULL) {}};前序遍历,顺序是“根-左-右”。
使⽤递归实现:递归的思想很简单就是我们每次访问根节点后就递归访问其左节点,左节点访问结束后再递归的访问右节点。
代码如下:class Solution {public:vector<int> preorderTraversal(TreeNode* root) {if(root == NULL) return {};vector<int> res;helper(root,res);return res;}void helper(TreeNode *root, vector<int> &res){res.push_back(root->val);if(root->left) helper(root->left, res);if(root->right) helper(root->right, res);}};使⽤辅助栈迭代实现:算法为:先把根节点push到辅助栈中,然后循环检测栈是否为空,若不空,则取出栈顶元素,保存值到vector中,之后由于需要想访问左⼦节点,所以我们在将根节点的⼦节点⼊栈时要先经右节点⼊栈,再将左节点⼊栈,这样出栈时就会先判断左⼦节点。
代码如下:class Solution {public:vector<int> preorderTraversal(TreeNode* root) {if(root == NULL) return {};vector<int> res;stack<TreeNode*> st;st.push(root);while(!st.empty()){//将根节点出栈放⼊结果集中TreeNode *t = st.top();st.pop();res.push_back(t->val);//先⼊栈右节点,后左节点if(t->right) st.push(t->right);if(t->left) st.push(t->left);}return res;}};Morris Traversal⽅法具体的详细解释可以参考如下链接:这种解法可以实现O(N)的时间复杂度和O(1)的空间复杂度。
二叉树常用的三种遍历方法

二叉树常用的三种遍历方法二叉树是一种常用的数据结构,它由一个根节点和两个子节点组成,其中左子节点小于根节点,右子节点大于根节点。
遍历二叉树是对所有节点进行访问的过程,常用的三种遍历方法是前序遍历、中序遍历和后序遍历。
下面将详细介绍这三种方法的实现步骤。
一、前序遍历前序遍历是指先访问根节点,然后按照左子树、右子树的顺序依次访问每个节点。
具体实现步骤如下:1. 如果当前节点为空,则返回。
2. 访问当前节点。
3. 递归进入左子树。
4. 递归进入右子树。
代码实现:void preorderTraversal(TreeNode* root) {if (root == NULL) return;cout << root->val << " ";preorderTraversal(root->left);preorderTraversal(root->right);}二、中序遍历中序遍历是指先访问左子树,然后访问根节点,最后访问右子树。
具体实现步骤如下:1. 如果当前节点为空,则返回。
2. 递归进入左子树。
3. 访问当前节点。
4. 递归进入右子树。
代码实现:void inorderTraversal(TreeNode* root) {if (root == NULL) return;inorderTraversal(root->left);cout << root->val << " ";inorderTraversal(root->right);}三、后序遍历后序遍历是指先访问左子树,然后访问右子树,最后访问根节点。
具体实现步骤如下:1. 如果当前节点为空,则返回。
2. 递归进入左子树。
3. 递归进入右子树。
4. 访问当前节点。
代码实现:void postorderTraversal(TreeNode* root) {if (root == NULL) return;postorderTraversal(root->left);postorderTraversal(root->right);cout << root->val << " ";}总结:以上就是二叉树常用的三种遍历方法的详细介绍和实现步骤。
二叉树的各种遍历算法及其深度算法

二叉树的各种遍历算法及其深度算法一、二叉树的遍历算法二叉树是一种常见的数据结构,遍历二叉树可以按照根节点的访问顺序将二叉树的结点访问一次且仅访问一次。
根据遍历的顺序不同,二叉树的遍历算法可以分为三种:前序遍历、中序遍历和后序遍历。
1. 前序遍历(Pre-order Traversal):首先访问根节点,然后遍历左子树,最后遍历右子树。
可以用递归或者栈来实现。
2. 中序遍历(In-order Traversal):首先遍历左子树,然后访问根节点,最后遍历右子树。
可以用递归或者栈来实现。
3. 后序遍历(Post-order Traversal):首先遍历左子树,然后遍历右子树,最后访问根节点。
可以用递归或者栈来实现。
二、二叉树的深度算法二叉树的深度,也叫做高度,指的是从根节点到叶子节点的最长路径上的节点数目。
可以使用递归或者层次遍历的方式来计算二叉树的深度。
1.递归算法:二叉树的深度等于左子树的深度和右子树的深度的较大值加一、递归的终止条件是当节点为空时,深度为0。
递归的过程中通过不断递归左子树和右子树,可以求出二叉树的深度。
2.层次遍历算法:层次遍历二叉树时,每遍历完一层节点,深度加一、使用一个队列来辅助层次遍历,先将根节点加入队列,然后依次取出队列中的节点,将其左右子节点加入队列,直到队列为空,完成层次遍历。
三、示例为了更好地理解二叉树的遍历和求深度的算法,我们以一个简单的二叉树为例进行说明。
假设该二叉树的结构如下:A/\BC/\/\DEFG其中,A、B、C、D、E、F、G分别代表二叉树的结点。
1.前序遍历:A->B->D->E->C->F->G2.中序遍历:D->B->E->A->F->C->G3.后序遍历:D->E->B->F->G->C->A4.深度:2以上是针对这个二叉树的遍历和深度的计算示例。
二叉树的遍历学习心得 (4)

二叉树的遍历学习心得 (4)二叉树是一种重要的数据结构,在计算机科学领域中被广泛应用。
对二叉树的遍历是对树进行操作和处理的重要方法之一。
二叉树遍历包括先序遍历、中序遍历和后序遍历三种,每种遍历方式都有它的特点和应用场景。
在本文中,我将结合自己的学习经历,介绍二叉树遍历的相关知识,并分享我的学习心得。
一、什么是二叉树遍历?二叉树遍历指的是按照某种次序访问二叉树的所有节点。
具体来说,遍历过程中所有节点都会被访问且只会被访问一次。
遍历是二叉树最基本的操作之一,它能够帮助我们遍历整个二叉树,并且可以实现二叉树的各种功能。
二、二叉树遍历的种类1. 先序遍历:先访问根节点,然后按照左子树到右子树的顺序依次访问所有的节点。
2. 中序遍历:按照左子树、根节点、右子树的顺序依次访问所有的节点。
3. 后序遍历:按照左子树、右子树、根节点的顺序依次访问所有的节点。
在学习二叉树遍历时,首先需要掌握各种遍历方式的定义和遍历过程。
我们需要了解如何通过递归或非递归的方式来实现二叉树的遍历。
三、学习心得在学习二叉树遍历时,我发现遍历过程中需要注意以下几点:1. 二叉树的遍历是递归算法的经典应用之一。
在递归调用时,需要注意传递和保存上一层函数中的参数和变量,以及返回值的传递和处理。
2. 在遍历时需要针对每个节点进行相应的操作,比如修改节点值、计算节点的数值、输出节点信息等等。
3. 非递归遍历时需要使用栈或队列辅助存储节点信息,在遍历时需要注意栈或队列的操作和数据结构实现。
通过实践,我逐渐掌握了二叉树遍历的基本思想,学会了如何根据需要选择不同的遍历方式。
同时,我也深刻体会到学习算法需要循序渐进、一步步地进行,并且需要强化巩固,多多实践才能真正掌握。
四、总结二叉树遍历是数据结构中的重要主题之一,是学习和掌握二叉树等数据结构算法的基础。
学习时需要理解各种遍历方式的定义和遍历过程,对递归和非递归实现进行深入的练习和掌握,通过不断地巩固和实践,最终能够掌握二叉树遍历的基本思想和实现方法。
二叉树的遍历PPT-课件

4 、二叉树的创建算法
利用二叉树前序遍历的结果可以非常方便地生成给定的
二叉树,具体做法是:将第一个输入的结点作为二叉树的 根结点,后继输入的结点序列是二叉树左子树前序遍历的 结果,由它们生成二叉树的左子树;再接下来输入的结点 序列为二叉树右子树前序遍历的结果,应该由它们生成二 叉树的右子树;而由二叉树左子树前序遍历的结果生成二 叉树的左子树和由二叉树右子树前序遍历的结果生成二叉 树的右子树的过程均与由整棵二叉树的前序遍历结果生成 该二叉树的过程完全相同,只是所处理的对象范围不同, 于是完全可以使用递归方式加以实现。
void createbintree(bintree *t) { char ch; if ((ch=getchar())==' ') *t=NULL; else { *t=(bintnode *)malloc(sizeof(bintnode)); /*生成二叉树的根结点*/ (*t)->data=ch; createbintree(&(*t)->lchild); /*递归实现左子树的建立*/ createbintree(&(*t)->rchild); /*递归实现右子树的建立*/ }
if (s.top>-1) { t=s.data[s.top]; s.tag[s.top]=1; t=t->rchild; }
else t=NULL; }
}
7.5 二叉树其它运算的实现
由于二叉树本身的定义是递归的,因此关于二叉树的许多 问题或运算采用递归方式实现非常地简单和自然。 1、二叉树的查找locate(t,x)
(1)对一棵二叉树中序遍历时,若我们将二叉树严
格地按左子树的所有结点位于根结点的左侧,右子树的所
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
○A ○C○D ○B○E○F○G《数据结构与算法》实验报告三——二叉树的操作与应用一.实验目的熟悉二叉链表存储结构的特征,掌握二叉树遍历操作及其应用二. 实验要求(题目)说明:以下题目中(一)为全体必做,(二)(三)任选其一完成(一)从键盘输入二叉树的扩展先序遍历序列,建立二叉树的二叉链表存储结构;(二)分别用递归和非递归算法实现二叉树的三种遍历;(三)模拟WindowsXP资源管理器中的目录管理方式,模拟实际创建目录结构,并以二叉链表形式存储,按照凹入表形式打印目录结构(以扩展先序遍历序列输入建立二叉链表结构),如下图所示: (基本要求:限定目录名为单字符;扩展:允许目录名是多字符组合)三. 分工说明一起编写、探讨流程图,根据流程图分工编写算法,共同讨论修改,最后上机调试修改。
四. 概要设计实现算法,需要链表的抽象数据类型:ADT Binarytree {数据对象:D是具有相同特性的数据元素的集合数据关系R:若D为空集,则R为空集,称binarytree为空二叉树;若D不为空集,则R为{H},H是如下二元关系;(1)在D中存在唯一的称为根的数据元素root,它在关系H下无前驱;(2)若D-{root}不为空,则存在D-{root}={D1,Dr},且D1∩Dr为空集;(3)若D1不为空,则D1中存在唯一的元素x1,<root,x1>∈H,且存在D1上的关系H1是H的子集;若Dr不为空集,则Dr中存在唯一的元素Xr,<root,Xr>∈H,且存在Dr上的关系Hr为H的子集;H={<root,x1>,<root,Xr>,H1,Hr};(4) (D1,{H1})是一颗符合本定义的二叉树,称为根的左子树,(Dr,{Hr})是一颗符合本定义的二叉树,称为根的右子树。
基本操作:Creatbitree(&S,definition)初始条件:definition给出二叉树S的定义操作结果:按definition构造二叉树Scounter(T)初始条件:二叉树T已经存在操作结果:返回二叉树的总的结点数onecount(T)初始条件:二叉树T已经存在操作结果:返回二叉树单分支的节点数Clearbintree(S)初始条件:二叉树S已经存在操作结果:将二叉树S清为空树Bitreeempty(S)初始条件:二叉树S已经存在操作结果:若S为空二叉树,则返回TRUE,否则返回FALSEBitreedepth(S,&e)初始条件:二叉树S已经存在操作结果:返回S的深度Parent(S)初始条件:二叉树S已经存在,e是S中的某个结点操作结果:若e是T的非根结点,则返回它的双亲,否则返回空Preordertraverse(S)初始条件:二叉树S已经存在,Visit是对结点操作的应用函数。
操作结果:先序遍历S,对每个结点调用函数visit一次且仅一次。
一旦visit失败,则操作失败。
Inordertraverse (S,&e)初始条件:二叉树S已经存在,Visit是对结点操作的应用函数。
操作结果:中序遍历S,对每个结点调用函数visit一次且仅一次。
一旦visit失败,则操作失败。
Postordertraverse (&S,e)初始条件:二叉树S已经存在,Visit是对结点操作的应用函数。
操作结果:后序遍历S,对每个结点调用函数visit一次且仅一次。
一旦visit失败,则操作失败。
}ADT Binarytree五、详细设计扩展先序遍历:# include<stdio.h># include<stdlib.h>#include<string.h>typedef struct binarytree{char data;struct binarytree *lchild,*rchild;}BiTreeNode,*BiTree;void CreateBiTree(BiTree *bt){char ch;ch=getchar();if(ch=='.') *bt=NULL;else{*bt=(BiTreeNode *)malloc(sizeof(BiTreeNode));(*bt)->data=ch;CreateBiTree(&((*bt)->lchild));CreateBiTree(&((*bt)->rchild));}}void PreOder(BiTree root){if(root!=NULL){printf("%4c",root->data);PreOder(root->lchild);PreOder(root->rchild);}}main(){BiTree root;CreateBiTree(&root);printf("先序遍历:\n");PreOder(root);}递归算法:#include"stdio.h"#define PR printf#define ERROR 0#define MAX 100/*============================建立各结构体===============================*/ typedef struct node{char data; /*数据域*/struct node *lchild;struct node *rchild; /*结点的左右指针,分别指向结点的左右孩子*/}BTNode;typedef BTNode *DataType;typedef struct{DataType data[MAX];int top;}SeqStack;SeqStack *s;/*============================栈的操作===================================*/SeqStack *createemptystacks() /*创建一个空栈*/{SeqStack *s;s=(SeqStack*)malloc(sizeof(SeqStack));s->top=0;return s;}int stackemptys(SeqStack *s) /*判栈空*/{return s->top==0;}int stackfulls(SeqStack *s) /*判栈满*/{return s->top==MAX;}void pushs(SeqStack *s,DataType x) /*进栈*/{if(stackfulls(s))PR("over flow\n");elses->data[s->top++]=x;}void pops(SeqStack *s) /*退栈*/{if(stackemptys(s))PR("underflow\n");elses->top--;}DataType gettops(SeqStack *s) /*栈非空时取栈顶元素*/{return s->data[s->top-1];}/*============================建立二叉树==================================*/BTNode *createbintree() /*输入扩充的先序序列,建立二叉树*/ {BTNode *t;char x;scanf("%c",&x);if(x=='#')t=NULL; /*读入#,返回空指针 */else{t=(BTNode *)malloc(sizeof(BTNode)); /*生成结点*/ t->data=x;t->lchild=createbintree(); /*构造左子树*/t->rchild=createbintree(); /*构造右子树*/ }return(t);}/*==============================树的遍历===================================*/void preorder(BTNode *t) /*NLR 先序遍历*/{if(t!=NULL){PR(" %c\t",t->data); /*访问结点*/preorder(t->lchild); /*中序遍历左子树*/preorder(t->rchild); /*中序遍历右子树*/}}/*========================================================================= */void inorder(BTNode *t) /*LNR 中序遍历*/{if(t!=NULL){inorder(t->lchild); /*中序遍历左子树*/PR(" %c\t",t->data); /*访问结点*/inorder(t->rchild); /*中序遍历右子树*/}}/*========================================================================= */void postorder(BTNode *t) /*LRN 后序遍历*/{if(t!=NULL){postorder(t->lchild); /*后序遍历左子树*/postorder(t->rchild); /*后序遍历右子树*/PR(" %c\t",t->data); /*访问结点*/}}/*===============================主函数=============================-=======*/void main(){BTNode *t;int n=0;PR(" ->> 请输入二叉树各元素:(例如 abd##e##cf##g##)\n"); //例如abd##e##cf##g##t=createbintree();PR("\n\n ->> 1.按先序遍历输出为:\n");preorder(t); /*NLR 先序遍历*/PR("\n 按中序遍历输出为:\n");inorder(t); /*LNR 中序遍历*/PR("\n 按后序遍历输出为:\n");postorder(t); /*LRN 后序遍历*/}# include<stdio.h># include<stdlib.h># include<string.h># define TRUE 1# define FALSE 0# define Stack_Size 50# define NUM 20typedef struct binarytree /*定义一棵二叉树*/{char data;struct binarytree *LChild,*RChild;}BiTNode,*BiTree;typedef struct /*定义顺序栈S*/{BiTree data[Stack_Size];int top;}SeqStack;void CreateBiTree(BiTree &bt) /*利用“扩展先序遍历”创建二叉链表*/{char ch;ch=getchar(); /*调用getchar函数,需要用户输入字符,用户按回车键结束输入*/if(ch=='.') bt=NULL;else{bt=(BiTNode *)malloc(sizeof(BiTNode));bt->data=ch;CreateBiTree(bt->LChild);CreateBiTree(bt->RChild);}}void InitStack(SeqStack &S) /*初始化顺序栈S*/ {S.top=-1;}int IsEmpty(SeqStack S) /*判栈空*/{return(S.top==-1? TRUE:FALSE);}int Push(SeqStack &S,BiTree &x) /*进栈*/{if(S.top==Stack_Size-1)return(FALSE);S.top++;S.data[S.top]=x;return(TRUE);}int Pop(SeqStack &S,BiTree &x) /*出栈*/{if(S.top==-1)return(FALSE);else{x=S.data[S.top];S.top--;return(TRUE);}}void PreOrder(BiTree root) /*先序遍历非递归*/ {BiTNode *p;SeqStack S;p=root;InitStack(S);while(p!=NULL||!IsEmpty(S)){while(p!=NULL){printf("%4c",p->data);Push(S,p);p=p->LChild;}if(IsEmpty(S))return;Pop(S,p);p=p->RChild;}}void InOrder(BiTree root) /*中序遍历非递归*/{BiTNode *p;SeqStack S;InitStack(S);p=root;while(p!=NULL || ! IsEmpty(S)){if(p!=NULL){Push(S,p);p=p->LChild;}else{Pop(S,p);printf("%4c",p->data);p=p->RChild;}}}void PostOrder(BiTree root) /*后序遍历非递归*/{BiTNode *p,*q;BiTNode **S;int top=0;q=NULL;p=root;S=(BiTNode**)malloc(sizeof(BiTNode*)*NUM); /*NUM为预定义的常数*/ while(p!=NULL || top!=0){while(p!=NULL){top++;S[top]=p;p=p->LChild;}if(top>0){p=S[top];if((p->RChild==NULL)||(p->RChild==q)){printf("%4c",p->data);q=p;top--;p=NULL;}elsep=p->RChild;}}free(S);}void main() /*主函数部分*/{loop:BiTree root=NULL;CreateBiTree(root);printf("PreOrder traversal is:\n");PreOrder(root);printf("\n");printf("InOrder traversal is:\n");InOrder(root);printf("\n");printf("PostOrder traversal is:\n");PostOrder(root);printf("\n");printf("Please input a new one:\n");char c=getchar();goto loop;}实现概要设计中定义的所有的数据类型,对每个操作给出伪码算法或算法流程图。