1 / 46

Linked Lists

Linked Lists. CSCI 3333 Data Structures. by Dr. Bun Yue Professor of Computer Science yue@uhcl.edu http://sce.uhcl.edu/yue/ 2013. Acknowledgement. Mr. Charles Moen Dr. Wei Ding Ms. Krishani Abeysekera Dr. Michael Goodrich. Static Data Structures.

darnells
Download Presentation

Linked Lists

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Linked Lists CSCI 3333 Data Structures byDr. Bun YueProfessor of Computer Scienceyue@uhcl.eduhttp://sce.uhcl.edu/yue/2013

  2. Acknowledgement • Mr. Charles Moen • Dr. Wei Ding • Ms. Krishani Abeysekera • Dr. Michael Goodrich

  3. Static Data Structures • The size of static data structures do not change. • Example: array. During runtime, if there are more elements to be stored in an array: • A new array needs to be created. • The old array may be deleted. • Elements are copied. • Expensive!

  4. Dynamic Data Structures • The size of a dynamic data structure can change during runtime. • Many applications need to use dynamic data structures.

  5. Linked List ADT • A linked list is a sequence of nodes linked in a chain. • Some operations: • Create • Delete • Traverse • Insert a node • Delete a node • Insert a linked list • Delete a linked list • …

  6. Linked Lists vs. Arrays • Advantages: • Dynamic: size changes on demand. • Insertion and deletion of nodes: can be faster in some situations. • Disadvantages: • May not be randomly accessible efficiently. • Options: • Programmers needs to manage memory. • Automatic garbage collection may bring performance issues.

  7. Linked List ADT • There are many kinds of linked lists implemented by different languages. • They are different ADTs. • We can study the ADTs to use them without knowing how they are implemented.

  8. Example: C++ STL list • Some methods: • begin: returns an iterator addressing the first element in a list. • pop_back:deletes the element at the end of a list. • pop_front: deletes the element at the beginning of a list. • push_back: adds an element to the end of a list. • push_front: adds an element to the beginning of a list. • …

  9. Example Program #include <list> #include <iostream> using namespace std ; typedef list<int> INT_LIST; int main() { INT_LIST ilist; ilist.push_back(1); ilist.push_front(2); ilist.push_front(3); ilist.push_front(4); ilist.push_back(5); cout << ilist.front() << endl; cout << ilist.back() << endl;

  10. Example Program (cont) INT_LIST::iterator i; cout << "Int list content:"; for (i = ilist.begin(); i != ilist.end(); ++i) cout << " " << *i; // Note * cout << endl; for (i = ilist.begin(); i != ilist.end(); ++i) (*i)++; cout << "Int list content:"; for (i = ilist.begin(); i != ilist.end(); ++i) cout << " " << *i; // Note * cout << endl; ilist.pop_front(); ilist.pop_back(); cout << "Int list content:"; for (i = ilist.begin(); i != ilist.end(); ++i) cout << " " << *i; // Note * cout << endl; }

  11. Output 1 ilist.push_back(1); ilist.push_front(2); ilist.push_front(3); ilist.push_front(4); ilist.push_back(5); cout << ilist.front() << endl; cout << ilist.back() << endl; Output: 4 5

  12. Output 2 INT_LIST::iterator i; cout << "Int list content:"; for (i = ilist.begin(); i != ilist.end(); ++i) cout << " " << *i; // Note * cout << endl; for (i = ilist.begin(); i != ilist.end(); ++i) (*i)++; cout << "Int list content:"; for (i = ilist.begin(); i != ilist.end(); ++i) cout << " " << *i; // Note * cout << endl; Output: Int list content: 4 3 2 1 5 Int list content: 5 4 3 2 6

  13. Output 3 ilist.pop_front(); ilist.pop_back(); cout << "Int list content:"; for (i = ilist.begin(); i != ilist.end(); ++i) cout << " " << *i; cout << endl; Output: Int list content: 4 3 2

  14. Perl Example • In Perl, an array is also a list. • It is built into the language. (You can see the importance of lists here.) • Array/List variables start with the symbol @, e.g. @a. • List elements are scalar (which starts with the symbol $), e.g. $a[1], $a[12], etc.

  15. Perl’s List Examples @num[1,2] = (3,4); # $num[1] = 3; $num[2] = 4; @num[1,2] = @num[2,1]; # swap $num[1] and $num[2]; @num[1,2] = @num[3,3]; # $num[1] = $num[3]; $num[2] = $num[3]; ($num[1], $num[2]) = ($num[2], $num[1]); # swap $num[1] and $num[2]; @num = (1,2,3,4,5)[3,2,1]; # @num = (4,3,2); ($first, @num) = @num; # remove the first element of @num into $first (@num, $last) = @num; # pop the last element to $last

  16. Java’s List Interface ADT • Java has a List interface for ordered collection (sequence). • Super-interface: • Collection • Iterable • Some known implementation classes: • AbstractList • LinkedList • ArrayList • Vector • … • Practical APIs are much richer than those found in some textbooks!

  17. Interable Interface • Target of a for each statement. • One method only Iterator<T>iterator(): returns an iterator over a set of elements of type T. • Iterator<T> interface’s methods: • hasNext() • next() • remove()

  18. Collection Interface • Group of objects, possibly with duplicates. • Super-interface: iterable. • Some methods: • add(E e) • addAll(Collection<? extends E> c) • contains(Object o) • remove(Object o) • removeAll(Collection<?> c) • size() • toArray() • …

  19. List Interface • New required methods added: • Random access: • E get(int index) • E remove(int index) • Searching: • int indexOf(Object o) • int lastIndexOf(Object o) • List Iterator: • ListIterator<E> listIterator()

  20. Concrete Class LinkedList<E> • Interface implemented: • Serializable • Cloneable • Iterable<E> Collection<E>  Queue<E>  Deque<E> • Iterable<E>  Collection<E>  List<E> • <E>: Actual E should be a class (not int, float, etc)

  21. LinkedList Methods • From implementing Dequeue: • void addFirst(E e) • void addLast(E e) • E removeFirst() • E removeLast() • E offerFirst(): retrieve, not remove, exception version for empty Dequeue. • E peekFirst(): retrieve, not remove, return null version for empty Dequeue. • …

  22. LinkedList Methods • From implementing List: • add(E e) • E get(int index) • E remove(int index) • remove(Object o) • int indexOf(Object o)

  23. Finding the Right Structures • APIs are usually feature rich. • Study purposes of classes and interfaces. • Study hierarchical class and interface structures. • Study methods available.

  24. Examples • Good to critically read program code. • http://www.java-samples.com/showtutorial.php?tutorialid=347 • http://www.idevelopment.info/data/Programming/java/collections/LinkedListExample.java

  25. Implementation Issues • You do not need to know how classes are implemented to use them! • However, knowing the implementations: • May deepen understanding of the classes for better usages. • May help selecting the best class for the application. • May transfer this knowledge when you need to implement custom-designed classes yourself.

  26. Example Implementation in C++ • Singly linked list of float • Each node has only one pointer to its successor. • The list stores a head pointer to the head of the list. • If the list is empty, the head pointer is null. • For simplicity, each node stores an float.

  27. Implementation issues • Data members: • Value of float • head pointer • tail pointer: for efficiency • size of the list: for efficiency. • Tips: ensure all data members properly updated in operations.

  28. Node • class FloatList{ private: // Declare a structure for the list. // Simliar to nested classes in Java struct ListNode { float value; struct ListNode *next; }; ListNode *head, *tail; // head and tail pointers int _size;

  29. Method Prototypes public: FloatList() // Constructor { head = tail = NULL; _size = 0; } ~FloatList(); // Destructor • Tips: always include constructors and destructors.

  30. Method Prototypes void appendTailNode(float); // insert node at the tail. bool deleteHeadNode(); // delete node at the head. bool deleteNode(float); // delete the first occurrence of the float // list. void displayList(); int size() { return _size; } bool isEmpty() { return _size == 0; } };

  31. Method Implementations void FloatList::appendTailNode(float num) { ListNode *newNode; // Allocate a new node & store num newNode = new ListNode; newNode->value = num; newNode->next = NULL; if (head==NULL) { // empty list head = tail = newNode; } else { tail->next = newNode; tail = tail-> next; } _size++; }

  32. Discussion • Maintenance of data members. • Trade off of using _size and tail: faster for some operations and slower for others. • Definition of newNode as class instead of struct: use of constructors.

  33. deleteHeadNode bool FloatList::deleteHeadNode() { if (head == NULL) return false; else { ListNode *temp = head; head = head-> next; if (head == NULL) tail = NULL; delete temp; _size--; return true; } }

  34. Discussion • Other possible methods: • deleteTailNode • May change prototype:

  35. deleteNode(float f) bool FloatList::deleteNode(float f) { if (head == NULL) return false; else { ListNode *curr = head; ListNode *prev = NULL; while (curr != NULL && curr->value != f) { prev = curr; curr = curr-> next; } if (curr == NULL) // do not find the number to be deleted. return false; else // to be continued. } }

  36. else part { if (prev == NULL) { // the head node contains the number. head = curr-> next; } if (curr == tail) { // the tail node will be deleted. tail = prev; } //link the prev node to skip the curr node. prev->next = curr->next; delete curr; _size--; return true; }

  37. Discussion • Other possible methods. • deleteLastNode.

  38. displayList void FloatList::displayList() { ListNode *nodePtr; nodePtr = head; while (nodePtr) { cout << nodePtr->value << " "; nodePtr = nodePtr->next; } cout << endl; }

  39. Discussion • Not flexible. • Need an ‘iterator’.

  40. Destructor FloatList::~FloatList(){ ListNode *curr, *next; curr = head; while (curr != NULL) { next = curr->next; delete curr; curr = next; } }

  41. Test Program FloatList list; list.appendTailNode(2.2); list.appendTailNode(3.4); list.appendTailNode(2.2); list.appendTailNode(1.8); list.appendTailNode(2.2); list.displayList(); cout << "size: " << list.size() << endl; • Output: 2.2 3.4 2.2 1.8 2.2 size: 5

  42. Test Program list.deleteHeadNode(); list.displayList(); cout << "size: " << list.size() << endl; list.deleteNode(2.2); list.displayList(); cout << "size: " << list.size() << endl; list.deleteNode(2.2); list.displayList(); cout << "size: " << list.size() << endl; • Outpit: 3.4 2.2 1.8 2.2 size: 4 3.4 1.8 2.2 size: 3 3.4 1.8 size: 2

  43. Test Program list.deleteHeadNode(); list.deleteHeadNode(); list.displayList(); cout << "size: " << list.size() << endl; • Output: size: 0

  44. Discussion • Other possible methods: • getHeadNodeValue() • getTailNodeValue() • deleteTailNode() • …

  45. Discussion • Some operations, deleteTailNode may take longer time, O(N), where N is the number of nodes in the list. • May use a doubly linked list. • Need to have a way to analyze performance. • List only works for float • May use template.

  46. Questions and Comments?

More Related