3-2-基础算法-查找算法2-树和二叉树查找(遍历:前序中序后序遍历,深度优先广度优先)

一、树

1、什么是树?
树状图是一种数据结构,它是由n(n>=1)个有限节点组成一个具有层次关系的集合。
把它叫做“树”是因为它看起来像一棵倒挂的树,也就是说它是根朝上,而叶朝下的。

它具有以下的特点:
每个节点有零个或多个子节点;
没有父节点的节点称为根节点;
每一个非根节点有且只有一个父节点;
除了根节点外,每个子节点可以分为多个不相交的子树;


几个概念

  • 父节点,子节点: A和B
  • 兄弟节点:D E J
  • 根节点:A
  • 叶节点: GI


几个概念

  • 节点高度:节点到叶节点的最长路径(边数),这个图就是3,
  • 节点深度:根节点到这节点所经历的边的个数,根节点的深度是0,
  • 节点的层数:节点的深度 + 1
  • 树高度:根节点的高度

二, 二叉树

树有有序树和无序树,我们只研究有序树中的二叉树,

1、什么是二叉树?
二叉树,就是度不差过2的树(节点最多有两个叉)

2,二叉树的分类:

1,完全二叉树:

叶节点只能出现在最下层和次下层,并且最下面一层的结点都集中在该层最左边的若干位置的二叉树

2,满二叉树

一个二叉树,如果每一个层的结点数都达到最大值,则这个二叉树就是满二叉树。
满二叉树一定是完全二叉树,但是完全二叉树不一定是满二叉树

3,平衡二叉树

4,二叉排序树

三、二叉树的存储方式

二叉树也可以使用顺序表进行存储,
不过树还是使用链表存储,就是连接两个节点,
常见的树应用的场景,html就是树的结构,
树的应用场景是非常的多的,

1、链式存储方式

a、二叉树的链式存储:将二叉树的节点定义为一个对象,节点之间通过类似链表的链接方式来连接。
b、节点定义
class BiTreeNode:
def init(self,data): #data就是传进去的节点的值
self.data = data
self.lchild = None
self.rchild = None

c、二叉树的遍历:

I 、先(前)序遍历:访问根结点的操作发生在遍历其左右子树之前

  具体操作:若二叉树非空,则依次执行如下操作:
⑴ 访问根结点;
⑵ 遍历左子树;
⑶ 遍历右子树。

II、中序遍历:访问根结点的操作发生在遍历其左右子树之中(间)。

 具体操作: 若二叉树非空,则依次执行如下操作:

⑴遍历左子树;
⑵访问根结点;
⑶遍历右子树。

III、后序遍历:访问根结点的操作发生在遍历其左右子树之后。

  若二叉树非空,则依次执行如下操作:

⑴遍历左子树;
⑵遍历右子树;
⑶访问根结点。
IV、层次遍历
用一个队列保存被访问的当前节点的左右孩子以实现层序遍历。

二叉树的遍历代码

class Node(object):
"""节点类"""
    def __init__(self, elem=-1, lchild=None, rchild=None):
        self.elem = elem
        self.lchild = lchild  # 有两个子节点
        self.rchild = rchild

class Tree(object):
    """树类"""
    def __init__(self, root=None):
        self.root = root

    def add(self, elem):
        """为树添加节点"""
        node = Node(elem)
        #如果树是空的,则对根节点赋值
        if self.root == None:
            self.root = node
        else:
            queue = []
            queue.append(self.root)
            #对已有的节点进行层次遍历
            while queue:  # 结束的条件就是队列为空,
                #弹出队列的第一个元素
                cur = queue.pop(0)
                if cur.lchild == None:
                    cur.lchild = node
                    return
                elif cur.rchild == None:
                    cur.rchild = node
                    return
                else:
                    #如果左右子树都不为空,加入队列继续判断
                    queue.append(cur.lchild)
                    queue.append(cur.rchild)


    # 树的遍历
    ####################################################################
    # 广度优先遍历
    def breadth_travel(self):
        """利用队列实现树的层次遍历"""
        if self.root == None:
            return
        queue = [self.root]
        while queue:
            node = queue.pop(0)
            print(node.elem)
            if node.lchild != None:
                queue.append(node.lchild)
            if node.rchild != None:
                queue.append(node.rchild)

    ##################################################################
    # 深度优先遍历
    # 有三种方式
    # 这个遍历的代码可以不用管,但是一定要会数,给你顺序,你能画出来一个二叉树,这个正推和逆推都要会
    # 先序遍历,永远都是根节点优先,中左右
    def preorder(self, root):
        """递归实现先序遍历"""
        if root == None:
            return
        print(root.elem)
        self.preorder(root.lchild)
        self.preorder(root.rchild)

    # 中序遍历: 左中右,
    def inorder(self, root):
        """递归实现中序遍历"""
        if root == None:  # 这是递归的结束条件
            return
        self.inorder(root.lchild)
        print(root.elem)
        self.inorder(root.rchild)

    # 后续遍历,左右中,
    def postorder(self, root):
        """递归实现后续遍历"""
        if root == None:
            return
        self.postorder(root.lchild)
        self.postorder(root.rchild)
        print(root.elem)


if __name__ == '__main__':
    tree=Tree()
    tree.add(1)
    tree.add(2)
    tree.add(3)
    tree.add(4)
    tree.add(5)
    tree.breadth_travel()
posted @ 2020-02-23 01:11  技术改变命运Andy  阅读(251)  评论(0编辑  收藏  举报