Lists - Data Structures - Lecture Notes | CSCI 1200, Study notes of Data Structures and Algorithms

Material Type: Notes; Class: DATA STRUCTURES; Subject: Computer Science; University: Rensselaer Polytechnic Institute; Term: Fall 2008;

Typology: Study notes

Pre 2010

Uploaded on 08/09/2009

koofers-user-v4p
koofers-user-v4p 🇺🇸

10 documents

1 / 6

Toggle sidebar

This page cannot be seen from the preview

Don't miss anything!

bg1
CSCI-1200 Computer Science II Fall 2008
Lecture 9 Lists
Review from Lecture 8
We wrote several versions of a program to maintain a class enrollment list and an associated waiting list.
The first version used vectors to store the information. Unfortunately, erasing items from vectors is
inefficient.
In the second version, we explored iterators and iterator operations as a different means of manipulating
the contents of the vector.
This allows us to replace the vector with a list in the third version. There is an erase function for both
vectors and lists. The vector erase function does pretty much what we did in our enrollment example
program. The list erase function is much more efficient (more on this next week!).
For the enrollment problem, the list is a better sequential container class than the vector.
Today’s Class
Returning references to member variables from member functions
Review of iterators and iterator operations
STL Lists, erase and insert on lists
Differences between indices and iterators, differences between lists and vectors
Introductory example on linked lists.
Basic linked list operations:
Stepping through a list
Push back
... & we’ll continue on Tuesday
9.1 References and Return Values
A reference is an alias for another variable. For example:
string a = "Tommy";
string b = a; // a new string is created using the string copy constructor
string& c = a; // c is an alias/reference to the string object a
b[1] = ’i’;
cout << a << " " << b << " " << c << endl; // outputs: Tommy Timmy Tommy
c[1] = ’a’;
cout << a << " " << b << " " << c << endl; // outputs: Tammy Timmy Tammy
The reference variable crefers to the same string as variable a. Therefore, when we change c, we change a.
Exactly the same thing occurs with reference parameters to functions and the return values of functions. Let’s
look at the Student class from Lecture 4 again:
class Student {
public:
const string& first_name() const { return first_name_; }
const string& last_name() const { return last_name_; }
// etc....
private:
string first_name_;
string last_name_;
// etc...
};
pf3
pf4
pf5

Partial preview of the text

Download Lists - Data Structures - Lecture Notes | CSCI 1200 and more Study notes Data Structures and Algorithms in PDF only on Docsity!

CSCI-1200 Computer Science II — Fall 2008

Lecture 9 — Lists

Review from Lecture 8

  • We wrote several versions of a program to maintain a class enrollment list and an associated waiting list.
    • The first version used vectors to store the information. Unfortunately, erasing items from vectors is inefficient.
    • In the second version, we explored iterators and iterator operations as a different means of manipulating the contents of the vector.
    • This allows us to replace the vector with a list in the third version. There is an erase function for both vectors and lists. The vector erase function does pretty much what we did in our enrollment example program. The list erase function is much more efficient (more on this next week!).
  • For the enrollment problem, the list is a better sequential container class than the vector.

Today’s Class

  • Returning references to member variables from member functions
  • Review of iterators and iterator operations
  • STL Lists, erase and insert on lists
  • Differences between indices and iterators, differences between lists and vectors
  • Introductory example on linked lists.
  • Basic linked list operations:
    • Stepping through a list
    • Push back
    • ... & we’ll continue on Tuesday

9.1 References and Return Values

  • A reference is an alias for another variable. For example:

string a = "Tommy"; string b = a; // a new string is created using the string copy constructor string& c = a; // c is an alias/reference to the string object a

b[1] = ’i’; cout << a << " " << b << " " << c << endl; // outputs: Tommy Timmy Tommy

c[1] = ’a’; cout << a << " " << b << " " << c << endl; // outputs: Tammy Timmy Tammy

The reference variable c refers to the same string as variable a. Therefore, when we change c, we change a.

  • Exactly the same thing occurs with reference parameters to functions and the return values of functions. Let’s look at the Student class from Lecture 4 again:

class Student { public: const string& first_name() const { return first_name_; } const string& last_name() const { return last_name_; } // etc....

private: string first_name_; string last_name_; // etc... };

  • In the main function we had a vector of students:

vector students;

Based on our discussion of references above and looking at the class declaration, what if we wrote the following. Would the code then be changing the internal contents of the i-th Student object?

string & fname = students[i].first_name(); fname[1] = ’i’

  • The answer is NO! The Student class member function first_name returns a const reference. The compiler will complain that the above code is attempting to assign a const reference to a non-const reference variable.
  • If we instead wrote the following, then compiler would complain that you are trying to change a const object.

const string & fname = students[i].first_name(); fname[1] = ’i’

  • Hence in both cases the Student class would be “safe” from attempts at external modification.
  • However, the author of the Student class would get into trouble if the member function return type was only a reference, and not a const reference. Then external users could access and change the internal contents of an object! This is a bad idea in most cases.

9.2 The list Standard Library Container Class

  • Lists are formed as a sequentially linked structure instead of the array-like, random-access / indexing structure of vectors.

array/vector:

7 5 8 1 9 7 5 8 1 9 0 1 2 3 4

list:

  • Lists have push front and pop front functions in addition to the push back and pop back functions of vectors.
  • Erase is very efficient for a list, independent of the size of the list (we’ll see why when we learn the implemen- tation details later in the semester).
  • We can’t use the standard sort function; we must use a special sort function defined by the list type.
  • Lists have no subscripting operation (a.k.a. they do not allow “random-access”).

9.3 Iterators and Iterator Operations — General

  • An iterator type is defined by each container class. For example,

vector::iterator v_itr; list::iterator l_itr; string::iterator s_itr;

  • An iterator is assigned to a specific location in a container. For example: Note: We can add an integer to vector and string iterators, but not to list iterators.

v_itr = vec.begin() + i; // i-th location in a vector l_itr = lst.begin(); // first entry in a list s_itr = str.begin(); // first char of a string

  • The contents of the specific entry referred to by an iterator are accessed using the * dereference operator: In the first and third lines, *v itr and *l itr are l-values. In the second, *s_itr is an r-value.

*v_itr = 3.14; cout << *s_itr << endl; *l_itr = "Hello";

9.7 Erase

  • Lists and vectors each have a special member function called erase. In particular, given list of ints s, consider the example:

list::iterator p = s.begin(); ++p; list::iterator q = s.erase(p);

  • After the code above is executed:
    • The integer stored in the second entry of the list has been removed.
    • The size of the list has shrunk by one.
    • The iterator p does not refer to a valid entry.
    • The iterator q refers to the item that was the third entry and is now the second.

?

7 5 8 1 9

7 8 1 9

p q

p

  • To reuse the iterator p and make it a valid entry, you will often see the code written:

list::iterator p = s.begin(); ++p; p = s.erase(p);

  • Now we can rewrite the erase from vector function from the Lecture 8 enrollment example:

p = v.erase(p);

  • Even though this has the same syntax for vectors and for list, the vector version is O(n), whereas the list version is O(1).

9.8 Insert

  • Similarly, there is an insert function for lists that takes an iterator and a value and adds a link in the chain with the new value immediately before the item pointed to by the iterator.
  • The call returns an iterator that points to the newly added element. Variants on the basic insert function are also defined.

9.9 Exercise: Erase & Insert

Write a function that takes a list of integers, lst, and an integer, x. The function should 1) remove all negative numbers from the list, 2) verify that the remaining elements in the list are sorted in increasing order, and 3) insert x into the list such that the order is maintained.

9.10 Motivation

  • Thus far our discussion of how list is implemented has been only intuitive: it is a “chain” of objects.
  • Now we will look at the mechanism — linked lists.
  • Learning this mechanism is good background for higher-level courses where the design of novel data structures is important.

9.11 Objects with Pointers / Linking Objects

  • The two fundamental mechanisms of linked lists are:
    • creating objects with pointers as one of the member variables, and
    • making these pointers point to other objects of the same type.
  • These mechanisms are illustrated in the following program:

#include using namespace std;

template class Node { public: T value; Node* ptr; };

void main() { Node* ll; // ll is a pointer to a (non-existent) Node ll = new Node; // Create a Node and assign its memory address to ll ll->value = 6; // This is the same as (*ll).value = 6; ll->ptr = NULL; // NULL == 0, which indicates a "null" pointer

Node* q = new Node; q->value = 8; q->ptr = NULL;

// set ll’s ptr member variable to // point to the same thing as variable q ll->ptr = q;

cout << "1st value: " << ll->value << "\n" << "2nd value: " << ll->ptr->value << endl; }

6

ll

value ptr

value ptr

q

NULL

8

9.12 Definition: A Linked List

  • The definition is recursive: A linked list is either:
    • Empty, or
    • Contains a node storing a value and a pointer to a linked list.
  • The first node in the linked list is called the head node and the pointer to this node is called the head pointer. The pointer’s value will be stored in a variable called head.