树与二叉树

树的定义与性质

树:在数据结构中,树是用来概括这种传递关系的一种数据结构。
结点:数据结构中把树枝分叉处、树叶、树根抽象为结点。
根结点:树根
叶子结点:树叶
边:茎干和树枝
在这里插入图片描述
一棵树最多存在一个根节点
叶子结点不再延伸出新的结点
一条边只用来连接两个结点(一个端点一个)

树:由若干个结点和若干个边组成的数据结构,且在树中的结点不能被边连成环。

树的性质:

  1. 树可以没有结点,即空树
  2. 树的层次:从根结点开始算起,根结点为第一层,根结点子树的根结点为第二次…
  3. 度:结点的子树棵数
  4. 树的度:树中结点的最大的度
  5. 由于一条边连接两个结点,且树中不存在环,因此对有n个结点的树,边数一定是n-1。且满足连通、边数等于顶点数减1的结构一定是一棵树
  6. 叶子结点:度0的结点。因此当树中只有一个结点(即只有根结点)时,根结点也算叶子结点
  7. 结点的深度:从根结点(深度为1)开始自顶向下逐层累加至该结点时的深度值
  8. 结点的高度:从最底层叶子结点(高度为1)开始自底向上逐层累加至该结点时的高度值。
  9. 树的深度:树中结点的最大深度
  10. 树的高度:树中结点的最大高度
  11. 森林:多棵树组合在一起。森林是若干棵树的集合

二叉树的递归定义

二叉树递归定义:

  1. 要么二叉树没有根结点,是一颗空树
  2. 要么二叉树由根结点、左子树、右子树组成,且左子树和右子树都是二叉树
    在这里插入图片描述
    二叉树与度为2的树的区别:
  3. 对树来说,结点的子树不区分左右顺序的,度为2的树只能说明树中每个结点的子结点个数不超过2.
  4. 二叉树满足每个结点的子结点个数不超过2,要严格区分左右子树

特殊的二叉树:

  1. 满二叉树:每一层的结点个数都达到了当层能达到的最大结点数。
  2. 完全二叉树:除了最下面一层之外,其余的结点个数都达到了当层能达到的最大结点数,且最下面一层只从左至右连续存在若干结点,而这些连续结点右边的结点全部不存在。

二叉树的存储结构与基本操作

  1. 二叉树的存储结构
struct node{
    typename data; //数据域
    node* lchild; //指向左子树根结点的指针
    node* rchild; //指向右子树根结点的指针
};

由于在二叉树建树前根结点不存在,因此其地址一般设为NULL

node* root = NULL;

新建结点

node* newNode(int v){
    node* Node = new node; //申请一个node型变量的地址空间
    Node->data = v; //结点权值v
    Node->lchild = Node->rchild = NULL; //初始化状态下没有左右孩子
    return Node; //返回新建结点的地址
}
  1. 二叉树结点的查找、修改
    查找:在给定数据域的条件下,在二叉树中找到所有数据域为给定数据域的结点,并将它们数据域修改为给定的数据域。

递归式:对当前结点的左子树和右子树分别递归
递归边界:当前结点为空时到达死胡同

先判断当前结点是否是需要查找的结点:
如果是,则对其修改
如果不是,则分别往该结点的左孩子和右孩子递归,直到当前结点为NULL

void search(node* root, int x, int newdata)
{
    if(root == NULL)
    {
        return; //空树,死胡同(递归边界)
    }
    if(root->data = x) //找到数据域为x的结点,把它修改成newdata
    {
        root->data = newdata;
    }
    search(root->lchild, x, newdata); //往左子树搜索x(递归式)
    search(root->rchild, x, newdata); //往右子树搜索x(递归式)
}

search函数为什么不需要加引用:因为该函数中修改的是指针root指向的内容,而不是root本身,对指针指向的结点内容的修改时不需要加引用的。

  1. 二叉树结点的插入
    二叉树结点的插入位置:数据域在二叉树中查找失败的位置。
//insert函数将在二叉树中插入一个数据域为x的新结点
//注意根结点指针root要使用引用,否则插入不会成功
void insert(node* &root, int x)
{
    if(root == NULL) //空树,说明查找失败,也即插入位置(递归边界)
    {
        root = newNode(x);
        return;
    }
    if(由二叉树的性质,x应该插在左子树)
    {
        insert(root->lchild, x); //往左子树搜索(递归式)
    }
    else
    {
        insert(root->rchild, x); //往右子树搜索(递归式)
    }
}

根结点指针root使用了引用&。即在函数中修改root会直接修改原变量。

判断是否加引用:如果函数中需要新建结点,即对二叉树的结构做出修改,就需要加引用;如果只修改当前已有结点的内容,或仅仅是遍历树,就不用加引用。

注意:在新建结点之后,务必令新结点的左右指针域为NULL,表示这个新结点暂时没有左右指针。

  1. 二叉树的创建
    把需要插入的数据存储在数组中,然后再将它们使用insert函数一个个插入二叉树中,并最终返回根结点的指针root。
//二叉树的建立
node* Create(int data[], int n)
{
    node* root = NULL; //新建空根结点root
    for(int i = 0; i < n; i++)
    {
        insert(root, data[i]); //将data[0]~data[n-1]插入二叉树中
    }
    return root; //返回根结点
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

阳光开朗男孩

你的鼓励是我最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值