第5章 树和二叉树

树的遍历操作
前序遍历
若树为空,则空操作返回;否则执行以下操作:
访问根节点;
按照从左到右的顺序从左到右的顺序前序遍历根节点的每一颗子树。
后序遍历
若树为空,则空操作返回;否则执行以下操作:
按照从左到右的顺序后序遍历根节点的每一颗子树
访问根节点
层序遍历
从树的根节点开始,自上而下逐层遍历,在同一层中,按从左到右的顺序对节点逐个访问
树的存储结构
双亲表示法
除根节点外,树中的每个节点有且仅有一个双亲结点,根据这一特性,可以用一维数组来树的各个节点(一般按层序存储),数组中的每个元素对应书中的一个节点,数组元素包括树中节点的数据信息以及该节点的双亲在数组中的下标。
template
struct PNode
{
T data;
int parent;
};
孩子表示法
是一种基于链表的存储方法,即把每个节点的孩子排列起来,看成是一个线性表,且以单链表存储
struct CTNode
{
int child;
CTNode *next;
};
template
struct CBNode
{
T data;
CTNode *firstChild;
};
孩子兄弟表示法
又称为二叉链表法,其方法是链表的每个节点除数据域外,还设置了两个指针分别指向该节点的第一个孩子和右指针
template
struct TNode
{
T data;
TNode *firstChild,*rightSib;
};
二叉树
(1)斜树
所有节点只有左子树的二叉树称为左斜树
所有节点只有右子树的二叉树称为右斜树
左斜树和右斜树统称为斜树
特点:每一次只有一个节点,节点的个数与其深度相同
(2)满二叉树
在一颗二叉树中,如果所有的分支节点都存在左子树和右子树,并且所有的叶子都在同一层上
特点:叶子只能出现在最下一层,只有度数为0和度数为2的节点
(3)完全二叉树
对一颗具有n个节点的二叉树按层序编号,如果编号为i(1=<i<=n)的节点与同样深度的满二叉树中编号为i的节点在二叉树中的位置完全相同
特点:深度为k的完全二叉树在k-1层是满二叉树,叶子节点只能出现在最下两层且最下两层的叶子节点集中在左侧连续的位置,如果有度数为1的节点只可能有一个且该节点只有左孩子
二叉树的基本性质
性质 1 在一颗二叉树中,如果叶子节点的个数为n0,度数为2的节点个数为n2,则n0=n2+1
性质 2 二叉树的第i层上最多有2的i-1次方个节点
性质 3 在一颗深度为k的二叉树中,最多有2k-1次方-1个节点
性质 4 具有n个节点的完全二叉树的深度为[log(2)n]+1
性质 5 对一颗具有n个节点的完全二叉树从1开始按层序编号,则对于编号为i(1=<i<=n)的节点(简称节点i),有如下关系:
1)如果i>1,则节点i的双亲编号为[i/2];否则节点i是根节点,无双亲。
2)如果2i<=n,则节点i的左孩子的编号为2i;否则无左孩子
3)如果2i+1<=n,则节点i的右孩子的编号为2i+1;否则节点无右孩子。
二叉树的遍历操作
前序遍历
若二叉树为空,则空操作返回;否则执行以下操作:
访问根节点;
前序遍历根节点的左子树;
前序遍历根节点的右子树;
中序遍历
若二叉树为空,则空操作返回;否则执行以下操作:
中序遍历根节点的左子树;
访问根节点;
中序遍历根节点的右子树;
后序遍历
若二叉树为空,则空操作返回;否则执行以下操作:
后序遍历根节点的左子树;
后序遍历根节点的右子树;
访问根节点;
二叉树的存储结构
1.顺序存储
按照完全二叉树进行层序编号,再利用一维数组进行存储
根节点的编号为1,若某节点i有左孩子,则左孩子的编号为2i,若有右孩子则右孩子的编号为2i+1
2.二叉链表
基本思想:令二叉树的每个节点对应一个链表节点,链表节点除了存放二叉树节点的数据信息外,还要存放指示左右孩子的指针
template
struct BiNode
{
T data;
BiNode *lchild,*rchild;
};
template
class BiTree
{
public:
BiTree(){rootCreat();}
~BiTree(){Release(root);}
void PreOrder(){ PreOrder(root);}
void InOrder(){ InOrder(root);}
void PostOrder(){ PostOrder(root);}
void LevelOrder();
private:
BiNode*Creat();
void Release(BiNode*bt);
void PreOrder(BiNode*bt);
void InOrder(BiNode*bt);
void PostOrder(BiNode*bt);
BiNode*root;
};
temalate
void BiTree::PreOrder(BiNode*bt)
{
if(bt
nullptr) return;
else{
cout<data<<"\t";
PreOrder(bt->lchild);
PreOrder(bt->rchild);
}
}
temalate
void BiTree::InOrder(BiNode*bt)
{
if(btnullptr) return;
else{
InOrder(bt->lchild);
cout<data<<"\t";
InOrder(bt->rchild);
}
}
temalate
void BiTree::PostOrder(BiNode*bt)
{
if(bt
nullptr) return;
else{
PostOrder(bt->lchild);
PostOrder(bt->rchild);
cout<data<<"\t";
}
}
template
void BiTree::LeveOrder()
{
BiNode*Q[100],*qnullptr;
int front=-1,rear=-1;
if(root
nullptr) return;
Q[++rear]=root;
while(front!=rear)
{
q=Q[++front];
cout<data<<"\t";
if(q->lchild!=nullptr) Q[++rear]=q->lchild;
if(q->rchild!=nullptr) Q[++rear]=q->rchild;
}
}
template
BiNode*BiTree::Creat()
{
BiNode*bt;
char ch;
cin>>ch;
if(ch==’#’) bt=nullptr;
else{
bt=new BiNode;
bt->data=ch;
bt->lchild=Creart();
bt->rchild=Creat();
}
return bt;
}
template
void BiTree::Release(BiNode*bt)
{
if(bt==nullptr) return;
else{
Release(bt->lchild);
Release(bt->rchild);
delete bt;
}
}
1.树转换为二叉树
1)加线—树中所有相邻兄弟节点之间加一条连线
2)去线—对树中的每个节点,只保留它与第一个孩子节点之间的连线,删去它与其他孩子节点之间的连线
3)层次调整—按照二叉树之间的节点关系行调整
2.森林转换成二叉树
1)将森林中的每个树转换成二叉树
2)将每棵树的根节点视为兄弟,在所有根节点之间加上连线
3)按照二叉树节点之间的关系进行调整
3.二叉树转换为树或森林
1)加线—若某节点x是其双亲y的左孩子,则把节点x的右孩子、右孩子的右孩子、……,都与节点y用线连起来
2)去线—删去原二叉树中所有双亲节点右孩子节点的连线;
3)层次调整—整理由1)、2)两步所得到的树或森林,使层次分明。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值