打牢地基-二叉树、BST

章节

  • tree结构简介
  • 二叉树详解
  • 二分搜索树 – Binary Search Tree

1 tree结构简介

tree-简介

  1. tree 是非线性数据结构
  2. tree 是高效的

tree-高效性

2 二叉树详解

重新认识下tree

1. 和链表一样,动态的数据结构  class Node {      E e;   Node left;   Node right;  }  2. 二叉树具有唯一根节点  3. 二叉树中每个节点最多有两个孩子 - 左孩子 or 右孩子  4. 1个孩子都没有的节点叫叶子节点  5. 二叉树每个节点最多有一个父节点  6. 根节点没有父节点  7. 二叉树具有比链表更明显的递归属性   

二叉树的天然递归属性

一个节点有n个分叉- n叉树

满二叉树

定义: 除了叶子节点,每个节点都有两个孩子节点

二叉树不一定是满二叉树

3 二分搜索树 – Binary Search Tree

1. 二分搜索树是二叉树    2. 二分搜索树每个节点的值:     大于其左子树所有节点的值     小于其右子树所有节点的值     左子树(all node val) < cur node val < 右子树(all node val)    3. 每一棵子树也是二分搜索树   

二分搜索树-BTS 加速查询过程的原因,假如根节点val = 28, 现在在查找 30 这个元素,因为BTS的存储特性,只需要查找右子树部分就可以了,大大提高了查询的速度 有个细节,需要保证node的val 是可比较的,这是有局限性的

3.1 定义树中节点-struct

class Node:     def __init__(self, e=None, left=None, right=None):            self.e = e            self.left = left            self.right = right   

节点结构体中 包含数据域 e, 左子树引用 left, 右子树引用right

3.2 定义BTS

class BST:     def __init__(self, root: Node = None):     """            根节点            :param root:            """            self._root = root            self._size = 0   

一棵树包包含一个根节点root,以及node的个数 size

3.3 add(e)-递归新增一个节点数据

 def add(self, e):            self._root = self._add_element(self._root, e)           def _add_element(self, root, e):     """            递归构建二分搜索树            :param root:            :param e:            :return:            """     if root is None:                self._size += 1     """                返回的是子树根节点                """     return Node(e)     elif e < root.e:                root.left = self._add_element(root.left, e)     elif e > root.e:                root.right = self._add_element(root.right, e)     return root   

3.4 contains- 递归查询树中是否包含某个数据

 def contains(self, e):     return self._contains(self._root, e)     def _contains(self, _root, e):     if self._root is None:    return False     if self._root.e == e:     return True       if e < self._root.e:     return self._contains(self._root.left, e)     if e > self._root.e:     return self._contains(self._root.right, e)   

3.5 二分搜索树的遍历

3.5.1 前序遍历 – 递归

def pre_order(self):     """            前序遍历            :return:            """            self._pre_order(self._root)           def _pre_order(self, node):     if node is None:     return           print(node.e)                  self._pre_order(node.left)            self._pre_order(node.right)   

3.5.2 中序遍历-递归

 def in_order(self):     """            中序遍历,即是二分搜索树从小到达排序的数据            :return:            """            self._in_order(self._root)           def _in_order(self, node):     if node is None:     return                  self._in_order(node.left)     print(node.e)            self._in_order(node.right)   

3.5.3 后序遍历 post_order – 递归

 def post_order(self):     """            后续遍历            :return:            """            self._post_order(self._root)           def _post_order(self, node):     if node is None:     return            self._post_order(node.left)            self._post_order(node.right)     print(node.e)   

3.5.4 前序遍历 – 非递归算法(栈的应用)- DFS 深度优先遍历

LinkedListStack-使用先前实现的链表栈

 def pre_order_nr(self):     """            前序遍历-非递归,使用栈            :return:            """            stack = LinkedListStack()            stack.push(self._root)     while stack.is_empty() is False:                cur = stack.pop()     print(cur.e)     if cur.right is not None:                    stack.push(cur.right)     if cur.left is not None:                    stack.push(cur.left)   

3.5.5 二分搜索树的层序遍历-(队列的应用) BFS (Breadth First Search)

LinkedListQueue-使用先前实现的链表队列实现层序遍历

 def level_order(self):     """            队列实现中序遍历 - 先进先出            :return:            """            queue = LinkedListQueue()            queue.enqueue(self._root)     while queue.is_empty() is False:                cur = queue.dequeue()     print(cur.e.e)     if cur.e.left is not None:                    queue.enqueue(cur.e.left)     if cur.e.right is not None:                    queue.enqueue(cur.e.right)   

编程的过程中会发现其实每一个节点都会被访问3次。