数据结构-树与二叉树-C++代码实现

一、树

 

1.树的存储结构-三种表示法

(1)双亲表示

(2)孩子表示法

(3)孩子兄弟表示法

二、二叉树

1.存储结构

(1)顺序存储

(2)链式存储

2.二叉树的建立

//算法5.3 先序遍历的顺序建立二叉链表
void CreateBitTree(BitTree &T){
    char ch;//接收树存储的数据
    cin>>ch;
    if(ch=='#') T=NULL;//若输入为字符为#,递归结束,建立空树
    else
     {
        T=new BitNode;//申请空间,创建结点
        T->data=ch;//存储数据,生成根节点
        CreateBitTree(T->lchild);//创建左子树(递归)
        CreateBitTree(T->rchild);//创建右子树(递归)
     };
     //一定注意递归调用的函数不要写错了!
}

3.二叉树的遍历

(1)前序遍历(PreOrderTraverse)

//先序遍历输出结点
void PreOrderTraverse(BitTree T){
    if(T) 
    {
        Visit(T);//访问根节点
        PreOrderTraverse(T->lchild);
        PreOrderTraverse(T->rchild);
    }
}

(2)中序遍历(InOrderTraverse)

//中序遍历输出结点
void InOrderTraverse(BitTree T){
    if(T==0) return;
    InOrderTraverse(T->lchild);
    Visit(T);//访问根节点
    InOrderTraverse(T->rchild);
}

(3)后序遍历(PostOrderTraverse)

//后序遍历输出结点
void PostOrderTraverse(BitTree T){
    if(T==0) return;
    PostOrderTraverse(T->lchild);
    PostOrderTraverse(T->rchild);
    Visit(T);//访问根节点
}

先序、中序、后序遍历的完整代码及运行结果:

//二叉树的链式存储
#include <cstdlib>
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <typeinfo>
using namespace std;

//定义存储结构
typedef struct BitNode{
    char data;
    struct BitNode *lchild,*rchild;
}BitNode,*BitTree;

void Visit(BitTree T){
    cout<<T->data;
}

//先序遍历输出结点
void PreOrderTraverse(BitTree T){
    if(T) 
    {
        Visit(T);//访问根节点
        PreOrderTraverse(T->lchild);
        PreOrderTraverse(T->rchild);
    }
}

//中序遍历输出结点
void InOrderTraverse(BitTree T){
    if(T==0) return;
    InOrderTraverse(T->lchild);
    Visit(T);//访问根节点
    InOrderTraverse(T->rchild);
}

//后序遍历输出结点
void PostOrderTraverse(BitTree T){
    if(T==0) return;
    PostOrderTraverse(T->lchild);
    PostOrderTraverse(T->rchild);
    Visit(T);//访问根节点
}


//算法5.3 先序遍的顺序建立二叉链表
void CreateBitTree(BitTree &T){
    char ch;//接收树存储的数据
    cin>>ch;
    if(ch=='#') T=NULL;//若输入为字符为#,递归结束,建立空树
    else
     {
        T=new BitNode;//申请空间,创建结点
        T->data=ch;//存储数据,生成根节点
        CreateBitTree(T->lchild);//创建左子树(递归)
        CreateBitTree(T->rchild);//创建右子树(递归)
     };
     //一定注意递归调用的函数不要写错了!
}

//测试用例1:ABDH#K###E##CFI###G#J##
//测试用例2:12#46###3#5##
int main()
{
    BitTree T;//T为指向当前根节点的指针
    cout<<"请输入构造结点的数值"<<endl;
    CreateBitTree(T);
    cout<<"树已构造完毕"<<endl;

    cout<<"前序遍历结果:"<<endl;
    PreOrderTraverse(T);

    cout<<endl<<"中序遍历结果:"<<endl;
    InOrderTraverse(T);

    cout<<endl<<"后序遍历结果:"<<endl;
    PostOrderTraverse(T);
}

//总结:
//1、创建、先序、中序、后序都是使用递归的思想;
//2、递归调用的是自己的函数,自己的函数里面调用自己,写代码时注意同步修改!

//测试用例1:ABDH#K###E##CFI###G#J##(树如图1)

//测试用例2:12#46###3#5##(树如图2)

需要注意的是,我们在创建一棵树前,就需要现在草稿纸上画好树的模样,而且注意:

1)“#”不要遗漏,尤其右子树的叶子节点的#容易遗漏,一旦遗漏,无法成功遍历;

2)数字和字母都属于字符,代码中定义data的数据类型为char型,所以输入数字和字母,代码都能完成遍历,无需将data类型改为int,反而会出错。

(图1:《大话数据结构》P178)

(图2:《王道》P132-图5.4)

前序遍历结果:124635   中序遍历结果:264135  后序遍历结果:642531

运行结果:

  


(4)层序遍历

(5)访问根节点

void Visit(BitTree T){
    cout<<T->data;
}

(6)遍历的应用1:用后序遍历思想求:二叉树的深度

先放代码,如下:

这段代码,真是耐人寻味,虽然短短几句,但是理解其本质,还是要下点功夫!本质是后序遍历:左右根,而深度统计的实现,也是基于递归的过程,此处访问根的操作即为:

1.每次对左右子树的深度进行比较,

2.如果左子树的深度l>右子树的深度r,那么就将l+1作为当前根节点构成树的深度作为返回值返回

3.否则(注意这个else语句,否则包括:l<r 和 l=r 两种情况,比如某个结点为叶子结点,那么它的l=r=0,此时递归函数是有返回值的为:r+1,这点很容易被忽略,这也是递归能够持续下去的出发点)就返回r+1;

4.在代码中专门加入输出语句,以观测每次递归的返回值,也即当前结点的深度。

5.对T的理解:一定要明确T是时刻移动更新的,时刻指向新的根节点。假设B是A的孩子,T初始时指向A,比如T=T->Lchild执行后,此时T的指向已经发生改变,指向B,是一个动态递归的过程。

为了更清晰的展示【二叉树深度算法】的执行过程,列出如下表格,读者可跟着演算:

二叉树深度求解算法-手动推算过程(上图1)

后序遍历结点

访问顺序(当前根结点)

左子树深度

L

右子树深度

R

当前跟结点的深度

Depth(x)=L>R?L+1:R+1

K00Depth(K)=R+1=1
H01Depth(H)=R+1=2
D20Depth(D)=L+1=3
E00Depth(E)=R+1=1
B31Depth(B)=L+1=4
I00Depth(I)=R+1=1
F10Depth(F)=L+1=2
J00Depth(J)=R+1=1
G01Depth(G)=R+1=2
C22Depth(C)=R+1=3
A43Depth(A)=L+1=5
运行结果如下:

始运行...

请输入树的结点值:
ABDH#K###E##CFI###G#J##
前序遍历的结果是:ABDHKECFIGJ
中序遍历的结果是:HKDBEAIFCGJ
后序遍历的结果是:KHDEBIFJGCA
当前访问结点:K,当前树深度:1
当前访问结点:H,当前树深度:2
当前访问结点:D,当前树深度:3
当前访问结点:E,当前树深度:1
当前访问结点:B,当前树深度:4
当前访问结点:I,当前树深度:1
当前访问结点:F,当前树深度:2
当前访问结点:J,当前树深度:1
当前访问结点:G,当前树深度:2
当前访问结点:C,当前树深度:3
当前访问结点:A,当前树深度:5

运行结束。

  • 2
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值