C++二叉树的前序,中序,后序,层序遍历的递归算法55555
- 格式:doc
- 大小:57.00 KB
- 文档页数:4
标题:前序序列、中序序列和后序序列的规律分析1.概述前序序列、中序序列和后序序列是树的三种遍历方式,它们分别描述了在树结构中节点的访问顺序。
这三种遍历方式具有一定的规律,本文将对这些规律进行分析和总结。
2.前序序列、中序序列和后序序列的定义2.1 前序序列:节点的访问顺序是先访问根节点,然后依次访问左子树和右子树。
2.2 中序序列:节点的访问顺序是先访问左子树,然后访问根节点,最后访问右子树。
2.3 后序序列:节点的访问顺序是先访问左子树,然后访问右子树,最后访问根节点。
3.前序序列、中序序列和后序序列的规律分析3.1 规律一:对于任意一颗树,它的前序序列中的第一个节点必定是根节点。
3.2 规律二:对于任意一颗树,它的中序序列中,根节点的位置将左右子树分割开来。
3.3 规律三:对于任意一颗树,它的后序序列中的最后一个节点必定是根节点。
3.4 规律四:对于同一颗树,其前序序列和后序序列的第二个节点是该树的左子树的根节点。
4.应用举例4.1 求解建立二叉树4.1.1 根据前序序列和中序序列建立二叉树4.1.2 根据中序序列和后序序列建立二叉树4.2 根据前序序列和后序序列求解树的唯一性5.总结前序序列、中序序列和后序序列的规律分析,有助于我们更好地理解树的结构和遍历方式,从而在树的操作中提供了很好的指导。
在实际应用中,可根据这些规律来建立二叉树,求解树的唯一性等问题。
希望通过对这些规律的深入理解,能够更加灵活地应用于相关领域的问题解决中。
6.参考文献[1] 《数据结构与算法分析》,作者:Mark Allen Weiss[2] 《算法导论》,作者:Thomas H. Cormen, Charles E. Leiserson, Ronald L. Rivest, Clifford Stein致谢感谢所有对本文撰写提供过帮助的人,包括对数据结构和算法有深入研究的学者们,以及对本文提出宝贵意见和建议的朋友们。
数据结构(⼆⼗四)⼆叉树的链式存储结构(⼆叉链表) ⼀、⼆叉树每个结点最多有两个孩⼦,所以为它设计⼀个数据域和两个指针域,称这样的链表叫做⼆叉链表。
⼆、结点结构包括:lchild左孩⼦指针域、data数据域和rchild右孩⼦指针域。
三、⼆叉链表的C语⾔代码实现:#include "string.h"#include "stdio.h"#include "stdlib.h"#include "io.h"#include "math.h"#include "time.h"#define OK 1#define ERROR 0#define TRUE 1#define FALSE 0#define MAXSIZE 100 /* 存储空间初始分配量 */typedef int Status; /* Status是函数的类型,其值是函数结果状态代码,如OK等 *//* ⽤于构造⼆叉树********************************** */int index=1;typedef char String[24]; /* 0号单元存放串的长度 */String str;Status StrAssign(String T,char *chars){int i;if(strlen(chars)>MAXSIZE)return ERROR;else{T[0]=strlen(chars);for(i=1;i<=T[0];i++)T[i]=*(chars+i-1);return OK;}}/* ************************************************ */typedef char TElemType;TElemType Nil=''; /* 字符型以空格符为空 */Status visit(TElemType e){printf("%c ",e);return OK;}typedef struct BiTNode /* 结点结构 */{TElemType data; /* 结点数据 */struct BiTNode *lchild,*rchild; /* 左右孩⼦指针 */}BiTNode,*BiTree;/* 构造空⼆叉树T */Status InitBiTree(BiTree *T){*T=NULL;return OK;}/* 初始条件: ⼆叉树T存在。
⼆叉树的遍历及常⽤算法⼆叉树的遍历及常⽤算法遍历的定义:按照某种次序访问⼆叉树上的所有结点,且每个节点仅被访问⼀次;遍历的重要性:当我们需要对⼀颗⼆叉树进⾏,插⼊,删除,查找等操作时,通常都需要先遍历⼆叉树,所有说:遍历是⼆叉树的基本操作;遍历思路:⼆叉树的数据结构是递归定义(每个节点都可能包含相同结构的⼦节点),所以遍历也可以使⽤递归,即结点不为空则继续递归调⽤每个节点都有三个域,数据与,左孩⼦指针和右孩⼦之指针,每次遍历只需要读取数据,递归左⼦树,递归右⼦树,这三个操作三种遍历次序:根据访问三个域的不同顺序,可以有多种不同的遍历次序,⽽通常对于⼦树的访问都按照从左往右的顺序;设:L为遍历左⼦树,D为访问根结点,R为遍历右⼦树,且L必须位于R的前⾯可以得出以下三种不同的遍历次序:先序遍历操作次序为DLR,⾸先访问根结点,其次遍历根的左⼦树,最后遍历根右⼦树,对每棵⼦树同样按这三步(先根、后左、再右)进⾏中序遍历操作次序为LDR,⾸先遍历根的左⼦树,其次访问根结点,最后遍历根右⼦树,对每棵⼦树同样按这三步(先左、后根、再右)进⾏后序遍历操作次序为LRD,⾸先遍历根的左⼦树,其次遍历根的右⼦树,最后访问根结点,对每棵⼦树同样按这三步(先左、后右、最后根)进⾏层次遍历层次遍历即按照从上到下从左到右的顺序依次遍历所有节点,实现层次遍历通常需要借助⼀个队列,将接下来要遍历的结点依次加⼊队列中;遍历的应⽤“遍历”是⼆叉树各种操作的基础,可以在遍历过程中对结点进⾏各种操作,如:对于⼀棵已知⼆叉树求⼆叉树中结点的个数求⼆叉树中叶⼦结点的个数;求⼆叉树中度为1的结点个数求⼆叉树中度为2的结点个数5求⼆叉树中⾮终端结点个数交换结点左右孩⼦判定结点所在层次等等...C语⾔实现:#include <stdio.h>//⼆叉链表数据结构定义typedef struct TNode {char data;struct TNode *lchild;struct TNode *rchild;} *BinTree, BinNode;//初始化//传⼊⼀个指针令指针指向NULLvoid initiate(BinTree *tree) {*tree = NULL;}//创建树void create(BinTree *BT) {printf("输⼊当前结点值: (0则创建空节点)\n");char data;scanf(" %c", &data);//连续输⼊整形和字符时.字符变量会接受到换⾏,所以加空格if (data == 48) {*BT = NULL;return;} else {//创建根结点//注意开辟的空间⼤⼩是结构体的⼤⼩⽽不是结构体指针⼤⼩,写错了不会⽴马产⽣问题,但是后续在其中存储数据时极有可能出现内存访问异常(飙泪....) *BT = malloc(sizeof(struct TNode));//数据域赋值(*BT)->data = data;printf("输⼊节点 %c 的左孩⼦ \n", data);create(&((*BT)->lchild));//递归创建左⼦树printf("输⼊节点 %c 的右孩⼦ \n", data);create(&((*BT)->rchild));//递归创建右⼦树}}//求双亲结点(⽗结点)BinNode *Parent(BinTree tree, char x) {if (tree == NULL)return NULL;else if ((tree->lchild != NULL && tree->lchild->data == x) || (tree->rchild != NULL && tree->rchild->data == x))return tree;else{BinNode *node1 = Parent(tree->lchild, x);BinNode *node2 = Parent(tree->rchild, x);return node1 != NULL ? node1 : node2;}}//先序遍历void PreOrder(BinTree tree) {if (tree) {//输出数据printf("%c ", tree->data);//不为空则按顺序继续递归判断该节点的两个⼦节点PreOrder(tree->lchild);PreOrder(tree->rchild);}}//中序void InOrder(BinTree tree) {if (tree) {InOrder(tree->lchild);printf("%c ", tree->data);InOrder(tree->rchild);}}//后序void PostOrder(BinTree tree) {if (tree) {PostOrder(tree->lchild);PostOrder(tree->rchild);printf("%c ", tree->data);}}//销毁结点递归free所有节点void DestroyTree(BinTree *tree) {if (*tree != NULL) {printf("free %c \n", (*tree)->data);if ((*tree)->lchild) {DestroyTree(&((*tree)->lchild));}if ((*tree)->rchild) {DestroyTree(&((*tree)->rchild));}free(*tree);*tree = NULL;}}// 查找元素为X的结点使⽤的是层次遍历BinNode *FindNode(BinTree tree, char x) {if (tree == NULL) {return NULL;}//队列BinNode *nodes[1000] = {};//队列头尾位置int front = 0, real = 0;//将根节点插⼊到队列尾nodes[real] = tree;real += 1;//若队列不为空则继续while (front != real) {//取出队列头结点输出数据BinNode *current = nodes[front];if (current->data == x) {return current;}front++;//若当前节点还有⼦(左/右)节点则将结点加⼊队列if (current->lchild != NULL) {nodes[real] = current->lchild;real++;}if (current->rchild != NULL) {nodes[real] = current->rchild;real++;}}return NULL;}//层次遍历// 查找元素为X的结点使⽤的是层次遍历void LevelOrder(BinTree tree) {if (tree == NULL) {return;}//队列BinNode *nodes[1000] = {};//队列头尾位置int front = 0, real = 0;//将根节点插⼊到队列尾nodes[real] = tree;real += 1;//若队列不为空则继续while (front != real) {//取出队列头结点输出数据BinNode *current = nodes[front];printf("%2c", current->data);front++;//若当前节点还有⼦(左/右)节点则将结点加⼊队列if (current->lchild != NULL) {nodes[real] = current->lchild;real++;}if (current->rchild != NULL) {nodes[real] = current->rchild;real++;}}}//查找x的左孩⼦BinNode *Lchild(BinTree tree, char x) {BinTree node = FindNode(tree, x);if (node != NULL) {return node->lchild;}return NULL;}//查找x的右孩⼦BinNode *Rchild(BinTree tree, char x) {BinTree node = FindNode(tree, x);if (node != NULL) {return node->rchild;}return NULL;}//求叶⼦结点数量int leafCount(BinTree *tree) {if (*tree == NULL)return 0;//若左右⼦树都为空则该节点为叶⼦,且后续不⽤接续递归了else if (!(*tree)->lchild && !(*tree)->rchild)return 1;else//若当前结点存在⼦树,则递归左右⼦树, 结果相加return leafCount(&((*tree)->lchild)) + leafCount(&((*tree)->rchild));}//求⾮叶⼦结点数量int NotLeafCount(BinTree *tree) {if (*tree == NULL)return 0;//若该结点左右⼦树均为空,则是叶⼦,且不⽤继续递归else if (!(*tree)->lchild && !(*tree)->rchild)return 0;else//若当前结点存在左右⼦树,则是⾮叶⼦结点(数量+1),在递归获取左右⼦树中的⾮叶⼦结点,结果相加 return NotLeafCount(&((*tree)->lchild)) + NotLeafCount(&((*tree)->rchild)) + 1;}//求树的⾼度(深度)int DepthCount(BinTree *tree) {if (*tree == NULL)return 0;else{//当前节点不为空则深度+1 在加上⼦树的⾼度,int lc = DepthCount(&((*tree)->lchild)) + 1;int rc = DepthCount(&((*tree)->rchild)) + 1;return lc > rc?lc:rc;// 取两⼦树深度的最⼤值 }}//删除左⼦树void RemoveLeft(BinNode *node){if (!node)return;if (node->lchild)DestroyTree(&(node->lchild));node->lchild = NULL;}//删除右⼦树void RemoveRight(BinNode *node){if (!node)return;if (node->rchild)DestroyTree(&(node->rchild));node->rchild = NULL;}int main() {BinTree tree;create(&tree);BinNode *node = Parent(tree, 'G');printf("G的⽗结点为%c\n",node->data);BinNode *node2 = Lchild(tree, 'D');printf("D的左孩⼦结点为%c\n",node2->data);BinNode *node3 = Rchild(tree, 'D');printf("D的右孩⼦结点为%c\n",node3->data);printf("先序遍历为:");PreOrder(tree);printf("\n");printf("中序遍历为:");InOrder(tree);printf("\n");printf("后序遍历为:");PostOrder(tree);printf("\n");printf("层次遍历为:");LevelOrder(tree);printf("\n");int a = leafCount(&tree);printf("叶⼦结点数为%d\n",a);int b = NotLeafCount(&tree);printf("⾮叶⼦结点数为%d\n",b);int c = DepthCount(&tree);printf("深度为%d\n",c);//查找F节点BinNode *node4 = FindNode(tree,'C');RemoveLeft(node4);printf("删除C的左孩⼦后遍历:");LevelOrder(tree);printf("\n");RemoveRight(node4);printf("删除C的右孩⼦后遍历:");LevelOrder(tree);printf("\n");//销毁树printf("销毁树 \n");DestroyTree(&tree);printf("销毁后后遍历:");LevelOrder(tree);printf("\n");printf("Hello, World!\n");return 0;}测试:测试数据为下列⼆叉树:运⾏程序复制粘贴下列内容:ABDGHECKFIJ特别感谢:iammomo。
数据结构二叉树先序中序后序考研题目
以下是一些关于二叉树先序、中序和后序遍历的考研题目:
1. 已知二叉树的先序遍历序列为 "A B D E C F",中序遍历序列为 "D B E A F C",请画出该二叉树。
2. 已知二叉树的中序遍历序列为 "D B E A F C",后序遍历序列为 "D E B F C A",请画出该二叉树。
3. 给定一棵二叉树的先序遍历序列为 "A B D E F C",中序遍历序列为 "D B E F A C",请写出该二叉树的后序遍历序列。
4. 请写出一棵二叉树的先序遍历序列为 "A B D E C F",中序遍历序列为 "D B E A F C",后序遍历序列为 "D E B F C A" 的二叉树。
5. 已知一棵二叉树的中序遍历序列为 "D B E A F C",后序遍历序列为 "D E B F C A",请写出该二叉树的先序遍历序列。
6. 给定一棵二叉树的先序遍历序列为 "A B D E F C",后序遍历序列为 "D E F B C A",请写出该二叉树的中序遍历序列。
以上题目可以帮助你练习理解二叉树的遍历方式及其序列之间的关系。
⼆叉树遍历(前序、中序、后序、层次、⼴度优先、深度优先遍历)⽬录转载:⼆叉树概念⼆叉树是⼀种⾮常重要的数据结构,⾮常多其他数据结构都是基于⼆叉树的基础演变⽽来的。
对于⼆叉树,有深度遍历和⼴度遍历,深度遍历有前序、中序以及后序三种遍历⽅法,⼴度遍历即我们寻常所说的层次遍历。
由于树的定义本⾝就是递归定义,因此採⽤递归的⽅法去实现树的三种遍历不仅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。
第⼀部分即直接訪问之,之后在推断左⼦树是否为空,不为空时即反复上⾯的步骤,直到其为空。
若为空。
则须要訪问右⼦树。
注意。
在訪问过左孩⼦之后。
数据结构先序中序后序理解数据结构是计算机科学中的重要概念之一,它是指一组数据的组织方式以及对这组数据进行操作的方法。
在学习数据结构的过程中,我们经常会遇到先序、中序和后序这三个概念。
它们是用来描述二叉树的遍历方式的,也可以用来表示表达式的计算顺序。
本文将从先序、中序和后序这三个角度来解释数据结构的含义和应用。
一、先序遍历先序遍历是指按照根节点、左子树、右子树的顺序访问二叉树的节点。
在先序遍历中,我们首先访问根节点,然后递归地遍历左子树和右子树。
先序遍历的应用非常广泛,比如在文件系统的目录结构中,我们可以使用先序遍历来列出所有的文件和文件夹。
二、中序遍历中序遍历是指按照左子树、根节点、右子树的顺序访问二叉树的节点。
在中序遍历中,我们首先递归地遍历左子树,然后访问根节点,最后再递归地遍历右子树。
中序遍历在二叉搜索树的操作中非常常见,它可以按照从小到大的顺序输出二叉搜索树中的元素。
三、后序遍历后序遍历是指按照左子树、右子树、根节点的顺序访问二叉树的节点。
在后序遍历中,我们首先递归地遍历左子树和右子树,最后访问根节点。
后序遍历常用于对二叉树进行一些计算操作,比如计算二叉树的深度、判断二叉树是否对称等。
除了用于二叉树的遍历,先序、中序和后序还可以用来表示表达式的计算顺序。
在数学表达式中,运算符和操作数之间的顺序非常重要,它决定了表达式的计算结果。
先序、中序和后序可以用来表示运算符的位置,从而决定表达式的计算顺序。
先序表示法中,运算符位于操作数之前,如"+ 3 4"表示加法运算。
中序表示法中,运算符位于操作数之间,如"3 + 4"表示加法运算。
后序表示法中,运算符位于操作数之后,如"3 4 +"表示加法运算。
不同的表示法对应着不同的计算顺序,但它们都能得到相同的结果。
先序、中序和后序在数据结构中有着广泛的应用。
它们不仅仅是一种遍历方式,还可以表示表达式的计算顺序。
《数据结构》综合复习资料一、填空题1、数据结构是()。
2、数据结构的四种基本形式为集合、()、()和()。
3、线性结构的基本特征是:若至少含有一个结点,则除起始结点没有直接前驱外,其他结点有且仅有一个直接();除终端结点没有直接()外,其它结点有且仅有一个直接()。
4、堆栈的特点是(),队列的特点是(),字符串中的数据元素为()。
5、字符串s1=“I am a student!”(单词与单词之间一个空格),s2=“student”,则字符串s1的长度为(),串s2是串s1的一个()串,串s2在s1中的位置为()。
6、KMP算法的特点:效率较();()回溯,对主串仅需要从头到尾扫描()遍,可以边读入边匹配。
7、广义表((a),((b),c),(((d))))的长度为(),表头为(),表尾为()。
8、ADT称为抽象数据类型,它是指()。
9、求下列程序的时间复杂度,并用大O表示方法表示()。
for( i=1 ; i<=n ; + + i)for( j=1 ; j<=i; + + j ){ ++x;a[i][j] = x;}10、以下运算实现在链栈上的退栈操作,请在_____处用适当句子予以填充。
int Pop(LstackTp *ls,DataType *x){ LstackTp *p;if(ls!=NULL){ p=ls;*x= ;ls= ;;return(1);}else return(0);}11、用堆栈求中缀表达式a+b*c/d+e*f的后缀表达式,求出的后缀表达式为()。
12、C语言中存储数组是采用以()为主序存储的,在C语言中定义二维数组float a[8][10],每个数据元素占4个字节,则数组共占用()字节的内存。
若第一个数据元素的存储地址为8000,则a[5][8]的存储地址为()。
13、含零个字符的串称为()串,用 表示。
其他串称为()串。
任何串中所含字符的个数称为该串的()。
二叉树的先序,中序,后序遍历c语言
二叉树是常见的数据结构,具有广泛的应用场景,例如搜索树、哈夫曼树等。
其中比较重要的一点就是对二叉树的遍历。
二叉树遍历有三种方式:先序遍历、中序遍历、后序遍历。
接下来,我将通过C语言来详细介绍这三种遍历方式。
一、先序遍历(Preorder Traversal)
先序遍历是指根节点->左子树->右子树的遍历方式。
C语言中的先序遍历算法如下:
```
void preorderTraversal(Node *node) {
if (node != NULL) {
printf("%d ", node->data); // 打印节点值
preorderTraversal(node->left); // 递归遍历左子树
preorderTraversal(node->right); // 递归遍历右子树
}
}
```
先序遍历的实现通过递归调用实现,当节点为空即遍历完成时返回。
总结:
以上三种遍历方式是二叉树遍历中最基本的方法,它们都是基于递归实现的。
通过学习这三种遍历方式,可以更好地理解二叉树的结构特点,提高数据结构算法的学习效果。
⼆叉树遍历(前中后序遍历,三种⽅式)⽬录刷题中碰到⼆叉树的遍历,就查找了⼆叉树遍历的⼏种思路,在此做个总结。
对应的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)的空间复杂度。
c语言二叉树的先序,中序,后序遍历1、先序遍历先序遍历可以想象为,一个小人从一棵二叉树根节点为起点,沿着二叉树外沿,逆时针走一圈回到根节点,路上遇到的元素顺序,就是先序遍历的结果先序遍历结果为:A B D H I E J C F K G2、中序遍历中序遍历可以看成,二叉树每个节点,垂直方向投影下来(可以理解为每个节点从最左边开始垂直掉到地上),然后从左往右数,得出的结果便是中序遍历的结果中遍历结果为:H D I B E J A F K C G3、后序遍历后序遍历就像是剪葡萄,我们要把一串葡萄剪成一颗一颗的。
还记得我上面提到先序遍历绕圈的路线么?(不记得翻上面理解)就是围着树的外围绕一圈,如果发现一剪刀就能剪下的葡萄(必须是一颗葡萄)(也就是葡萄要一个一个掉下来,不能一口气掉超过1个这样),就把它剪下来,组成的就是后序遍历了。
后序遍历中,根节点默认最后面后序遍历结果:H I D J E B K F G C A4、口诀先序遍历:先根再左再右中序遍历:先左再根再右后序遍历:先左再右再根这里的根,指的是每个分叉子树(左右子树的根节点)根节点,并不只是最开始头顶的根节点,需要灵活思考理解5、代码展示#include<stdio.h>#include<stdlib.h>typedef struct Tree{int data; // 存放数据域struct Tree *lchild; // 遍历左子树指针struct Tree *rchild; // 遍历右子树指针}Tree,*BitTree;BitTree CreateLink(){int data;int temp;BitTree T;scanf("%d",&data); // 输入数据temp=getchar(); // 吸收空格if(data == -1){ // 输入-1 代表此节点下子树不存数据,也就是不继续递归创建return NULL;}else{T = (BitTree)malloc(sizeof(Tree)); // 分配内存空间T->data = data; // 把当前输入的数据存入当前节点指针的数据域中printf("请输入%d的左子树: ",data);T->lchild = CreateLink(); // 开始递归创建左子树printf("请输入%d的右子树: ",data);T->rchild = CreateLink(); // 开始到上一级节点的右边递归创建左右子树return T; // 返回根节点}}// 先序遍历void ShowXianXu(BitTree T) // 先序遍历二叉树{if(T==NULL) //递归中遇到NULL,返回上一层节点{return;}printf("%d ",T->data);ShowXianXu(T->lchild); // 递归遍历左子树ShowXianXu(T->rchild); // 递归遍历右子树}// 中序遍历void ShowZhongXu(BitTree T) // 先序遍历二叉树{if(T==NULL) //递归中遇到NULL,返回上一层节点{return;}ShowZhongXu(T->lchild); // 递归遍历左子树printf("%d ",T->data);ShowZhongXu(T->rchild); // 递归遍历右子树}// 后序遍历void ShowHouXu(BitTree T) // 后序遍历二叉树{if(T==NULL) //递归中遇到NULL,返回上一层节点{return;}ShowHouXu(T->lchild); // 递归遍历左子树ShowHouXu(T->rchild); // 递归遍历右子树printf("%d ",T->data);}int main(){BitTree S;printf("请输入第一个节点的数据:\n");S = CreateLink(); // 接受创建二叉树完成的根节点printf("先序遍历结果: \n");ShowXianXu(S); // 先序遍历二叉树printf("\n中序遍历结果: \n");ShowZhongXu(S); // 中序遍历二叉树printf("\n后序遍历结果: \n");ShowHouXu(S); // 后序遍历二叉树return 0;}。
#include <iostream>
using namespace std;
#define queuesize 100
#define ERROR 0
#define OK 1
typedef struct BiTNode//二叉树
{
char data;
struct BiTNode *lchild,*rchild;
}BinNode;
typedef BinNode * BiTree;//定义二叉链表指针类型
typedef struct
{
int front,rear;
BiTree data[queuesize];//循环队列元素类型为二叉链表结点指针
int count;
}cirqueue;//循环队列结构定义
void leverorder(BiTree t)
{
cirqueue *q;
BiTree p;
q=new cirqueue;//申请循环队列空间
q->rear=q->front=q->count=0;//将循环队列初始化为空
q->data[q->rear]=t;q->count++;q->rear=(q->rear+1)%queuesize;//将根结点入队
while (q->count) //若队列不为空,做以下操作
if (q->data[q->front]) //当队首元素不为空指针,做以下操作
{
p=q->data[q->front]; //取队首元素*p
cout<<p->data;
q->front=(q->front+1)%queuesize;q->count--;//队首元素出队
if (q->count==queuesize)//若队列为队满,则打印队满信息,退出程序的执行cout<<"error,队列满了!";
else
{//若队列不满,将*p结点的左孩子指针入队
q->count++;q->data[q->rear]=p->lchild;
q->rear=(q->rear+1)%queuesize;
}
if (q->count==queuesize)//若队列为队满,则打印队满信息,退出程序的执行cout<<"error";
else
{//若队列不满,将*p结点的右孩子指针入队
q->count++;q->data[q->rear]=p->rchild;
q->rear=(q->rear+1)%queuesize;
}
}
else
{q->front=(q->front+1)%queuesize;q->count--;}//当队首元素为空指针,将空指针出队}
int CreatBiTree(BiTree& root)
{
char ch;
BiTree p;
BiTree q[100];
int front=1,rear=0;
int jj=0;
ch=getchar();
while(ch!='#')
{
p=NULL;
if(ch!=',')
{
p=(BiTNode*)malloc(sizeof(BiTNode));
if(NULL==p)
return ERROR;
jj++;
p->data=ch;
p->lchild=p->rchild=NULL;
}
rear++;
q[rear]=p;
if(1==rear)
root=p;
else
{
if(p&&q[front])
{
if(0==(rear%2))
q[front]->lchild=p;
else
q[front]->rchild=p;
}
if(p&&(NULL==q[front]))
{
free(p);
return ERROR;
}
if(1==rear%2)
front++;
}
ch=getchar();
}
return OK;
}
void PreOrder(BiTree root) //先序遍历
{
if(root!=NULL)
{
cout<<root->data; //根
PreOrder(root->lchild);//左
PreOrder(root->rchild);//右
}
}
void InOrder(BiTree root) //中序遍历
{
if(root!=NULL)
{
InOrder(root->lchild); //左
cout<<root->data; //根
InOrder(root->rchild); //右
}
}
void PostOrder(BiTree root) //后序遍历
{
if(root!=NULL)
{
PostOrder(root->lchild);//左
PostOrder(root->rchild);//右
cout<<root->data; //根
}
}
int shuru()
{cout<<"输入二叉树(,表示空)安#结束输入:\n";}
int main()
{
shuru();
BiTree ss;
int i=CreatBiTree(ss);
cout<<endl<<"先序遍历二叉树:";
PreOrder(ss);
cout<<endl<<"中序遍历二叉树:";
InOrder(ss);
cout<<endl<<"后序遍历二叉树:";
PostOrder(ss);
cout<<endl<<"层序遍历二叉树:";
leverorder(ss);
cout<<endl;
return 0;
}
程序结果:。