Python学习笔记:4.2.4 二叉树遍历

本文是学习陆老师的《python全栈工程师 - 数据结构与算法》课程的笔记,欢迎学习交流。同时感谢陆老师的精彩传授!

一、课程目标
  • 树结构定义
  • 二叉树结构
  • 遍历与搜索
二、详情解读

01.什么是树:

爷爷
父亲
伯伯
哥哥
妹妹
堂哥
堂妹
术语定义
节点树中分叉处,用来存储项
没有父节点的节点,即最顶端的节点
子节点一个节点的直接相邻的后一个节点,可以拥有多个子节点,子节点顺序从左到右
父节点一个节点的直接相邻的前一个节点
兄弟节点拥有共同父节点的节点
叶子节点没有子节点的节点称为叶子节点
内部节点至少拥有一个子节点的节点
边/分支链接节点的连接线
后代一个节点的所有的子节点、子子节点
祖先一个节点之前的父节点、父节点的父节点,一直到根节点
路径一个节点到某一个后代节点的序列
深度/层级一个节点的深度等于将其连接到根节点的路径的长度,因此,根节点深度为0,根节点的子节点深度是1,以此类推
高度树中最长的路径的长度
子树将一个节点及其所有后代节点包括在内所形成的树

树结构的应用:

1.文件路径,就是一种树状结构
2.商品分类的菜单实现,也是树状结构
3.网页中的文档树
4.机器学习中的决策树,随机森林
5.数据库中的B树
6…很多,不一而足

二叉雄起的形状:

普通树:

爷爷
父亲
伯伯
哥哥
妹妹
堂哥
堂妹

二叉树:
一个节点最多拥有2个子节点
两个子节点分别称为左节点与右节点
如果只有一个子节点,该子节点可以看作是左节点或者右节点,
并且因此带来的树结构不同

爷爷
父亲
伯伯
妹妹
堂哥

02.二叉树:
在这里插入图片描述
二叉树的形状:

鼻祖
远祖
太祖
烈祖
天祖
高祖
普祖
祖父

十世单传,树的高度=树的节点树-1
这种情况下,就好像一个链表
对这棵树的访问插入删除的时间复杂度都是线性的O(n)


爷爷
父亲
伯伯
哥哥
妹妹
堂哥
堂妹

满二叉树:
除了叶子节点,每个节点都包含了二个节点
满二叉树的高度H = log2(N+1)-1

在这里插入图片描述
在这里插入图片描述
03.二叉树的遍历与搜索
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
二叉树的查找:
在这里插入图片描述
代码实现:

# 文件linkedstack.py内容
# -*- coding: utf-8 -*-

class Node(object):

    def __init__(self, data, next = None):
        self.data = data
        self.next = next

class LinkedStack:

    # Constructor
    def __init__(self, sourceCollection = None):
        self._items = None
        self._size = 0
        if sourceCollection:
            for item in sourceCollection:
                self.add(item)

    # Accessor methods
    def isEmpty(self):
        return len(self) == 0
    
    def __len__(self):
        return self._size

    def __str__(self):
        return "[" + ", ".join(map(str, self)) + "]"

    def __add__(self, other):
        result = type(self)(self)
        for item in other:
            result.add(item)
        return result

    def __eq__(self, other):

        if self is other: return True
        if type(self) != type(other) or \
           len(self) != len(other):
            return False
        otherIter = iter(other)
        for item in self:
            if item != next(otherIter):
                return False
        return True
    
    def __iter__(self): 
        def visitNodes(node):
            if not node is None:
                visitNodes(node.next)
                tempList.append(node.data)
                
        tempList = list()                
        visitNodes(self._items)
        return iter(tempList)
    
    def add(self, item):
        self.push(item)
    
    def peek(self):
    
        if self.isEmpty():
            raise KeyError("The stack is empty.")
        return self._items.data
    
    def clear(self):
        self._size = 0
        self._items = None

    def push(self, item):
        self._items = Node(item, self._items)
        self._size += 1

    def pop(self):
        if self.isEmpty():
            raise KeyError("The stack is empty.")
        data = self._items.data
        self._items = self._items.next
        self._size -= 1
        return data
# 文件linkedbst.py内容
# -*- coding: utf-8 -*-

class BSTNode(object):
    
    def __init__(self, data, left = None, right = None):
        self.data = data
        self.left = left
        self.right = right
        
from linkedstack import LinkedStack

class LinkedBST:

    def __init__(self, sourceCollection = None):
        self._root = None
        self._size = 0
        if sourceCollection:
            for item in sourceCollection:
                self.add(item)

    def __len__(self):
        
        return self._size
    
    def __str__(self):
        def recurse(node, level):
            s = ""
            if node != None:
                s += recurse(node.right, level + 1)
                s += "| " * level
                s += str(node.data) + "\n"
                s += recurse(node.left, level + 1)
            return s
        return recurse(self._root, 0)

    def __iter__(self):
        if not self.isEmpty():
            stack = LinkedStack()
            stack.push(self._root)
            while not stack.isEmpty():
                node = stack.pop()
                yield node.data
                if node.right != None:
                    stack.push(node.right)
                if node.left != None:
                    stack.push(node.left)

    def isEmpty(self):
        return len(self) == 0
    
    def inorder(self):
        lists = list()
        def recurse(node):
            if node != None:
                recurse(node.left)
                lists.append(node.data)
                recurse(node.right)
        recurse(self._root)
        return iter(lists)

    def postorder(self):
        return None

    def levelorder(self):
        return None

    def __contains__(self, item):
        return self.find(item) != None

    def find(self, item):
        def recurse(node):
            if node is None:
                return None
            elif item == node.data:
                return node.data
            elif item < node.data:
                return recurse(node.left)
            else:
                return recurse(node.right)
        return recurse(self._root)

    def clear(self):
        self._root = None
        self._size = 0

    def add(self, item):
        def recurse(node):
            if item < node.data:
                print("item=", item, "node.data=", node.data)
                if node.left == None:
                    node.left = BSTNode(item)
                else:
                    recurse(node.left)
            elif node.right == None:
                node.right = BSTNode(item)
            else:
                recurse(node.right)

        if self.isEmpty():
            self._root = BSTNode(item)
        else:
            recurse(self._root)
        self._size += 1

    def remove(self, item):
        if not item in self:
            raise KeyError("Item not in tree.""")

        def liftMaxInLeftSubtreeToTop(top):
            parent = top
            currentNode = top.left
            while not currentNode.right == None:
                parent = currentNode
                currentNode = currentNode.right
            top.data = currentNode.data
            if parent == top:
                top.left = currentNode.left
            else:
                parent.right = currentNode.left


        if self.isEmpty(): return None

        itemRemoved = None
        preRoot = BSTNode(None)
        preRoot.left = self._root
        parent = preRoot
        direction = 'L'
        currentNode = self._root
        while not currentNode == None:
            if currentNode.data == item:
                itemRemoved = currentNode.data
                break
            parent = currentNode
            if currentNode.data > item:
                direction = 'L'
                currentNode = currentNode.left
            else:
                direction = 'R'
                currentNode = currentNode.right
                
        if itemRemoved == None: return None
        
        if not currentNode.left == None \
           and not currentNode.right == None:
            liftMaxInLeftSubtreeToTop(currentNode)
        else:
            
            if currentNode.left == None:
                newChild = currentNode.right
                
            else:
                newChild = currentNode.left
                
            if direction == 'L':
                parent.left = newChild
            else:
                parent.right = newChild
            

        self._size -= 1
        if self.isEmpty():
            self._root = None
        else:
            self._root = preRoot.left
        return itemRemoved

    def replace(self, item, newItem):

        probe = self._root
        while probe != None:
            if probe.data == item:
                oldData = probe.data
                probe.data = newItem
                return oldData
            elif probe.data > item:
                probe = probe.left
            else:
                probe = probe.right
        return None
# 文件testbst.py内容
"""
File: testbst.py

A tester program for binary search trees.
"""
#%%
from linkedbst import LinkedBST

#%%
tree = LinkedBST()
lists = ["D", "B", "A", "C","F", "E", "G"]
for i, word in enumerate(lists):
    tree.add(word)
    print("\n\n","*"*10, "--",i,"--","*"*10)
    print("\nString:\n" + str(tree))

#%% 
tree = LinkedBST()
lists = ["H","D", "B", "A", "C", "L", "F", "E", "G", "J", "K", "I", "N", "M", "O"]
for i, word in enumerate(lists):
    tree.add(word)
    print("\n\n","*"*10, "--",i,"--","*"*10)
    print("String:\n" + str(tree))

#%%
print("\n\n前序遍历: ", end="")
for item in tree: 
    print(item, end = " ")

#%%   
print("\n\n中序遍历: ", end="")
for item in tree.inorder(): 
    print(item, end = " ")

运行结果:
在这里插入图片描述

#%%
print("\n\n移除:", end = " ")
for item in "ACDF":
    print(tree.remove(item), end=" ")
print("\n\n: ", len(tree))

#%%
tree = LinkedBST(range(1, 16))
print("\nAdded 1..15:\n" + str(tree))

运行结果:
在这里插入图片描述


#%% 
lists = list(range(1, 16))
import random
random.shuffle(lists)
tree = LinkedBST(lists)
print("\nAdded ", lists, "\n" + str(tree))

运行结果:
在这里插入图片描述

三、课程小结
  • 学习了树的结构定义
  • 学习了二叉树
  • 学习了二叉树遍历
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值