Binary Search Trees: Implementation and Invariants, Summaries of Computer science

The BST Invariant. ○ A tree whose nodes are ordered is called a binary search tree. ○ We can write a specification function that check BSTs.

Typology: Summaries

2022/2023

Uploaded on 03/01/2023

anala
anala 🇺🇸

4.3

(15)

259 documents

1 / 66

Toggle sidebar

This page cannot be seen from the preview

Don't miss anything!

bg1
Binary Search Trees
pf3
pf4
pf5
pf8
pf9
pfa
pfd
pfe
pff
pf12
pf13
pf14
pf15
pf16
pf17
pf18
pf19
pf1a
pf1b
pf1c
pf1d
pf1e
pf1f
pf20
pf21
pf22
pf23
pf24
pf25
pf26
pf27
pf28
pf29
pf2a
pf2b
pf2c
pf2d
pf2e
pf2f
pf30
pf31
pf32
pf33
pf34
pf35
pf36
pf37
pf38
pf39
pf3a
pf3b
pf3c
pf3d
pf3e
pf3f
pf40
pf41
pf42

Partial preview of the text

Download Binary Search Trees: Implementation and Invariants and more Summaries Computer science in PDF only on Docsity!

Binary Search Trees

Reflecting on Dictionaries

Cost

 Hash dictionaries are clearly the best implementation

 O(1) lookup and insertion are hard to beat!

or are they?

 It’s O(1) average

o we could be (very) unlucky and incur an O(n) cost

 e.g., if we use a poor hash function

 It’s O(1) amortized

o from time to time, we need to resize the table

 then the operation costs O(n)

 Operations like finding the entry with

the smallest key cost O(n)

o we have to check every entry

Always read
the fine prints!
Always read
the fine prints!
Using hash dictionaries is too risky
or not good enough
for applications that require a
guaranteed (short) response time

But they are great for applications that don’t have such constraints

 Develop a data structure that has guaranteed O(log n)

worst-case complexity for lookup, insert and find_min

 always!

o O(1) would be great but we can’t get that Unsorted array Array sorted by key Linked list Hash Table

lookup O(n) O(log n) O(n) O(1)

average

O(log n)
insert O(1)

amortized

O(n) O(1)
O(1)

average and amortized

O(log n)
find_min O(n) O(1) O(n) O(n) O(log n)

Goal

ExerciseExerciseExerciseExercise
Returns the
entry with the
smallest key

Searching Sorted Data

Searching for a Number

 Consider the following sorted array

 When searching for a number x using binary search,

we always start by looking at the midpoint, index 4

 Then, 3 things can happen

o x = 12 (and we are done) o x < 12 o x > 12

We always look
at this element

0 1 2 3 4 5 6 7 8 9

  • 2 0 4 7 12 19 22 42 65 12

Searching for a Number

 Assume x < 12, so we look at 4

o if x = 4, we are done o if x < 4, we necessarily look at 0 o if x > 4, we necessarily look at 7

Then, we may look
at these elements

0 1 2 3 4 5 6 7 8 9

  • 2 0 4 7 12 19 22 42 65 if x > 12 if x < 12 if x < 4 if x > 4 0 7

0 1 2 3 4 5 6 7 8 9

  • 2 0 4 7 12 19 22 42 65 Searching for a Number

 Assume x < 4, so we look at 0

o if x = 0, we are done o if x < 0, we necessarily look at - 2

Then, we may look
at this element

if x > 12 if x < 12 if x < 4 if x > 4 if x < 0

Searching for a Number

 An array provides direct access to all elements

o This is overkill for binary search o At any point, it needs direct access to at most two elements 0 1 2 3 4 5 6 7 8 9

  • 2 0 4 7 12 19 22 42 65

if x > 12 if x < 12 if x < 4 if x > 4 if x < 0

if x < 42 if x > 42 if x < 22

Searching for a Number

 We can achieve the same access pattern by pairing up

each element with two pointers

o one to each of the two elements that may be examined next

 We are losing direct access to arbitrary elements,

o but it retains access to the elements that matter to binary search

Arrays gave us
more power
than needed

Constructing this Tree

 Let’s build the first

few nodes of this

example

tree* T = alloc(tree);

T->data = 12;

T->left = alloc(tree);

T->left->data = 4;

T->right= alloc(tree);

T->right->data = 42;

T->left->left = alloc(tree);

typedef struct tree_node tree; struct tree_node { tree* left; int data; tree* right; }; 12 4 42 22 65 19

left data right

T

The End of the Line

 What should

the blank

left/right

fields

point

to?

o NULL

 each sequence of left/right pointers works like a NULL-terminated list

o a dummy node

 not very useful here

typedef struct tree_node tree; struct tree_node { tree* left; int data; tree* right; }; 12 4 42 22 65 19

left data right  

We used dummy nodes to get
direct access to the end of a list

Searching

 Searching for 5

o 5 < 12: go left o 5 > 4: go right o 5 < 7: go left

 nowhere to go

o not there

 We are doing the same steps as binary search

 Starting from an n-element array, the cost is O(log n)

left data right 

If the tree is obtained
18 as in this example

 Develop a data structure that has guaranteed O(log n)

worst-case complexity for lookup, insert and find_min

 always!

o lookup has cost O(log n) o What about insert and find_min? Target data structure

lookup O(log n)
insert O(log n)
find_min O(log n)

Recall our Goal  in this setup