Day20 数据结构

发布于:2024-11-03 ⋅ 阅读:(4) ⋅ 点赞:(0)

队列 (Queue)

队列是一种运算受限的线性结构,遵循先进先出(FIFO)原则。

  • 队列是一种受限的线性结构

  • 受限之处在于它只允许在表的前端(front)进行删除操作,而在表的后端(rear)进行插入操作

  普通队列 

queue.Queue,适用于多线程环境。

  双端队列 

collections.deque,具有队列和栈性质的数据结构 ,允许在两端进行元素的添加和移除。deque是一个双端队列的实现,它提供了在两端快速添加和移除元素的能力。(结合使用appendleft和popleft时,你实际上是在实现一个栈(Stack)的数据结构 ,append和pop结合使用同理。 )

  优先队列 :元素按照优先级排序。Python 标准库中提供了 queue.PriorityQueue 和 heapq 模块来实现优先队列。

heapq

heapq 模块是 Python 标准库中的一个模块,提供了基于堆的优先队列实现。heapq 模块不是线程安全的,适用于单线程环境。

  代码实现 :

#普通队列 

     import queue

  q = queue.Queue()

  q.put(1)

  q.put(3)

  q.put(2)

  print(q.qsize())

  print(q.get())

  print(q.get())

  print(q.get())

 #双端队列 

  from collections import deque

  q = deque()

  q.append(1)

  q.append(2)

  q.appendleft(3)

  q.appendleft(4)

  print(q.pop())

  print(q.popleft())

#优先队列

import queue

q = queue.PriorityQueue()
# 向队列中添加元素,元素是一个元组 (priority, item),其中 priority 是优先级,item 是实际的数据
q.put((1,'item1'))
q.put((3,'item3'))
q.put((2,'item2'))

print(q.get())
print(q.get())
print(q.get())

#heapq模块

import heapq

# 创建一个列表作为堆
heap = []

# 向堆中添加元素,元素是一个元组 (priority, item)
heapq.heappush(heap, (3, 'Task 3'))
heapq.heappush(heap, (1, 'Task 1'))
heapq.heappush(heap, (2, 'Task 2'))

# 从堆中取出元素
print(heapq.heappop(heap))  # 输出: (1, 'Task 1')
print(heapq.heappop(heap))  # 输出: (2, 'Task 2')
print(heapq.heappop(heap))  # 输出: (3, 'Task 3')

   

树 (Tree)

树的定义:

树是由: nn0)个节点组成的层次结构,每个节点有零个或多个子节点。

1.当n=0时,称为空树;

2.对于任一棵非空树(n> 0),它具备以下性质:

3.树中有一个称为根(Root的特殊结点,用 root 表示;

4.其余结点可分为m(m>0)个互不相交的有限集T1T2... Tm,其中每个集合本身又是一棵

树,称为原来树的子树(SubTree

注意:

1.子树之间不可以相交

2.除了根结点外,每个结点有且仅有一个父结点;

3.一棵N个结点的树有N-1条边。

  树的术语 :

   节点的度:子树个数。

   树的度:最大节点度数。

   叶子节点:度为0的节点。

   父节点:有子树的节点。

   子节点:父节点的子树的根节点。

   兄弟节点:具有同一父节点的节点。

   路径和路径长度:从节点到另一节点的节点序列及其边数。

   节点的层次:根节点为1层,其他节点为父节点层数加1。

   树的深度:最大节点层次。

二叉树 (Binary Tree)

定义

二叉树是由节点和边组成的树,每个节点最多有两个子节点。

二叉树可以为空, 也就是没有结点.

若不为空,则它是由根结点和称为其左子树TL和右子树TR的两个不相交的二叉树组成。

二叉树有五种形态:

注意cd是不同的二叉树, 因为二叉树是有左右之分的

 特性 :

 第i层最大节点数:2^(i 1)。

 深度为k的二叉树最大节点总数:2^k  1。

 叶子节点数n0 = 度为2的非叶子节点数n2 + 1。

特殊二叉树 

 满二叉树:每层节点都有2个子节点。

 完全二叉树:除最后一层外,其他各层节点数都达到最大个数,最后一层从左向右的叶子节点连续存在。

存储 :通常使用链表存储,每个节点包含数据、左子节点引用和右子节点引用。

遍历 (按照顺序访问节点):

前序遍历:根节点、左子树、右子树。

中序遍历:左子树、根节点、右子树。

后序遍历:左子树、右子树、根节点。

二叉查找树 (Binary Search Tree, BST)

二叉查找树是一种特殊的二叉树,具有以下性质:

 每个节点都有一个键值。

 左子树中的所有节点的键值都小于该节点的键值。

 右子树中的所有节点的键值都大于该节点的键值。

 左子树和右子树也是二叉查找树。

 不允许出现键值相等的节点。

创建二叉查找树节点

     class TreeNode:

      def __init__(self, key):

          self.key = key

          self.left = None

          self.right = None

key: 节点的键值。

left:指向左子节点的指针。

right: 指向右子节点的指针

创建二叉查找树类

  class BinarySearchTree:

      def __init__(self):

          self.root = None

   root: 指向二叉搜索树的根节点。初始时为 None

插入节点

插入操作的步骤:

1. 树为空

直接将新节点作为根节点。

2. 树不为空

从根节点开始,根据新节点的键值与当前节点的键值的比较结果,决定向左子树还是右子树

移动。

如果新节点的键值小于当前节点的键值,如果当前节点没有左子树,则将新节点插入到当前

节点的左子树,否则向左子树移动。

如果新节点的键值大于当前节点的键值,如果当前节点没有右子树,则将新节点插入到当前

节点的右子树,否则向右子树移动。

重复上述步骤,直到找到一个空位置,将新节点插入到该位置

      def insert(self, key):

          if self.root is None:

              self.root = TreeNode(key)

          else:

              self._insert(self.root, key)

      

      def _insert(self, node, key):

          if key < node.key:

              if node.left is None:

                  node.left = TreeNode(key)

              else:

                  self._insert(node.left, key)

          elif key > node.key:

              if node.right is None:

                  node.right = TreeNode(key)

              else:

                  self._insert(node.right, key)

      查找节点

      def search(self, key):

          return self._search(self.root, key)

      

      def _search(self, node, key):

          if node is None or node.key == key:

              return node

          if key < node.key:

              return self._search(node.left, key)

          return self._search(node.right, key)

      

      删除节点

      def delete(self, key):

          self.root = self._delete(self.root, key)

      

      def _delete(self, node, key):

          if node is None:

              return node

          if key < node.key:

              node.left = self._delete(node.left, key)

          elif key > node.key:

              node.right = self._delete(node.right, key)

          else:

              if node.left is None and node.right is None:

                  return None

              elif node.left is None:

                  return node.right

              elif node.right is None:

                  return node.left

              temp = self._min_value_node(node.right)

              node.key = temp.key

              node.right = self._delete(node.right, temp.key)

          return node

      

      def _min_value_node(self, node):

          current = node

          while current.left is not None:

              current = current.left

          return current

       中序遍历

        先遍历左子树,然后访问当前节点,最后遍历右子树。

      def inorder_traversal(self):

          result = []

          self._inorder_traversal(self.root, result)

          return result

      前序遍历

      先访问根节点、然后遍历左子树、最后遍历右子树。

      代码实现:

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

class LeftTree:
    def __init__(self):
        self.root = None

    def left_search(self):
        result = []
        if self.root is None:
            return result
        self._left_search(self.root, result)
        return result

    def _left_search(self, node,result):
        if node is None:
            return None
        result.append(node.key)
        if node.left is not None:
            self._left_search(node.left, result)


if __name__ == "__main__":
    tree = LeftTree()
    tree.root = TreeNode(1)
    tree.root.left = TreeNode(2)
    tree.root.right = TreeNode(3)
    tree.root.left.left = TreeNode(4)
    tree.root.left.right = TreeNode(5)
    tree.root.right.left = TreeNode(6)
    tree.root.right.right = TreeNode(7)

    print(tree.left_search())

#输出:[1, 2, 4]

     后序遍历

     先访问左子树、然后遍历右子树、最后遍历根节点。

     代码实现:

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

class BehindTree:
    def __init__(self):
        self.root = None

    def behind_search(self):
        result = []
        if self.root is None:
            return result
        self._behind_search(self.root, result)
        return result

    def _behind_search(self, node, result):
        if node is None:
            return
        self._behind_search(node.left, result)
        self._behind_search(node.right, result)
        result.append(node.key)

if __name__ == "__main__":
    # 创建一个二叉树
    tree = BehindTree()
    tree.root = TreeNode(1)
    tree.root.left = TreeNode(2)
    tree.root.right = TreeNode(3)
    tree.root.left.left = TreeNode(4)
    tree.root.left.right = TreeNode(5)
    tree.root.right.left = TreeNode(6)
    tree.root.right.right = TreeNode(7)


    print(tree.behind_search())

 # 输出: [4, 5, 2, 6, 7, 3, 1]