数据结构之树与二叉树

一.树与树算法
1.什么是树
树是哟总抽象数据类型,用来模拟具有树状结构性值的数据集合,它是由n(n>=1)个有限节点组成一个具有层次关系的集合,如下图所示:
在这里插入图片描述
它具有以下特点:
1)每个节点有零个或这多个子节点
2)没有父节点的节点成为根节点,如上图的节点1就是根节点
3)没有个非根节点有且只有一个父节点
4)除了根节点外,每个子节点可以分为多个不相交的子树
2.树的概念
节点的度:一个节点含有的子树的个数成为该节点的度;
树的度:一棵树中,最大的节点的度称为树的度,如上图树的度为2,因为最大的节点的度为2(节点2 和 节点3)
兄弟节点:拥有同一个父节点的子节点叫做兄弟节点
叶子节点:没有子节点的节点叫做叶子节点
3.二叉树的性质
1).一个节点最多只有两个子节点的树交二叉树
2).二叉树中,第 i 层最多有 2i-1 个结点。
3).如果二叉树的深度为 K,那么此二叉树最多有 2K-1 个结点。
4).二叉树中,终端结点数(叶子结点数)为 n0,度为 2 的结点数为 n2,则 n0=n2+1。
4.二叉树的分类
满二叉树
如果二叉树中除了叶子结点,每个结点的度都为 2,则此二叉树称为满二叉树
在这里插入图片描述
完全二叉树
如果二叉树中除去最后一层节点为满二叉树,且最后一层的结点依次从左到右分布,
则此二叉树被称为完全二叉树。
在这里插入图片描述
5.二叉树的创建
我们用pyhton代码创建一个二叉树

class Node(object):
    """
    二叉树节点对象封装的类
    """

    def __init__(self, element):
        self.element = element
        self.lchild = None
        self.rchild = None

class Tree(object):
    """二叉树的封装"""

    def __init__(self, root=None):
        self.root = root

    def add(self, item):
        """往二叉树里面添加元素"""
        node = Node(item)
        #  #如果树是空的,则对根节点赋值
        if not self.root:
            self.root = node
        else:
            # 先找树的根节点, 存储到变量queue中
            queue = []
            queue.append(self.root)
            while queue:
                item = queue.pop(0)
               #如果当前节点没有左孩节点,则把元素加入左孩节点
                if not item.lchild:
                    item.lchild = node
                    return
                #如果当前节点有左孩节点,没有右孩节点,把元素加入右节点
                elif not item.rchild:
                    item.rchild = node
                    return
                #如果当前节点即有左节点也有右节点,把这两个节点加入队列,重新进入while循环,判断这两个节点是否还有左右子节点,一直循环下去
                else:
                    queue.append(item.lchild)
                    queue.append(item.rchild)

二. 二叉树的遍历
遍历是指对树中所有结点的信息的访问,即依次对树中每个结点访问一次且仅访问一次,我们把这种对所有节点的访问称为遍历。
遍历的模式分为深度优先和广度优先,如图所示:

在这里插入图片描述
我们以下图简单的二叉树为例,理解深度遍历优先与广度遍历优先:
在这里插入图片描述
1.广度优先遍历
广度优先遍历即层级遍历,逐层依次遍历,以上图为例,遍历顺序为 1—>2—>3—>4—>5—>6—>7,我们可以利用队列实现数的层次遍历

def breadth_travel(self):
        if not self.root:           #判断有无根节点,若无根结点即二叉树为空
            return
        else:
            queue = []              #创建空列表,存储节点
            queue.append(self.root)            #首先将跟节点加入队列
            while queue:               
                node = queue.pop(0)         #从列表中弹出第一个节点
                print(node.element, end=',')
                if node.lchild:            #此处的node为从列表中弹出的第一个节点,判断此节点有无左孩节点
                    queue.append(node.lchild)          #若左孩节点存在,则加入队列
                if node.rchild:         #判断此节点有无右孩节点
                    queue.append(node.rchild)         #若右孩节点存在,则加入队列
            print()

2.深度优先遍历
深度优先遍历分为三类:先序遍历,中序遍历,后序遍历。
依然以上面简单的二叉树为例,三种遍历方法的遍历顺序如下:
先序遍历:1 2 4 5 3 6 7 (可简单看为从上到下,从左到右的不重复遍历)

#递归实现先序遍历
 def preorder(self, root):
        if root == None:
            return
        print(root.element, end=', ')
        self.preorder(root.lchild)
        self.preorder(root.rchild)

中序遍历:4 2 5 1 6 3 7 (可以简单看作根据数中节点的平面位置按从左到右依次遍历)

    """递归实现中序遍历"""
 def inorder(self, root):
        if root == None:
            return
        self.inorder(root.lchild)
        print(root.element, end=', ')
        self.inorder(root.rchild)

后续遍历:4 5 2 6 7 3 1 (可以看作从叶子节点开始从左到右,从下到上依次遍历)

#递归实现后序遍历
 def preorder(self, root):
        if root == None:
            return
        self.preorder(root.lchild)
        self.preorder(root.rchild)
        print(root.element, end=', ')

三. 二叉排序树
1.定义
二叉排序树,又叫二叉查找树,它或者是一棵空树;或者是具有以下性质的二叉树:
1.若它的左子树不空,则左子树上所有节点的值均小于它的根节点的值;
2.若它的右子树不空,则右子树上所有节点的值均大于它的根节点的值;
3.它的左右子树也分别为二叉排序树。

四. 二叉树遍历总结
1).某二叉树的前序序列和后序序列正好相反,则该二叉树一定是高度等于其节点数的二叉树。
解:前序遍历我们可以理解为 根-左-右,后序可以理解为左-右-根,若前序和后序相反,则该二叉树的任意结点必定没有左孩节点或者右孩节点,包括空节点和一个节点的情况,综上所述即就是高度等于其节点数的二叉树满足。
2)一个二叉树的先序遍历结果和中序遍历结果相同,则其所有非叶子节点必须满足的条件是只有右子树
解:前序遍历是从根节点开始,中序遍历从最左边的开始,若两个的遍历结果相同,则第一个必定是根节点,所以根节点不能有左子树,如果是三层二叉树,则第二层的节点也不能有左子树,所以每个非叶子节点必须没有左子树。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值