280 likes | 290 Views
This lesson covers various aspects of data structures including lists, operator overloading, indexing, vectors, pointer arithmetic, and constructors.
E N D
CS 240: Data Structures Monday, June 23rd Lists
Feedback: Value Semantics • Return semantics: • Similiarly to our Passing semantics (pass by value, pass by reference), we can return by value or return by reference. • int someFunc(); • int & someFunc(); • int * someFunc(); • int & and int * are related (you can convert one into another) but have different syntax.
Feedback: Operator Overloading • We’ll cover some more of this later in the slides, however: • Overloading operators allows us to use operators (see the Table from the first reading), such as +, -, *, <<, >>, *, with our ADTs. • Overloading an operator should provide functionality that is appropriate for the operator. << should output data, >> should input data, + should do some sort of adding. • Various operators have different return types. • Commonly overloaded operators are: =, <<, >>, < and ==.
Feedback: Indexing operator • The indexing operator is used to access data from an array. int data[10]; cin >> data[5]; cout << data[5]; data[1] = 10; data[3] = data[5]; • So, if we create an ADT that acts as an array (mycontainer) how would we access its data? • We could build functions (such as getitemat) to do this. • But, we can’t use [ ] unless we overloading it for mycontainer.
Feedback: Using Vector • We’ll cover this at the end of this lecture and tomorrow.
Feedback: Pointer Arithmetic • In general, we have data variables and pointer variables. • & provides the address of a variable • * takes the variable’s value and uses that as an address to find a piece of data. • Therefore, *&X is equivalent to X. • Consider, • T data = &otherData; • Then, apply * to both sides • *data = *&otherData; • Or: *data = otherData;
Feedback: Constructors • We have almost solely covered the default constructor so far. However, from the readings it should be apparent that there are other constructors. • We can use these other constructors as a way to initialize our object with particular values (see Card). • However, one constructor we haven’t discussed is rather important: The copy constructor
Copy Constructor • The copy constructor allows us to create an object as a copy of another object: • mycontainer x; • mycontainer y(x); • This is commonly expected from ADTs. For mycontainer.h: mycontainer(const mycontainer & source); • We must then provide the functionality which copies the data from the source to ourselves. Let’s do that now.
Feedback • A couple of people mentioned concerns about using streams. I’m just not sure what concerns to address, so let me know and we can discuss them now.
Freebie • //Resizes the mycontainer to have N items. If this is larger than the current number of items, fills the spaces with newVal (default newVal is int constructor) • .h void resize(int N, int newVal = int()); • .cpp void mycontainer::resize(int N, int newVal) { if(location>=N) { location = N; } while(location<N) { insert(newVal); } }
To lists! • The first type of list we talked about was an array-based linked list: • What is the major difference between this an a non-array based linked list? • How nodes are created! • So, if we replace “new Node” with a function that returns the node pointer. We can: • Use the same logic for either list type • Provide different “newNode” functions for the two different list types
Lists • We need a constructor to determine if our list is array based or linked based. • Assignment (operator =) and copy constructor are part of the requirements for a full-fledged object • Empty is just a function to have • NewNode provides a usable node pointer for insert. DeleteNode takes it back. • We will add “node * free” to the linked list (this is an optimization that makes an array-based linked list much easier to manage). • Lets implement the previous slide on top of our list code: • What do we need? Or are going to add? • Constructor • Assignment Operator/Copy Constructor • empty • newNode/deleteNode
Extra Stuff • Adding “operator <<“ to Node. • Adding “operator +” and “operator –”. How should these behave to conform to the expected behavior of + and -?
Linked List • Linked list is similar to the array-based list. But, there are differences: • We don’t need a “free” list. • Data is not contiguous (however, the user shouldn’t be able to notice anyway) • On each insert, we need to create a new node and refer to it. • On each remove, we need to delete a node.
“operator” overloading • Most operators in C++ can be overloaded to change their meaning. • For the most part, we have overloaded << and >>. In general, we need to overload =. • << and >> are never part of the class prototype (we won’t discuss how this can be done). • operator = is part of the class prototype and returns *this (a reference to the object itself)
Operators • For “class sample” • sample & operator = (const sample & rhs); • const isn’t needed, it provides “advice” • We return a reference to “this”, this allows compounded assignment • ostream & operator << (ostream & out, const sample & rhs); • Against, const isn’t needed. We need to return “out” after we used it. • istream & operator >> (istream & in, sample & rhs); • << and >> are special cases. Most of the other operators follow cleaner rules • These can be a pain to remember all of the nuances involved – particularly for other operators.
Operators • sample operator + (const sample & rhs) const; • Neither const isn’t needed, it provides “advice” • Why doesn’t this return “sample &”? • Well, operator + doesn’t change anything. • X+Y; //Adds X+Y, but doesn’t do anything with the result • Therefore, we don’t modify X or Y. But, we need to return the result (we return it by value instead of by reference)
Operators • General rule: • If the left-hand side is modified, return a reference • If a new value is produced, and this isn’t stored in the left-hand side, return by value. • bool operator == (const sample & rhs);
Queues • What is a Queue? • Queue is a subset of List • Differences: • Insertion and removal occur at different ends of the Queue. • Generally, we dequeue (remove) from the head (front) of the queue. • We enqueue (insert) at the tail (back/end) of the queue. • In most cases, we can peek at the head of the queue without removing the item.
Queues • What do we change in our list (or even linked list) to turn it into a Queue?
Stacks • What is a Stack? • Similarly to a Queue, it is a subset of list. • Differences: • Insertion and removal occur at the same end of the Stack. • We pop (remove) from the top (back/end) of the stack. • We push (insert) at the top (back/end) of the stack. • In most cases, we can peek at the head of the stack without removing the item.
Stacks • What do we change in our list (or even linked list) to turn it into a Stack?
Implementation • Queues and Stacks can both be implemented in a linked list fashion. • However, Stacks are much less efficient as a linked list – compared to a dynamic array (not array-based list). • Queues are more difficult to manipulate as a dynamic array (again, not array-based list) – a linked list lends well to Queue manipulation.
Vector • Vector is an STL provided sequential container. • It provides us with similar abilities as does our templated mycontainer (lab 4) – this Thursday.
Vector • We declare a vector just like we do a templated mycontainer: • vector<T> testvector; • Many methods are built in: • Constructor, destructor, operator = • size(), capacity(), • clear() //equivalent to mycontainer::empty() • push_back(T) //equivalent to mycontainer::insert(T) • pop_back(T) //removes the last element
Vector • We can access Vector data as follows: • front() //gets first element • back() //gets last element • operator [unsigned int] //gets element at specified location.
Vector • Instead of currentvalue, Vector uses iterators: • vector<T>::iterator myiterator; //T must match the vector you want to use this iterator with. • myiterator = testvector.begin(); • myiterator = testvector.end(); • myiterator++; //equivalent to mycontainer::next() • myiterator--; //equivalent to mycontainer::previous() • *myiterator; //equivalent to mycontainer::current() • testvector.erase(myiterator); //equivalent to mycontainer::removeHere(); • testvector.insert(myiterator, T); //equivalent to mycontainer::insertHere(T);
To do: • Next class we will talk about dynamic array implementations of Queue and Stack • Tomorrow: Linked List Presentations. Yay!