5.3.1二叉树的遍历
二叉树的遍历是指按某条探索路径访问树的每个节点,使每个节点均被访问一次,且仅被访问一次
二叉树-->遍历次序
常见遍历次序
最坏的情况下,二叉树有n个节点且深度为n的单支树,空间复杂度为O(n)
先中后序遍历手算展开
1.先序遍历
先访问根节点,先序遍历左子树,先序遍历右子树
第一次路过时就访问--一个箭头指向时
void preOrder(linklist t) {
visit(t);//访问根节点
preOrder(t->lChild);//递归遍历左子树
preOrder(t->rChild);//递归遍历右子树
}
2.中序遍历
中序遍历左子树,访问根节点,中序遍历右子树
第二次路过时就访问--两个箭头指向时
//中序遍历
void preOrder(linklist t) {
preOrder(t->lChild);//递归遍历左子树
visit(t);//访问根节点
preOrder(t->rChild);//递归遍历右子树
}
3.后序遍历
后序访问左子树,后序访问右子树,访问根节点
第三次路过时就访问--三个箭头指向时
//后序遍历
void preOrder(linklist t) {
preOrder(t->lChild);//递归遍历左子树
preOrder(t->rChild);//递归遍历右子树
visit(t);//访问根节点
}
层次遍历
自上而下,从左至右遍历
遍历思想:(王道p47 1.22m)
①现将二叉树根节点入队
②若队列非空,则队头节点出队,访问该节点,若有左孩子,则将左孩子入队;若有右孩子则将右孩子入队;
③重复②步,直至该队列为空
算法
void LevelOrder(linklist t) {
initqueue(s);//初始化队列
linklist p;
enqueue(s, t);//将根节点入队
while (!isempty(s))//判断队列是否为空
{
//不为空则输出节点
//访问其左孩子,右孩子,并将其入队
dequeue(s,p);
visit(p);//访问出队节点
if (p->lChild!=NULL)
{
enqueue(s, p->lChild);
}
if (p->rChild!=NULL)
{
enqueue(s, p->rChild);
}
}
}
由遍历序列构造二叉树(遍历序列->二叉树)
※找到树的根节点,并根据中序序列划分左右子树,在找到左右子树根节点
- 中序+前序
- 中序+后序
- 中序+层次
5.3.2线索二叉树
线索二叉树基本概念
二叉树的线索化是将二叉树链表中的空指针改为前驱或后继节点的线索.
线索二叉树节点结构
若无左孩子,则lchild指向前驱节点;若无右孩子,则rchild指向后继节点
标志域ltag=0则lchild指向左孩子;ltag=1则lchild指向前驱节点
中序线索二叉树
步骤
算法实现
#include<stdio.h>;
typedef struct BiTree
{
int data;
BiTree* rchild;
BiTree* lchild;
int ltag;
int rtag;
}BiTree,*linklist;
linklist pre = NULL;
//中序遍历
void inThread(linklist& p) {
inThread(p->lchild);
visit(p);
inThread(p->rchild);
}
void visit(linklist &p) {
if (p->lchild == NULL) {
p->lchild = pre;
p->ltag = 1;
}
if (pre != NULL && p->rchild == NULL) {
pre->rchild = p;
pre->rtag = 1;
}
pre = p;
}
void createInThread(linklist &p) {
if (p != NULL) {
inThread(p);
if (pre->rchild==NULL)
{
pre->rtag = 1;
}
}
}
前序线索二叉树
算法实现
//前序遍历
void inThread(linklist& p) {
visit(p);
if (p->ltag==0)
{
inThread(p->lchild);
}
inThread(p->rchild);
}
void visit(linklist& p) {
if (p->lchild == NULL) {
p->lchild = pre;
p->ltag = 1;
}
if (pre != NULL && p->rchild == NULL) {
pre->rchild = p;
pre->rtag = 1;
}
pre = p;
}
void createInThread(linklist& p) {
if (p != NULL) {
inThread(p);
if (pre->rchild == NULL)
{
pre->rtag = 1;
}
}
}
后序线索二叉树
算法实现
//后序遍历
void inThread(linklist& p) {
inThread(p->lchild);
inThread(p->rchild);
visit(p);
}
void visit(linklist& p) {
if (p->lchild == NULL) {
p->lchild = pre;
p->ltag = 1;
}
if (pre != NULL && p->rchild == NULL) {
pre->rchild = p;
pre->rtag = 1;
}
pre = p;
}
void createInThread(linklist& p) {
if (p != NULL) {
inThread(p);
if (pre->rchild == NULL)
{
pre->rtag = 1;
}
}
}