Sorted Lists CS 302 Data Structures Sections 4

  • Slides: 50
Download presentation
Sorted Lists CS 302 - Data Structures Sections 4. 1, 4. 2 & 4.

Sorted Lists CS 302 - Data Structures Sections 4. 1, 4. 2 & 4. 3

Sorted List Implementations Array-based Linked-list-based

Sorted List Implementations Array-based Linked-list-based

Array-based Implementation template<class Item. Type> class Sorted. Type { public: void Make. Empty(); bool

Array-based Implementation template<class Item. Type> class Sorted. Type { public: void Make. Empty(); bool Is. Full() const; int Length. Is() const; void Retrieve. Item(Item. Type&, bool&); void Insert. Item(Item. Type); void Delete. Item(Item. Type); void Reset. List(); bool Is. Last. Item(); void Get. Next. Item(Item. Type&); private: int length; Item. Type info[MAX_ITEMS]; int current. Pos; };

Insert. Item (Item. Type item) Function: Adds item to list Preconditions: (1) List has

Insert. Item (Item. Type item) Function: Adds item to list Preconditions: (1) List has been initialized, (2) List is not full, (3) item is not in list (4) List is sorted by key member. Postconditions: (1) item is in list, (2) List is still sorted.

Array-based Implementation template<class Item. Type> void Sorted. Type<Item. Type>: : Insert. Item(Item. Type item)

Array-based Implementation template<class Item. Type> void Sorted. Type<Item. Type>: : Insert. Item(Item. Type item) { int location = 0; bool found; found = false; while( (location < length) && !found) { if (item < info[location]) found = true; else location++; O(N) } (cont)

Array-based Implementation for (int index = length; index > location; index--) info[index] = info[index

Array-based Implementation for (int index = length; index > location; index--) info[index] = info[index - 1]; info[location] = item; O(1) length++; } Total time: O(N)

Delete. Item(Item. Type item) Function: Deletes the element whose key matches item's key Preconditions:

Delete. Item(Item. Type item) Function: Deletes the element whose key matches item's key Preconditions: (1) List has been initialized, (2) Key member of item has been initialized, (3) There is only one element in list which has a key matching item's key, (4) List is sorted by key member. Postconditions: (1) No element in list has a key matching item's key, (2) List is still sorted.

Array-based Implementation template<class Item. Type> void Sorted. Type<Item. Type>: : Delete. Item(Item. Type item)

Array-based Implementation template<class Item. Type> void Sorted. Type<Item. Type>: : Delete. Item(Item. Type item) { int location = 0; O(N) while (item != info[location]) location++; for (int index = location + 1; index < length; index++) info[index - 1] = info[index]; O(N) length--; } Total time: O(N)

Retrieve. Item (Item. Type& item, boolean& found) • Function: Retrieves list element whose key

Retrieve. Item (Item. Type& item, boolean& found) • Function: Retrieves list element whose key matches item's key (if present). • Preconditions: (1) List has been initialized, (2) Key member of item has been initialized. • Postconditions: (1) If there is an element some. Item whose key matches item's key, then found=true and item is a copy of some. Item; otherwise, found=false and item is unchanged, (2) List is unchanged.

Naive approach: use Linear Search Algorithm item is in the list retrieve “Sarah” item

Naive approach: use Linear Search Algorithm item is in the list retrieve “Sarah” item is not in the list retrieve “George” Might not have to search the whole list!

Improved Retrieve. Item() template<class Item. Type> void Sorted. Type<Item. Type>: : Retrieve. Item (Item.

Improved Retrieve. Item() template<class Item. Type> void Sorted. Type<Item. Type>: : Retrieve. Item (Item. Type& item, bool& found) { int location = 0; found = false; while ( (location < length) && !found) { if ( item > info[location]) { location++; else if(item < info[location]) location = length; // to break out of the loop… else { found = true; item = info[location]; } } Still O(N) …

Binary Search Algorithm Split the current search area in half, and if the item

Binary Search Algorithm Split the current search area in half, and if the item is not found there, then search the appropriate half.

- Search for 24:

- Search for 24:

Binary Search Algorithm (cont. ) template<class Item. Type> void Sorted. Type<Item. Type>: : Retrieve.

Binary Search Algorithm (cont. ) template<class Item. Type> void Sorted. Type<Item. Type>: : Retrieve. Item(Item. Type& item, bool& found) { int mid. Point; int first = 0; int last = length - 1; found = false; while( (first <= last) && !found) { mid. Point = (first + last) / 2; if (item < info[mid. Point]) last = mid. Point - 1; else if(item > info[mid. Point]) first = mid. Point + 1; else { found = true; item = info[mid. Point]; } } } O(log. N)

Binary Search Efficiency (1) Number of iterations: – For a list of 11 elements,

Binary Search Efficiency (1) Number of iterations: – For a list of 11 elements, it never iterates more than 4 times (e. g. , approximately log 2 11 times). – Linear Search can iterate up to 11 times. Number of Iterations List Length Linear Search (average) Binary Search 10 5. 5 3. 3 100 50. 5 6. 6 1, 000 500. 5 10 10, 000 5000. 5 13. 3

Binary Search Efficiency (cont’d) (2) Number of computations per iteration: – Binary search does

Binary Search Efficiency (cont’d) (2) Number of computations per iteration: – Binary search does more work per iteration than Linear Search Linear search iterations while ( (location < length) && !found) { if ( item > info[location]) { location++; else if(item < info[location]) location = length; // to break out of the loop… else { found = true; item = info[location]; } } Binary search iterations while( (first <= last) && !found) { mid. Point = (first + last) / 2; if (item < info[mid. Point]) last = mid. Point - 1; else if(item > info[mid. Point]) first = mid. Point + 1; else { found = true; item = info[mid. Point]; }

Is Binary Search more efficient? • Overall, it can be shown that: – If

Is Binary Search more efficient? • Overall, it can be shown that: – If the number of list elements is small (typically, under 20), then Linear Search is faster. – If the number of list elements is large, then Binary Search is faster.

List Implementations Big-O Comparison of List Operations Operation Unsorted Sorted Make. Empty O(1) Length.

List Implementations Big-O Comparison of List Operations Operation Unsorted Sorted Make. Empty O(1) Length. Is O(1) Is. Full O(1) Reset. List O(1) Get. Next. Item O(1) Retrieve. Item O(N) O(log N) Insert. Item O(1) O(N) Delete. Item O(N)

Example • Suppose we have a million elements in an sorted list; which algorithm

Example • Suppose we have a million elements in an sorted list; which algorithm would be faster? (1) A binary search on a 500 -MHz computer or (2) A linear search on a 5 -GHz computer

Example (cont’d) • Assumptions: (1) Each iteration of a linear search will be twice

Example (cont’d) • Assumptions: (1) Each iteration of a linear search will be twice as fast as each iteration of a binary search on the same computer. (2) Each instruction on the 5 -GHz computer is 10 times faster than each instruction on the 500 -MHz computer.

Example (cont’d) • Consider number of iterations first: Binary Search log 2(1, 000) ~

Example (cont’d) • Consider number of iterations first: Binary Search log 2(1, 000) ~ 20 (worst-case) Linear Search 1, 000 iterations (worst-case) or 500, 000 (average-case) • Binary search will be 500, 000/20 = 25, 000 faster than linear search.

Example (cont’d) • Assuming same computers and using assumption (1): – Binary search would

Example (cont’d) • Assuming same computers and using assumption (1): – Binary search would be 25, 000/2 = 12, 500 faster!

Example (cont’d) • Assuming different computers and using both assumptions (1) and (2): –

Example (cont’d) • Assuming different computers and using both assumptions (1) and (2): – Binary search will be 25, 000/20 = 1250 times faster on the 500 -MHz computer than linear search on the 5 -GHz computer!

Linked-list-based Implementation template <class Item. Type> private: struct Node. Type; int length; Node. Type<Item.

Linked-list-based Implementation template <class Item. Type> private: struct Node. Type; int length; Node. Type<Item. Type>* list. Data; template<class Item. Type> Node. Type<Item. Type>* current. Pos; class Sorted. Type { }; public: Sorted. Type(); ~Sorted. Type(); void Make. Empty(); bool Is. Full() const; int Length. Is() const; void Retrieve. Item(Item. Type&, bool&); void Insert. Item(Item. Type); void Delete. Item(Item. Type); void Reset. List(); bool Is. Last. Item() const; void Get. Next. Item(Item. Type&);

Retrieve. Item (Item. Type& item, boolean& found) • Function: Retrieves list element whose key

Retrieve. Item (Item. Type& item, boolean& found) • Function: Retrieves list element whose key matches item's key (if present). • Preconditions: (1) List has been initialized, (2) Key member of item has been initialized. • Postconditions: (1) If there is an element some. Item whose key matches item's key, then found=true and item is a copy of some. Item; otherwise, found=false and item is unchanged, (2) List is unchanged.

Retrieve. Item Could use linear search O(N) time

Retrieve. Item Could use linear search O(N) time

Retrieve. Item (cont. ) template<class Item. Type> void Sorted. Type<Item. Type>: : Retrieve. Item(Item.

Retrieve. Item (cont. ) template<class Item. Type> void Sorted. Type<Item. Type>: : Retrieve. Item(Item. Type& item, bool& found) { Node. Type<Item. Type>* location; location = list. Data; found = false; while( (location != NULL) && !found) { if (location info < item) location = location next; else if (location info == item) { found = true; O(N) item = location info; } else location = NULL; // to break out of the loop … } }

What about Binary Search? • Not efficient any more! – Cannot find the middle

What about Binary Search? • Not efficient any more! – Cannot find the middle element in O(1) time.

Insert. Item (Item. Type item) Function: Adds item to list Preconditions: (1) List has

Insert. Item (Item. Type item) Function: Adds item to list Preconditions: (1) List has been initialized, (2) List is not full, (3) item is not in list (4) List is sorted by key member. Postconditions: (1) item is in list, (2) List is still sorted.

Insert. Item

Insert. Item

Insert. Item (cont. ) • Can we compare one item ahead? – Yes, but

Insert. Item (cont. ) • Can we compare one item ahead? – Yes, but we need to check for special cases … • In general, we must keep track of the previous pointer, as well as the current pointer.

Insert. Item (cont. ) prev. Loc = location next

Insert. Item (cont. ) prev. Loc = location next

Insert at the beginning of the list Case 1 new. Node next= location; list.

Insert at the beginning of the list Case 1 new. Node next= location; list. Data=new. Node;

Insert between first and last elements Case 2 new. Node next=location; prev. Loc next

Insert between first and last elements Case 2 new. Node next=location; prev. Loc next = new. Node;

Insert at the end of the list Case 3 new. Node next=location; prev. Loc

Insert at the end of the list Case 3 new. Node next=location; prev. Loc next = new. Node;

Insert into an empty list Case 4 new. Node next=location; list. Data=new. Node;

Insert into an empty list Case 4 new. Node next=location; list. Data=new. Node;

(1) (2) new. Node next= location; list. Data=new. Node; new. Node next=location; prev. Loc

(1) (2) new. Node next= location; list. Data=new. Node; new. Node next=location; prev. Loc next = new. Node; (4) (3) new. Node next=location; prev. Loc next = new. Node; new. Node next=location; list. Data=new. Node;

Insert. Item (cont. ) template <class Item. Type> void Sorted. Type<Item. Type>: : Insert.

Insert. Item (cont. ) template <class Item. Type> void Sorted. Type<Item. Type>: : Insert. Item(Item. Type new. Item) { Node. Type<Item. Type>* new. Node; Node. Type<Item. Type>* pred. Loc; Node. Type<Item. Type>* location; bool found; found = false; location = list. Data; pred. Loc = NULL; O(1) while( location != NULL && !found) { if (location info < new. Item) { pred. Loc = location; location = location next; } else found = true; } O(N)

Insert. Item (cont. ) new. Node = new Node. Type<Item. Type>; new. Node info

Insert. Item (cont. ) new. Node = new Node. Type<Item. Type>; new. Node info = new. Item; if (pred. Loc == NULL) { new. Node next = list. Data; cases (1) and (4) list. Data = new. Node; } else { new. Node next = location; pred. Loc next = new. Node; cases (2) and (3) } length++; } O(1)

Delete. Item(Item. Type item) Function: Deletes the element whose key matches item's key Preconditions:

Delete. Item(Item. Type item) Function: Deletes the element whose key matches item's key Preconditions: (1) List has been initialized, (2) Key member of item has been initialized, (3) There is only one element in list which has a key matching item's key, (4) List is sorted by key member. Postconditions: (1) No element in list has a key matching item's key, (2) List is still sorted.

Delete. Item • The Delete. Item we wrote for unsorted lists • would work

Delete. Item • The Delete. Item we wrote for unsorted lists • would work for sorted lists too! Another possibility is to write a new Delete. Item based on several cases (see textbook)

Other Sorted. List functions • Same as in the Unsorted. List class. . .

Other Sorted. List functions • Same as in the Unsorted. List class. . .

Sorted List Implementations Big-O Comparison of Sorted List Operations Operation Array Implementation Linked Implementation

Sorted List Implementations Big-O Comparison of Sorted List Operations Operation Array Implementation Linked Implementation Class constructor O(1) Destructor O(1) O(N) Make. Empty O(1) O(N) Is. Full O(1) Length. Is O(1) Reset. List O(1) Get. Next. Item O(1) Retrieve. Item O(log. N) O(N) Insert. Item O(N) Delete. Item O(N)

Exercise: Write a client function that splits a sorted list into two sorted lists

Exercise: Write a client function that splits a sorted list into two sorted lists using the following specification. Split. Lists (Sorted. Type list, Item. Type item, Sorted. Type& list 1, Sorted. Type& list 2) Function: Divides list into two lists according to the key of item. Preconditions: list has been initialized and is not empty. Postconditions: list 1 contains all the items of list whose keys are less than or equal to item’s key. list 2 contains all the items of list whose keys are greater than item’s key.

void Split. Lists(const Sorted. Type& list, Item. Type item, Sorted. Type& list 1, Sorted.

void Split. Lists(const Sorted. Type& list, Item. Type item, Sorted. Type& list 1, Sorted. Type& list 2) { Item. Type list. Item; list 1. Make. Empty(); list 2. Make. Empty(); list. Reset. List(); while (!list. Is. Last. Item()) { list. Get. Next. Item(list. Item); if(list. Item > item) list 2. Insert. Item(list. Item); else list 1. Insert. Item(list. Item); } } What is the running time using big-O? O(N 2)

Exercise: Write a client function that takes two lists (unsorted or sorted) and returns

Exercise: Write a client function that takes two lists (unsorted or sorted) and returns a Boolean indicating whether the second list is a sublist of the first. (i. e. , the first list contains all the elements in the second list but it might contain other elements too).

bool Is. Sub. List (Sorted. Type list 1, Sorted. Type list 2) { Item.

bool Is. Sub. List (Sorted. Type list 1, Sorted. Type list 2) { Item. Type item; bool found=true; list 2. Reset. List(); while ( !list 2. Is. Last. Item() && found) { list 2. Get. Next. Item (item); list 1. Retrieve. Item (item, found); } What is the running time return found; using big-O? } O(Nlog. N) assuming array-based O(N 2) assuming array-based