Data Structures CSCI 262, Spring 2002 Lecture 2 Classes and
Download
Report
Transcript Data Structures CSCI 262, Spring 2002 Lecture 2 Classes and
Data Structures
CSCI 132, Spring 2014
Lecture 37
Binary Search Trees II
1
Definition of a Binary Search
Tree
A binary search tree is either empty, or every node has a key for
which the following are true:
1) The key of the root node is greater than any key in the left subtree.
2) The key of the root node is less than any key in the right subtree.
3) The left and right subtrees are themselves binary search trees.
2
Inserting into a Binary Search
Tree
To insert an item into a binary search tree, we must make sure
that the tree maintains the binary search tree property.
•We determine where an item may be inserted in a subtree by
comparison with the item at the root of the subtree
•If the item to be inserted has a value less than the value at the
subroot, it must be inserted in the left subtree.
•If the item to be inserted has a value greater than the value of
the subroot, it must be inserted into the right subtree.
3
Implementing insert( )
template <class Record>
Error_code Search_tree<Record> :: insert(const Record &new_data)
{
return search_and_insert(root, new_data);
}
template <class Record>
Error_code Search_tree<Record> :: search_and_insert(
Binary_node<Record> * &sub_root, const Record &new_data)
{
if (sub_root == NULL) {
sub_root = new Binary_node<Record>(new_data);
return success;
} else if (new_data < sub_root->data)
return search_and_insert(sub_root->left, new_data);
else if (new_data > sub_root->data)
return search_and_insert(sub_root->right, new_data);
else
return duplicate_error;
}
tree_sort( )
1. Build a binary search tree by using n calls to insert( ).
2. Print items out in order using inorder traversal.
How long does it take? It depends on the tree:
Short sort time:
Long sort time:
5
Tree_sort( ) vs. quick sort
•In tree sort, the first item is inserted into the root of the tree.
•All subsequent items partitioned to the left or right depending on
their relation to first item.
•This is analogous to quick sort, if the first item in the list is used
as the pivot for partition.
•In tree sort, the second item becomes the root of a subtree.
•It becomes the pivot to partition all subsequent items in that
subtree.
•This is analogous to quick sort for partitioning of one of the
sublists.
6
Running time of tree_sort
All comparisons for tree sort are done during the insert() calls.
The insert() function does the same number of comparisons as
quick sort.
Therefore, tree sort has the same running time as quick sort:
Worst case: Number of comparisons = O(n2)
Average case: Number of comparisons = O(n lg n)
Approximately: 1.39 n lg(n) + O(n)
7
Advantage of tree sort
•Tree sort does not require that all the items are present in the
list at the start of sorting.
•Items can be added gradually as they become available.
•Tree sort works on a linked structure that allows easier
insertions and deletions than a contiguous list.
•Disadvantage: In the worst case, tree sort is slow.
8
Removing a node from a binary
search tree--case 1
Case 1: The node is a leaf.
Replace the pointer to the node with Null. Then delete the node.
sub_root
data
left right
9
remove( ) case 2
Case 2: The node has 1 non-NULL subtree.
Replace link from parent to node with a link from the parent to
the non-null subtree.
Case 2a:
sub_root
data
left right
data
left right
...
Case 2b:
sub_root
data
left right
data
left right
...
10
remove( ) case 3
Case 3: The node has 2 non-NULL subtrees.
Find the immediate predecessor of the node by moving 1 branch to
the left and then as far right as possible.
Replace the node with its immediate predecessor.
sub_root
data
left right
data
left right
...
data
left right
...
11
Examples of removing a node
10
15
5
2
1
7
3
12
6
8
17
13
4
1. Remove node 5. What replaces it?
2. Remove node 15. What replaces it?
12
Implementation of remove( )
template <class Record>
Error_code Search_tree<Record> :: remove_root(
Binary_node<Record>* &sub_root){
if (sub_root == NULL)
return not_present;
// Remember node to delete at end.
Binary_node<Record> *to_delete = sub_root;
if (sub_root->right == NULL)
//cases 1 and 2a
sub_root = sub_root->left;
else if (sub_root->left == NULL) //case 2b
sub_root = sub_root->right;
13
remove( ) continued
else { // Neither subtree is empty. Case 3
to_delete = sub_root->left; // Move left to find predecessor.
Binary_node<Record> *parent = sub_root; // parent of to_delete
while (to_delete->right != NULL) { // to_delete is not the predecessor.
parent = to_delete;
to_delete = to_delete->right;
}
sub_root->data = to_delete->data; // Move from to_delete to root.
if (parent == sub_root)
sub_root->left = to_delete->left;
else
parent->right = to_delete->left;
}
delete to_delete; // Remove to_delete from tree.
return success;
}
14
search_and_destroy( )
template <class Record>
Error_code Search_tree<Record> :: remove(const Record &target) {
return search_and_destroy(root, target);
}
template <class Record>
Error_code Search_tree<Record> :: search_and_destroy(
Binary_node<Record>* &sub_root, const Record &target) {
// find the node to remove and remove it.
// we will work this out in class.
}
15
search_and_destroy( )
template <class Record>
Error_code Search_tree<Record> :: remove(const Record &target) {
return search_and_destroy(root, target);
}
template <class Record>
Error_code Search_tree<Record> :: search_and_destroy(
Binary_node<Record>* &sub_root, const Record &target) {
if (sub_root == NULL || sub_root->data == target)
return remove_root(sub_root);
else if (target < sub_root->data)
return search_and_destroy(sub_root->left, target);
else
return search_and_destroy(sub_root->right, target);
}
16