二叉树

树(tree)是n(n>=0)个节点的有限集。当n=0时,称为空树。

在任意一个非空树中,有如下特点:

1.有且仅有一个特点的称为根的节点
2.当n>1时,其余节点可分为m个互不相交的有限集,每一个集合本身又是一个树,并称为根的子树。
关键字:根节点;叶子节点;父节点;孩子节点;兄弟节点

二叉树:

左孩子结点,右孩子结点

满二叉树:

一个二叉树的所有非叶子节点都存在左孩子和右孩子,并且所有叶子节点都在同一层级上,那么这个树就是满二叉树

完全二叉树:

定义太复杂了,记特点吧:满二叉树一定是完全二叉树,完全二叉树不一定是满二叉树;满二叉树要求所有节点分支都是满的
而完全二叉树只要保证最后一个节点之前的节点都齐全即可(也就是说,最后一个非叶子节点可以没有右孩子节点,有没有左孩子节点它都是完全二叉树)

二叉树的链式存储结构

二叉树中的一个节点最多可以指向左右两个孩子节点,所以二叉树节点包含3部分
1.存储数据的data变量
2.指向左孩子的left指针
3.指向右孩子的right指针

二叉树的数组存储

使用数组存储时,会按层级顺序把二叉树的节点放到数组中对应的位置上。
如果某一个节点的左孩子或右孩子空缺,则数组的相应位置也空出来
这样可以更方便的在数组中定位二叉树的孩子节点和父节点
假设一个父节点的下标是parent1,那么它的左孩子节点的下标就是2*parent+1;
右孩子节点的下标就是2*parent+2
反过来,假设一个左孩子节点的下标是leftChild,那么他的父节点下标就是(leftChild-1)/2

二叉树的应用:

查找操作和维持相对顺序

1.查找

二叉查找树在二叉树的基础上增加了以下几个条件:
1.1如果左子树不为空,则左子树上所有节点的值均小于根节点的值
1.2如果右子树不为空,则右子树上所有节点的值均大于根节点的值
1.3左子树、右子树也都是二叉查找树
原则是左子树的值小于根节点的值,右子树的值大于根节点的值
对于一个节点分布相对均衡的二叉查找树来说,如果节点总数是n,那么搜索节点的时间复杂的就是O(logn),和树的深度是一样的

2.维持相对顺序

二叉查找树要求左子树节点的值小于父节点的值,右子树节点的值大于父节点的值,正是这样保证了二叉树的有序性

二叉查找树又称二叉排序树,需要插入的元素须遵守二叉排序数的原则,如从根节点插入,最终的位置需从根节点到左孩子节点或右孩子节点(原则是左子树的值小于根节点的值,右子树的值大于根节点的值)
但却有个问题,若插入的都是比根节点小的元素,那岂不都插入到左孩子节点中去么,所以这就涉及到二叉树的自平衡,如红黑树、AVL树、树堆等。
除了二叉查找树以外,二叉堆也维持着相对的顺序,只要求父节点的值比他的左右孩子的值都大。

遍历二叉树,二叉树是非线性数据结构

遍历时需要把非线性关联的节点转化成一个线性的序列。以不同的方式来遍历,遍历出的序列顺序也不同

二叉树的遍历分为3种(深度优先遍历)

1.前序遍历:根节点-->左子树-->右子树
2.中序遍历:左子树-->根节点-->右子树
3.后续遍历:左子树-->右子树-->根节点

二叉树的层序遍历(也称广度优先遍历)

如果说深度优先遍历是在一个方向上"一头扎到底",那么广度优先遍历则恰恰相反;现在各个方向上各走一步,再在各个方向上
走出第2步、第3步.....一直到各个方向全部走完。
层序遍历顾名思义就是二叉树按照从根节点到叶子节点的层次关系,一层一层横向遍历各个节点
可是,二叉树同一层次的节点之间是没有直接关联的,这时需要借助一个数据结构来辅助工作,这个数据结构就是队列

二叉树的三种遍历方法

class TreeNode:
    def __init__(self, data):
        self.data = data
        self.left = None
        self.right = None


def create_binary_tree(input_list=[]):
    """
    构建二叉树
    :param input_list: 输入数列
    
    """
    if input_list is None or len(input_list) == 0:
        return None
    data = input_list.pop(0)
    if data is None:
        return None
    node = TreeNode(data)
    node.left = create_binary_tree(input_list)
    node.right = create_binary_tree(input_list)
    return node


def pre_order_traversal(node):
    """
    前序遍历
    :param node: 二叉树节点
    """
    if node is None:
        return
    print(node.data)
    pre_order_traversal(node.left)
    pre_order_traversal(node.right)
    return node


def in_order_traversal(node):
    """
    中序遍历
    :param node: 二叉树节点
    """
    if node is None:
        return
    in_order_traversal(node.left)
    print(node.data)
    in_order_traversal(node.right)
    return node


def post_order_traversal(node):
    """
    后序遍历
    :param node: 二叉树节点
    """
    if node is None:
        return
    post_order_traversal(node.left)
    post_order_traversal(node.right)
    print(node.data)
    return node

# 这里吧一个线性的链表转化为非线性的二叉树
my_input_list = list([3, 2, 9, None, None, 10, None, None, 8, None, 4])
root = create_binary_tree(my_input_list)
print("前序遍历:")
pre_order_traversal(root)
print("中序遍历:")
in_order_traversal(root)
print("后序遍历:")
post_order_traversal(root)

二叉树非递归前序遍历

采用的是栈

class TreeNode:
    def __init__(self, data):
        self.data = data
        self.left = None
        self.right = None


def create_binary_tree(input_list=[]):
    if input_list is None or len(input_list) == 0:
        return None
    data = input_list.pop(0)
    if data is None:
        return None
    node = TreeNode(data)
    node.left = create_binary_tree(input_list)
    node.right = create_binary_tree(input_list)
    return node

# 二叉树非递归前序遍历
def pre_order_traversal_with_stack(node):
    stack = []
    while node is not None or len(stack) > 0:
        while node is not None:
            print(node.data)
            stack.append(node)
            node = node.left
        if len(stack) > 0:
            node = stack.pop()
            node = node.right


my_input_list = list([3, 2, 9, None, None, 10, None, None, 8, None, 4])
root = create_binary_tree(my_input_list)
print("前序遍历:")
pre_order_traversal_with_stack(root)

二叉树的层序遍历(广度优先遍历)

采用的是队列

from queue import Queue



def level_order_traversal(node):
    queue = Queue()
    queue.put(node)
    while not queue.empty():
        node = queue.get()
        print(node.data)
        if node.left is not None:
            queue.put(node.left)
        if node.right is not None:
            queue.put(node.right)


def create_binary_tree(input_list=[]):
    if input_list is None or len(input_list) == 0:
        return None
    data = input_list.pop(0)
    if data is None:
        return None
    node = TreeNode(data)
    node.left = create_binary_tree(input_list)
    node.right = create_binary_tree(input_list)
    return node


class TreeNode:
    def __init__(self, data):
        self.data = data
        self.left = None
        self.right = None


my_input_list = list([3, 2, 9, None, None, 10, None, None, 8, None, 4])
root = create_binary_tree(my_input_list)
print("层序遍历:")
level_order_traversal(root)
posted @ 2021-09-09 18:43  索匣  阅读(58)  评论(0编辑  收藏  举报