Chap22 Binary Search Trees 二叉查找树
- binary search --> access things in sub-linear time(小于O(N))
- 每次取半,can find item in O(lg(N)) time
1 Binary Search Trees Concepts
- 二叉搜索树(BST),节点有两个指向其他节点(通常称为左节点和右节点)的指针,以及它们需要保存的数据。左小于中小于右(或等于,如果允许重复)节点。树本身有一个指向节点(root)的指针
1.1 Terminology
- Node
- Edge --> a connection between two nodes,可以有向(一个方向移动),可以无向(2个方向移动),这里指directed edges(有向)
- Graph --> a collection of nodes and edges
- (Directed) path --> a sequence of nodes that “follows the edges” of the graph but does not repeat an edge
- Undirected path --> ignore the direction of the edges (i.e., ignore the direction of the arrows),也不允许edge重复
- Cycle --> a path that starts and ends at the same node—logically a “loop” in the graph
- Undirected cycle --> an undirected path that starts and ends at the same node— logically a “loop” where we might ignore the direction of the arrows
- Connected --> A graph is connected when there exists at least one undirected path between any pair of nodes
- Tree --> a data structure that comprises nodes and edges and is a connected graph with no undirected cycles 任何一对node之间都有一个undirected path
- Rooted tree --> a tree in which one particular node is the root node 根节点的特殊之处在于存在一条从它到树中每个其他节点的定向路径
- Binary tree --> a rooted tree where each node has at most two outgoing edges (other nodes that it points at)
- Binary search tree --> 一个左小于中小于等于右的二叉树
- Parent (of a node)
- Children (of a node)
- Ancestors (of a node) --> 到该节点的定向路径的节点集
- Descendants (of a node) --> 这个节点到它的后代存在一条直接路径的节点集
- Depth (of a node) --> 从根节点到该节点的路径长度。对于根结点是深度0还是深度1,不同的人有不同的习惯。我们将使用根结点深度为0的约定
- Leaf nodes --> a node with no children
- Sub-tree
- Height (of a node) --> 从节点到叶节点的最大路径长度, 不同的人使用不同的约定来精确计算高度(例如,一个叶节点的高度是0还是1)。我们将使用一个叶节点的高度是1,NULL的高度是0的约定
- Height (of a tree) --> root的height
- Full --> 每个节点要么0个children,要么2个
- Balanced --> 每个节点的子节点高度差不超过1
- Complete --> 除了最后一层,每一层都有尽可能多的节点,最后一层从左到右填充
1.2 Uses
- 二叉搜索树的一个用途是实现map和set ADTs的O(lg(N))访问时间进行加法、查找(检查集合中是否包含项,或者查找map中给定键的值)和删除
- BSTs的key的type必须是能够比较大小的type
- 高效地找到给定范围内的所有键(例如,在5000到30000之间)
- 找到大于或等于特定值的最小键值
- abstract syntax trees 抽象语法树 --> 当一个程序解析输入时——分析它的语法结构——构建一棵表示从解析中派生的含义的树通常是有用的
2 Adding to a Binary Search Tree
- O(lg(N)) time
2.1 Recursion
2.2 Find the Parent of the Node to Add
- keeping a pointer to a node and iteratively seeking out the node whose left or right pointer we need to update. As with linked lists, such an approach must stop at the node that will be the parent of the newly added node, and adding to the empty tree is a special case
- require the most code and is the least elegant
2.3 Pointer to a Pointer to a Node
- if L is the length of that path, then the algorithm is O(L) . If our tree is
balanced (or close to balanced), then L属于O(lg(N)), so the insertion algorithm is O(lg(N))
3 Searching a Binary Tree
- 如果树是平衡的(或接近平衡),有O(lg(N))搜索时间
4 Removing From a Binary Search Tree
- 使用一个指向指针的指针Node **, 搜索树,最终得到一个指针指向想要删除的node
- 找到要删除的节点后,需要操作树指针来实际删除该节点
- 对于要删除的节点有0个子节点或1个子节点的情况(即,至少它的一个指针是NULL),这种删除过程几乎与链表删除过程完全相同 --> 更新父节点的左右指针使其指向要删除节点的单子节点(如果该节点没有子节点,则将其设置为NULL),删除要删除的节点,完成
- 在删除根节点的情况下,需要更新根指针本身,而不是父节点的左指针或右指针(因为根节点没有父节点)
- 删除有2个子节点的node --> 找到树中有0个或1个子节点的最相似的节点,把数据转换成想要删除的节点,然后从树中删除该节点
- 其实只有3种情况:左子节点是NULL,右子节点是NULL,都不是NULL
if (node->left == NULL) {
//无子节点or只有右子节点
temp = node->right;
delete node;
return temp; //each recursive call returns the node that its parent should set its appropriate child to
}
else if (node->right == NULL) {
...
}
else {
...
}
5 Tree Traversals
5.1 Inorder Traversal 中序遍历
- 从最小打印到最大 --> 左根右
//a helper that would be called with the root of the tree
void printInorder(Node * current) {
if (current != NULL