【数据结构4】树的实例-模拟文件系统、二叉树的遍历(先序遍历、中序遍历、后序遍历、层次遍历)

1 树和二叉树
2 树的实例-模拟文件系统
3 二叉树
3.1 二叉树的遍历
二叉树的先序遍历
二叉树的中序遍历
二叉树的后序遍历
二叉树的层次遍历

1 树

树是一种数据结构
比如:目录结构
树是一种可以递归定义的数据结构

树是由n个节点组成的集合:
	如果n=0,那这是一棵空树;
	如果n>0,那存在1个节点作为树的根节点,其他节点可以分为m个集合,每个集合本身又是一棵树

【数据结构4】树的实例-模拟文件系统、二叉树的遍历(先序遍历、中序遍历、后序遍历、层次遍历)_第1张图片

2 树的实例-模拟文件系统

class Node:
    """
    表示文件系统树中的一个节点。

    属性:
        name (str): 节点的名称。对于目录,它以 '/' 结尾,对于文件,不以 '/' 结尾。
        type (str): 节点的类型,'dir' 代表目录,'file' 代表文件。
        children (list): 该节点的子节点列表。仅对目录节点有效。
        parent (Node): 该节点的父节点。如果是根节点,则为 None。
    """

    def __init__(self, name, type='dir'):
        """
        初始化一个新的节点。

        :param name: 节点的名称。目录名称通常以 '/' 结尾,文件名称不以 '/' 结尾。
        :param type: 节点的类型。默认为 'dir'(目录),可以设置为 'file'(文件)以表示文件节点。
        """
        self.name = name
        self.type = type
        self.children = []  # 初始化为空列表,目录节点可以包含子节点
        self.parent = None  # 父节点初始化为 None

    def __repr__(self):
        return self.name


class FileSystemTree:
    """
    表示一个文件系统树,支持创建目录、列出目录内容以及切换目录等操作。

    属性:
        root (Node): 文件系统树的根节点,初始化时创建。
        now (Node): 当前工作目录。操作会影响该目录。
    """

    def __init__(self):
        """
        初始化文件系统树,创建根目录,并将当前工作目录设置为根目录。
        """
        self.root = Node("/")  # 创建根目录,名称为 "/"
        self.now = self.root  # 将当前工作目录设置为根目录

    def mkdir(self, name):
        """
        在当前工作目录下创建一个新的目录。

        :param name: 新目录的名称。必须以 '/' 结尾。如果没有结尾的 '/', 会自动添加。
        """
        if name[-1] != "/":  # 检查目录名称是否以 '/' 结尾
            name += '/'  # 添加 '/' 以确保目录名称正确
        node = Node(name)  # 创建新的目录节点
        self.now.children.append(node)  # 将新目录添加到当前工作目录的子节点列表中
        node.parent = self.now  # 设置新目录的父节点为当前工作目录

    def ls(self):
        """
        展示当前工作目录下的所有子节点。

        :return: 当前目录下的子节点列表(包括目录和文件)。
        """
        return self.now.children  # 返回当前目录的子节点列表

    def cd(self, name):
        """
        切换到指定的目录。支持绝对路径和相对路径。

        :param name: 目标目录的路径。可以是绝对路径(以 '/' 开头)或相对路径(不以 '/' 开头)。
        :return: 无返回值。成功切换目录时,更新当前工作目录。
        :raises ValueError: 如果指定的路径无效或目录不存在,抛出异常。
        """
        if name[-1] != "/":  # 确保目录名称以 '/' 结尾
            name += '/'

        # 处理路径
        components = name.split('/')  # 将路径分解为各个部分
        node = self.now  # 从当前工作目录开始遍历

        for component in components:
            if component == '..':
                # 如果路径部分是 '..',则返回到上一级目录
                if node.parent is not None:
                    node = node.parent
            elif component and component != '/':
                # 如果路径部分是有效的目录名,则查找该目录
                found = False
                for child in node.children:
                    if child.name == component + '/':
                        node = child  # 找到目标目录,更新当前节点
                        found = True
                        break
                if not found:
                    # 如果没有找到目标目录,则抛出异常
                    raise ValueError('无效的目录')

        self.now = node  # 更新当前工作目录为目标目录


tree = FileSystemTree()
tree.mkdir('var/')
tree.mkdir('bin/')
tree.mkdir('bin/python')
tree.mkdir('usr/')

print(tree.root.children)
print(tree.ls())
print(tree.cd('bin/'))
tree.cd("../")
print(tree.ls())

3 二叉树

二叉树的链式存储:将二叉树的节点定义为一个对象,节点之间通过类似链表的链接方式来连接。

节点定义:
class BiTreeNode:
	def __init__(self, data):
		self.data = data
		self.lchild = None
		self.rchild = None

**实现这棵二叉树**
【数据结构4】树的实例-模拟文件系统、二叉树的遍历(先序遍历、中序遍历、后序遍历、层次遍历)_第2张图片

class BiTreeNode:
    def __init__(self, data):
        self.data = data
        self.lchild = None  # 左孩子
        self.rchild = None  # 右孩子


a = BiTreeNode('A')
b = BiTreeNode('B')
c = BiTreeNode('C')
d = BiTreeNode('D')
e = BiTreeNode('E')
f = BiTreeNode('F')
g = BiTreeNode('G')

e.lchild = a
e.rchild = g
a.rchild = c
c.lchild = b
c.rchild = d
g.rchild = f

root = e
print(root.lchild.rchild.data)

3.1 二叉树的遍历

二叉树的前序遍历是一种深度优先遍历方式。
遍历顺序为:
	访问根节点
	前序遍历左子树
	前序遍历右子树

二叉树的中序遍历也是一种深度优先遍历方式。
遍历顺序为:
	中序遍历左子树
	访问根节点
	中序遍历右子树
	
二叉树的后序遍历也是一种深度优先遍历方式。
遍历顺序为:
	后序遍历左子树
	后序遍历右子树
	访问根节点

二叉树的层次遍历(也称为广度优先遍历)是一种按层从上到下、从左到右访问节点的遍历方式。
常用的实现方法是利用队列(Queue)。

【数据结构4】树的实例-模拟文件系统、二叉树的遍历(先序遍历、中序遍历、后序遍历、层次遍历)_第3张图片

二叉树的前序遍历

def pre_order(root):
    """
    二叉树的前序遍历
    :param root:
    :return:
    """
    if root:
        print(root.data, end=',')
        pre_order(root.lchild)
        pre_order(root.rchild)

pre_order(root)  # E,A,C,B,D,G,F,
class TreeNode:
    def __init__(self, value=0, left=None, right=None):
        """
        初始化一个二叉树节点。
        
        :param value: 节点的值
        :param left: 左子节点,默认为 None
        :param right: 右子节点,默认为 None
        """
        self.value = value
        self.left = left  # 左子节点
        self.right = right  # 右子节点

def preorder_traversal(root):
    """
    前序遍历二叉树。
    
    前序遍历的顺序为:根节点 -> 左子树 -> 右子树。
    
    :param root: 二叉树的根节点
    :return: 节点值的列表,按照前序遍历的顺序
    """
    if root is None:
        return []  # 如果当前节点为空,则返回空列表
    
    # 访问根节点,将其值加入结果列表
    result = [root.value]
    
    # 前序遍历左子树,并将结果拼接到结果列表中
    result += preorder_traversal(root.left)
    
    # 前序遍历右子树,并将结果拼接到结果列表中
    result += preorder_traversal(root.right)
    
    return result

# 示例用法
# 构建一个二叉树
#     1
#    / \
#   2   3
#  / \
# 4   5
root = TreeNode(1)
root.left = TreeNode(2)
root.right = TreeNode(3)
root.left.left = TreeNode(4)
root.left.right = TreeNode(5)

# 前序遍历
print(preorder_traversal(root))  # 输出 [1, 2, 4, 5, 3]

二叉树的中序遍历

def mid_order(root):
    """
    二叉树的中序遍历
    :param root:
    :return:
    """
    if root:
        mid_order(root.lchild)
        print(root.data, end=',')
        mid_order(root.rchild)
        
        
mid_order(root)  # A,B,C,D,E,G,F,
class TreeNode:
    def __init__(self, value=0, left=None, right=None):
        """
        初始化一个二叉树节点。
        
        :param value: 节点的值
        :param left: 左子节点,默认为 None
        :param right: 右子节点,默认为 None
        """
        self.value = value
        self.left = left  # 左子节点
        self.right = right  # 右子节点

def inorder_traversal(root):
    """
    中序遍历二叉树。
    
    中序遍历的顺序为:左子树 -> 根节点 -> 右子树。
    
    :param root: 二叉树的根节点
    :return: 节点值的列表,按照中序遍历的顺序
    """
    if root is None:
        return []  # 如果当前节点为空,则返回空列表
    
    result = []
    
    # 先中序遍历左子树,并将结果拼接到结果列表中
    result += inorder_traversal(root.left)
    
    # 然后访问根节点,将其值加入结果列表
    result.append(root.value)
    
    # 最后中序遍历右子树,并将结果拼接到结果列表中
    result += inorder_traversal(root.right)
    
    return result

# 示例用法
# 构建一个二叉树
#     1
#    / \
#   2   3
#  / \
# 4   5
root = TreeNode(1)
root.left = TreeNode(2)
root.right = TreeNode(3)
root.left.left = TreeNode(4)
root.left.right = TreeNode(5)

# 中序遍历
print(inorder_traversal(root))  # 输出 [4, 2, 5, 1, 3]

二叉树的后序遍历

def post_order(root):
    """
    二叉树的后序遍历
    :param root:
    :return:
    """
    if root:
        post_order(root.lchild)
        post_order(root.rchild)
        print(root.data, end=',')


post_order(root)  # A,C,B,D,G,F,E
class TreeNode:
    def __init__(self, value=0, left=None, right=None):
        """
        初始化一个二叉树节点。
        
        :param value: 节点的值
        :param left: 左子节点,默认为 None
        :param right: 右子节点,默认为 None
        """
        self.value = value
        self.left = left  # 左子节点
        self.right = right  # 右子节点

def postorder_traversal(root):
    """
    后序遍历二叉树。
    
    后序遍历的顺序为:左子树 -> 右子树 -> 根节点。
    
    :param root: 二叉树的根节点
    :return: 节点值的列表,按照后序遍历的顺序
    """
    if root is None:
        return []  # 如果当前节点为空,则返回空列表
    
    result = []
    
    # 先后序遍历左子树,并将结果拼接到结果列表中
    result += postorder_traversal(root.left)
    
    # 然后后序遍历右子树,并将结果拼接到结果列表中
    result += postorder_traversal(root.right)
    
    # 最后访问根节点,将其值加入结果列表
    result.append(root.value)
    
    return result

# 示例用法
# 构建一个二叉树
#     1
#    / \
#   2   3
#  / \
# 4   5
root = TreeNode(1)
root.left = TreeNode(2)
root.right = TreeNode(3)
root.left.left = TreeNode(4)
root.left.right = TreeNode(5)

# 后序遍历
print(postorder_traversal(root))  # 输出 [4, 5, 2, 3, 1]

二叉树的层次遍历

from collections import deque


def level_order(root):
    """
    层次遍历二叉树的函数
    :param root: 二叉树的根节点
    :return: None
    """
    # 初始化一个队列,用于层次遍历
    queue = deque()

    # 将根节点入队
    queue.append(root)

    # 当队列不为空时,继续遍历
    while len(queue) > 0:
        # 从队列中取出一个节点
        node = queue.popleft()

        # 打印当前节点的数据
        print(node.data, end=',')

        # 如果当前节点有左子节点,将左子节点入队
        if node.lchild:
            queue.append(node.lchild)

        # 如果当前节点有右子节点,将右子节点入队
        if node.rchild:
            queue.append(node.rchild)


level_order(root)  # E,A,G,C,F,B,D,
from collections import deque

class TreeNode:
    def __init__(self, value=0, left=None, right=None):
        """
        初始化一个二叉树节点。
        
        :param value: 节点的值
        :param left: 左子节点,默认为 None
        :param right: 右子节点,默认为 None
        """
        self.value = value
        self.left = left  # 左子节点
        self.right = right  # 右子节点

def level_order_traversal(root):
    """
    层次遍历二叉树(广度优先遍历)。
    
    层次遍历的顺序为:按层从上到下,从左到右依次访问每个节点。
    
    :param root: 二叉树的根节点
    :return: 节点值的列表,按照层次遍历的顺序
    """
    if root is None:
        return []  # 如果根节点为空,则返回空列表
    
    result = []  # 用于存储遍历结果的列表
    queue = deque([root])  # 初始化队列,并将根节点加入队列
    
    while queue:
        node = queue.popleft()  # 从队列的左端弹出一个节点
        result.append(node.value)  # 将弹出的节点值加入结果列表
        
        # 如果左子节点存在,则加入队列
        if node.left:
            queue.append(node.left)
        
        # 如果右子节点存在,则加入队列
        if node.right:
            queue.append(node.right)
    
    return result

# 示例用法
# 构建一个二叉树
#     1
#    / \
#   2   3
#  / \
# 4   5
root = TreeNode(1)
root.left = TreeNode(2)
root.right = TreeNode(3)
root.left.left = TreeNode(4)
root.left.right = TreeNode(5)

# 层次遍历
print(level_order_traversal(root))  # 输出 [1, 2, 3, 4, 5]

你可能感兴趣的:(算法题,数据结构)