Binary Search Trees

本文详细介绍了二叉查找树的概念、性质和相关算法,包括中序遍历的时间复杂度证明,以及查找、最小值、最大值、前驱、后继等操作。同时探讨了二叉搜索树的插入和删除操作,并通过练习题加深理解。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Definition

A binary search tree is organized, as the name suggests, in a binary tree. Each node is an object. In addition to a key field and satellite data, left, right, and p fields that point to the nodes corresponding to its left child, its right child, and its parent, respectively. If a child or the parent is missing, the appropriate field contains the value NIL.

Property

let x be a node in a binary search tree. If y is a node in the left subtree of x, then key[y]key[x]. If y is a node in the right subtree of x, then key[x]key[y].
The binary-search-tree property allows us to print out all the keys in a binary search tree in sorted order by inorder tree walk.

Theorem If x is the root of an n-node subtree, then the call INORDER-TREE-WALK(x) takes θ(n) time.

Proof: Let T(n) denote the time taken by INORDER-TREE-WALK when it is called on the root of an n-node subtree.
INORDER-TREE-WALK takes a small, constant amount of time on an empty subtree and so T(0)=c for some positive constant c.
For n>0, suppose that INORDER-TREE-WALK is called on a node x whose left subtree has k nodes and whose right subtree has n-k-1 nodes. The time to perform INORDER-TREE-WALK(x) is T(n)=T(k)+T(nk1)+d for some positive constant d.
We use susstitution method to show that T(n)=θ(n) by proving that T(n)=(c+d)n+c.For n=0, we have (c+d)0+c=T(0). For n>0, we have
T(n)=T(k)+T(nk1)+d
=((c+d)k+c)+((c+d)(n-k-1)+c)+d
=(c+d)n+c-(c+d)+c+d
=(c+d)n+c
which completes the proof.

Exercises 12.1-1 For the set of keys {1, 4, 5, 10, 16, 17, 21}, draw binary search trees of height 2, 3, 4, 5, and 6.

这里写图片描述

Exercises 12.1-2 What is the difference between the binary-search-tree property and the min-heap property (see page 129)? Can the min-heap property be used to print out the keys of an n-node tree in sorted order in O(n) time? Explain how or why not.

BSP property:

let x be a node in a binary search tree. If y is a node in the left subtree of x, then key[y]key[x]. If y is a node in the right subtree of x, then key[x]key[y].

Min-Heap property:

for any node in Min-Heap ,key[parent[x]]<=key[x].

Min-Heap cannot print an n-node tree in sorted order in O(n) time, since after remove the minimum, the update of the Min-Heap takes time O(h), which h is the height of the heap.

Exercises 12.1-3 Give a nonrecursive algorithm that performs an inorder tree walk. (Hint: There is an easy solution that uses a stack as an auxiliary data structure and a more complicated but elegant solution that uses no stack but assumes that two pointers can be tested for equality.)

easy solution:

void InOrderTraversal(BinTree T)  
{  
    BinTree BT = T;  
    stack<BinTree> s;  
    while (BT || !(s.empty()))  
    {  
        while (BT)  
        {  
            s.push(BT);  
            BT = BT->Left;  
        }//一直向左面走  
        if (!s.empty())  
        {  
            BT = s.top();  
            s.pop();  
            printf("%c", BT->Data);  
            BT = BT->Right;  
        }  
    }  
}  

complicated solution:

void InOrderTraversal(BinTree T)  
{
    while(BT!=NULL)
    {
        while(BT->left!=NULL&&!BT->left->bVisited)
            BT=BT->left;
        if(!BT->bVisited)
        {
            Visit(BT);
            BT->bVisited=TRUE;
        }
        if(BT->right!=NULL&&!root->right->bVisited)
            BT=BT->right;
        else
            BT=BT->parent;
    }

Exercises 12.1-4 Give recursive algorithms that perform preorder and postorder tree walks in Θ(n) time on a tree of n nodes.

Preorder:

void PreOrderTraversal(BinTree T)  
{  
    if (T)  
    {  
        printf("%c",T->Data);  
        PreOrderTraversal(T->Left);  
        PreOrderTraversal(T->Right);  
    }  
}  

Postorder:

void PostOrderTraversal(BinTree T)  
{  
    if (T)  
    {  
        PostOrderTraversal(T->Left);  
        PostOrderTraversal(T->Right);  
        printf("%c", T->Data);  
    }  
}  

Search operation

TREE-SEARCH procedure given a pointer to the root of the tree an a key k, TREE-SEARCH returns a pointer to a node with key k if one exists; otherwise, it returns NIL.

TREE-SEARCH(x,k)
    if x=NIL or k=key[x]
    then return x
    if k<key[x]
    then return TREE-SEARCH(left[x],k)
    else return TREE-SEARCH(right[x],k)

Minimum and maximum operation

TREE-MINIMUM(X)
while left[x]!=NIL
    do x <- left[x]
return x
TREE-MAXIMUM(X)
while right[x]!=NIL
    do x <- right[x]
return x

Successor operation

Find BST successor in the sorted order. (Inorder tree walk). If all keys are distinct, the successor of a node x is the node with the smallest key greater than key[x].

TREE-SUCCESSOR(X)
if right[x]!=NIL
    then return TREE-MINIMUM(right[x])
y <- P[x]
while y!=NIL and x=right[y]
    do x <- y
       y <- p[y]
return y

If the fight subtree of node x is nonempty, then the successor of x is just the leftmost node in the right subtree. If the right subtree of node x is empty and x has a successor y, then y is the lowest ancestor of x whose left child is also an ancestor of x.

Exercises 12.2-1 Suppose that we have numbers between 1 and 1000 in a binary search tree and want to search for the number 363. Which of the following sequences could not be the sequence of nodes examined?

a. 2, 252, 401, 398, 330, 344, 397, 363.
b. 924, 220, 911, 244, 898, 258, 362, 363.
c. 925, 202, 911, 240, 912, 245, 363.
d. 2, 399, 387, 219, 266, 382, 381, 278, 363.
e. 935, 278, 347, 621, 299, 392, 358, 363.

c , e

Exercises 12.2-2 Write recursive versions of the TREE-MINIMUM and TREE-MAXIMUM procedures.

RECURSIVE-MINIMUM(X)
    if left[x]==NIL
        return x;
    else
        return RECURSIVE-MINIMUM(left[x]);
RECURSIVE-MAXIMUM(X)
    if right[x]==NIL
        return x;
    else
        return RECURSIVE-MINIMUM(right[x]);

Exercises 12.2-3 Write the TREE-PREDECESSOR procedure.

TREE-PREE-PREDECESSOR(X)
    if left[x]!=NIL
        then return TREE-MAXIMUM(left[x])
    y <- P[x]
    while y!=NIL and x=left[x]
        do x <- y
           y <- P[y]
    return y

Exercises 12.2-4 Professor Bunyan thinks he has discovered a remarkable property of binary search trees. Suppose that the search for key k in a binary search tree ends up in a leaf. Consider three sets: A, the keys to the left of the search path; B, the keys on the search path; and C, the keys to the right of the search path. Professor Bunyan claims that any three keys a A, b B, and c C must satisfy a ≤ b ≤ c. Give a smallest possible counterexample to the professor’s claim.

这里写图片描述
such as search(363) 350->362->363
A={361}, B={350,362,363}, C={}
Obviously, 361 is not smaller than 350.

Exercises 12.2-5 Show that if a node in a binary search tree has two children,then its successor has no left child and its predecessor has no right child.

node predecessor is the maximum of its left sub-tree, and its successor is the minimum of its right sub-tree. The smallest element has no left child, and the largest one has no right child.

Exercises 12.2-6 Consider a binary search tree T whose keys are distinct. Show that if the right subtree of a node x in T is empty and x has a successor y, then y is the lowest ancestor of x whose left child is also an ancestor of x. (Recall that every node is its own ancestor.)

if x don’t have right subtree, we just find node y that x was first contained in y left subtree. so x node successor is the lowest ancestor of x, whose left child is also an ancestor of x.

Exercises 12.2-7 An inorder tree walk of an n-node binary search tree can be implemented by finding the minimum element in the tree with TREE-MINIMUM and then making n-1 calls to TREESUCCESSOR. Prove that this algorithm runs in Θ(n) time.

Every edge was traversal twice. so the cost-time is θ(n)

Insertion operation

TREE-INSERT(T,Z)
    y <- NIL
    x <- root[T]
    while x!=NIL
        do y <- x
           if key[z]<key[x]
           then x <- left[x]
           else x <-right[x]
    P[Z] <- y
    if y==NIL
        then root[T] <- Z
        else if key[Z]<key[y]
                then left[y] <- z
                else right[y] <- z

TREE-INSERT begins at the root of the tree and traces a path downward. The pointer x traces the path, and the pointer y is maintained as the parent of x.

Deletion operation (Three cases)

  • If deletion node z has no children, we modify its parent p[z] to replace z with NIL as its child.
  • If the node z has only a singe child ,we “splice out” z by making a new link between its child and its parent.
  • If the node has two children, we splice out z’s successor y, which has no left child and replace z’s key and satellite data with y’s key and satellite data.
TREE-DELETE(T,z)
    if left[z]==NIL or right[z]=NIL
        then y <- z
    else y <- TREE-SUCCESSOR(z)
    if left[y]!=NIL
        then x <- left[y]
    else x <-right[y]
    if x!=NIL
        then p[x] <- p[y]
    if p[y]==NIL
        then root[T] <- x
    else if y==left[p[y]]
            then left[p[y]] <- x
         else right[p[y]] <- x
    if y!=z
        then key[z] <- key[y]
            copy y's satellite data into z
    return y

#

### 插入操作 对于二叉搜索树中的插入操作,目标是在保持树结构特性的前提下加入新节点。当向树中插入一个新的键值时,如果该位置已经存在,则通常不执行任何更改;否则,会创建新的叶子节点来容纳这个键。 ```java private BinaryNode<AnyType> insert(AnyType x, BinaryNode<AnyType> t) { if (t == null){ return new BinaryNode<>(x, null, null); } int compareResult = x.compareTo(t.element); if (compareResult < 0){ t.left = insert(x, t.left); } else if(compareResult > 0){ t.right = insert(x, t.right); } return t; } ``` 这段代码展示了如何递归地找到合适的位置并插入新元素[^1]。 ### 删除操作 删除操作较为复杂,取决于待删节点的状态: - 如果节点无子节点(即为叶节点),可以直接移除; - 若仅有一个孩子节点,则让此孩子的父指针指向其孙子代替自己; - 当有两个子女时,需寻找合适的继承者——通常是右子树里的最小值或左子树内的最大值,并将其移动到被删除项所在之处。 下面是用于查找最小值的方法作为辅助函数的一部分: ```java private BinaryNode<AnyType> findMin(BinaryNode<AnyType> t) { if (t != null) while (t.left != null) t = t.left; return t; } ``` 而这里是完整的删除逻辑实现方式之一: ```java public BinaryNode<AnyType> remove(AnyType x, BinaryNode<AnyType> t) { if (t == null) return t; // Item not found; do nothing int compareResult = x.compareTo(t.element); if (compareResult < 0){ t.left = remove(x, t.left); } else if (compareResult > 0){ t.right = remove(x, t.right); } else if (t.left != null && t.right != null){ // Two children t.element = findMin(t.right).element; t.right = remove(t.element, t.right); } else{ t = (t.left != null) ? t.left : t.right; } return t; } ``` 上述方法通过调整链接关系实现了安全有效地从二叉搜索树中去除指定元素的功能[^4]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值