Linked Lists Phil Tayco Slide version 1.0 Created Feb 8, 2015.

Slides:



Advertisements
Similar presentations
CHP-5 LinkedList.
Advertisements

C Structures and Memory Allocation There is no class in C, but we may still want non- homogenous structures –So, we use the struct construct struct for.
Introduction to Linked Lists In your previous programming course, you saw how data is organized and processed sequentially using an array. You probably.
Composition CMSC 202. Code Reuse Effective software development relies on reusing existing code. Code reuse must be more than just copying code and changing.
Chapter 4: Trees Part II - AVL Tree
Linked Lists Compiled by Dr. Mohammad Alhawarat CHAPTER 04.
Linked Lists
Lecture 8 CS203. Implementation of Data Structures 2 In the last couple of weeks, we have covered various data structures that are implemented in the.
1 Chapter 24 Lists Stacks and Queues. 2 Objectives F To design list with interface and abstract class (§24.2). F To design and implement a dynamic list.
Data Structures Hash Tables
Data Structures Advanced Sorts Part 2: Quicksort Phil Tayco Slide version 1.0 Mar. 22, 2015.
C++ Programming: Program Design Including Data Structures, Third Edition Chapter 17: Linked Lists.
1 Data Structures Data Structures Topic #2. 2 Today’s Agenda Data Abstraction –Given what we talked about last time, we need to step through an example.
Data Structures Topic #3. Today’s Agenda Ordered List ADTs –What are they –Discuss two different interpretations of an “ordered list” –Are manipulated.
Chapter 3: Arrays, Linked Lists, and Recursion
Data Structures Introduction Phil Tayco Slide version 1.0 Jan 26, 2015.
Chapter 13: Pointers, Classes, Virtual Functions, and Abstract Classes
C++ Programming: Program Design Including Data Structures, Fourth Edition Chapter 13: Pointers, Classes, Virtual Functions, and Abstract Classes.
Lecture 22 Miscellaneous Topics 4 + Memory Allocation.
Pointer Data Type and Pointer Variables
C++ Programming: From Problem Analysis to Program Design, Fourth Edition Chapter 14: Pointers, Classes, Virtual Functions, and Abstract Classes.
Comp 249 Programming Methodology Chapter 15 Linked Data Structure - Part B Dr. Aiman Hanna Department of Computer Science & Software Engineering Concordia.
Data Structures Week 5 Further Data Structures The story so far  We understand the notion of an abstract data type.  Saw some fundamental operations.
Data Structures Arrays Phil Tayco Slide version 1.0 Feb 02, 2015.
Data Structures Binary Trees Phil Tayco Slide version 1.0 Mar. 22, 2015.
IT253: Computer Organization Lecture 3: Memory and Bit Operations Tonga Institute of Higher Education.
Chapter 13 Recursion. Learning Objectives Recursive void Functions – Tracing recursive calls – Infinite recursion, overflows Recursive Functions that.
Data Structures Simple Sorts Phil Tayco Slide version 1.0 Feb. 8, 2015.
CSC 211 Data Structures Lecture 13
C++ Data Types Structured array struct union class Address pointer reference Simple IntegralFloating char short int long enum float double long double.
Lists II. List ADT When using an array-based implementation of the List ADT we encounter two problems; 1. Overflow 2. Wasted Space These limitations are.
Chapter 12: Pointers, Classes, Virtual Functions, and Abstract Classes.
A first look an ADTs Solving a problem involves processing data, and an important part of the solution is the careful organization of the data In order.
Data Structures Trees Phil Tayco Slide version 1.0 Apr. 23, 2015.
Recap form last time How to do for loops map, filter, reduce Next up: dictionaries.
Data Structures Stacks and Queues Phil Tayco Slide version 1.0 Feb. 16, 2015.
(c) University of Washington16-1 CSC 143 Java Linked Lists Reading: Ch. 20.
Linked List by Chapter 5 Linked List by
Programming Fundamentals. Topics to be covered Today Recursion Inline Functions Scope and Storage Class A simple class Constructor Destructor.
Chapter 5 Linked List by Before you learn Linked List 3 rd level of Data Structures Intermediate Level of Understanding for C++ Please.
1 Chapter 6 Methods for Making Data Structures. 2 Dynamic Arrays in Data Structures In almost every data structure, we want functions for inserting and.
1 CSC 211 Data Structures Lecture 11 Dr. Iftikhar Azim Niaz 1.
Data Structures Arrays and Lists Part 2 More List Operations.
MORE POINTERS Plus: Memory Allocation Heap versus Stack.
1 Linked List. Outline Introduction Insertion Description Deletion Description Basic Node Implementation Conclusion.
1 Chapter 4 Unordered List. 2 Learning Objectives ● Describe the properties of an unordered list. ● Study sequential search and analyze its worst- case.
CHAPTER 51 LINKED LISTS. Introduction link list is a linear array collection of data elements called nodes, where the linear order is given by means of.
Chapter 12: Pointers, Classes, Virtual Functions, Abstract Classes, and Lists.
Winter 2016CISC101 - Prof. McLeod1 CISC101 Reminders Assignment 5 is posted. Exercise 8 is very similar to what you will be doing with assignment 5. Exam.
Data Structures and Algorithm Analysis Dr. Ken Cosh Linked Lists.
LINKED LISTS.
You learned how to declare pointer variables how to store the address of a variable into a pointer variable of the same type as the variable how to manipulate.
Phil Tayco Slide version 1.0 Created Sep 10, 2017
Phil Tayco Slide version 1.0 Created Sep 18, 2017
Chapter 13: Pointers, Classes, Virtual Functions, and Abstract Classes
Linked lists.
Phil Tayco Slide version 1.0 Created Oct 2, 2017
Phil Tayco Slide version 1.0 Created Oct 16, 2017
Java Programming Arrays
Linked Lists.
Data Structures Sorted Arrays
Introduction to Data Structure
Object Comparisons and Arrays
Phil Tayco Slide version 1.3 Updated Feb 12, 2018
Data Structures Introduction
Data Structures Unsorted Arrays
Data Structures & Algorithms
Linked lists.
SPL – PS2 C++ Memory Handling.
Phil Tayco San Jose City College Slide version 1.2 Updated Sep 9, 2019
Presentation transcript:

Linked Lists Phil Tayco Slide version 1.0 Created Feb 8, 2015

Linked Lists Array pros and cons Arrays have many benefits: –Direct access to any element at any time –“Easier” to code –Can be used to apply binary search Like all structures, they have cons: –Memory is static. It must be reserved in advance and can lead to unused space –Does not conveniently allow for additional memory use. If the capacity is underestimated, getting more memory is an expensive procedure –Element shifts are O(n) As with any attempt at progress, we look at the cons. Can we have a data structure that is not static, conveniently handles additional memory needs and improves O(n) “shifting”?

Linked Lists Classes and structures Before diving into Linked Lists, we need to make sure we understand some other concepts A class or structure is an abstract data type defined by the programmer –int x; is a primitive data type given to you by the compiler. It already knows what an integer is and expects x to store whole numbers –Student x; would be an abstract data type. The compiler does not know what a Student is and would need to be defined –Once a Student is defined, you can create any number of variables like x of that type to store different values. We call these variables “objects” We will use the term “class” for these abstract data types

Linked Lists Class properties All classes are defined by their “attributes” or “properties” They model the concept the data type is named for and answers the question, “what does this class have?” A Student, for example, has a first name, last name, id, age, gender and a GPA. There are many other properties, so we limit it to what we want to capture

Linked Lists Class definition and usage example public class Student { public String firstName; public String lastName; public int age; public double gpa; public char gender; public String id; } Student myStudent = new Student(); myStudent.firstName = “Phil”; myStudent.lastName = “Tayco”; myStudent.age = 25; myStudent.gpa = 3.9; myStudent.gender = ‘M’; myStudent.id = “ABC123”;

Linked Lists Code observations Student objects are “instantiated” with the “new Student()” line. From there, the object properties are treated like normal variables myStudent is one instance of type Student with its own set of values for each of its properties. Similar code can be used with different objects Abstract data types are treated like normal data types –You can create an array of Students –You can use a class as a property of another class (known as “composition”) The class definition is a template or a definition. Actual memory is not allocated until an object is instantiated Classes can also contain functions (called methods) which you will see used later. Designing and programming extensively with classes is beyond the scope of this course

Linked Lists Pointers By definition, a pointer is a variable that contains a memory address The address is the location where the value(s) of a variable is stored When pointers are defined and memory is allocated, that space used by “dereferencing” the pointer (the pointer is also referred to as a “reference”) Modern programming languages have “no pointers”, but in fact they are handling a lot of the pointer process automatically for you C and C++ gives you more memory management control, which can be both a blessing and a curse!

Linked Lists Pointer example (in C++): int* x;// Pointer declaration x = new int;// Memory allocation // Store 25 in the memory location created for x *x = 25; // Display the memory location reserved for x printf(“%d\n”, x); // Dereference x by going to the memory location and then using the value printf(“%d\n”, *x); // Another pointer declaration, this time with a class Student* myStudent = new Student(); // Dereference myStudent and access any property there (*myStudent).firstName = “Phil”; // More convenient notation: myStudent->lastName = “Tayco”; // Deallocate the memory when you are done delete x; delete myStudent;

Linked Lists Pointers and classes Memory management can be tricky if you forget to allocate and deallocate memory (“leaks” can occur if the pointer variable is removed without first deleting the memory allocated for it) Memory addresses are just values in themselves and can accidentally be manipulated –“x = 25;” instead of “*x = 25;” is a common mistake –“x = 25;” makes the address 25 (some unexpected area of memory) –“*x = 25;” puts 25 in the memory location x is pointing to The notation gets more complex with classes as pointers. You can’t say “*myStudent.age = 25;” –The “.” operation takes precedence over the “*” –“(*myStudent).age = 25;” means dereference first and then access the age property, which is the correct logic –The “->” operator is the equivalent operation Direct access to memory management can be useful in low level systems. For higher level applications, memory management may not be as necessary and so languages like Java conveniently handle them

Linked Lists Dynamic memory allocation So what do we know to this point: –Abstract data types allow us to define our own types of structures –Class properties can use simple and complex data types within them –Pointers dynamically handle memory (we use it when we need it) Remember the cons with arrays with memory allocation? We can use pointers to abstract data types to develop a different structure that address them But, we don’t do so by creating an array of class pointers. That can be an improvement, but fundamentally, we are still reserving memory and can still lead to unused memory We need to define a class that allows us to dynamically manage memory with an array-like behavior

Linked Lists The Node class: public class Node { public int data; public Node next; } Node oneElement = new Node(); oneElement.data = 25; oneElement.next = null; Node anotherElement = new Node(); anotherElement.data = 30; anotherElement.next = oneElement;

Linked Lists Node observations The Node class contains 2 essential properties –A “data” property which can really be any data type. We use int as an example, but it could be a String or another class –A “next” property whose data type is Node. This does not mean “next” is itself, but that “next” is a pointer to another object of type “Node” oneElement is a Node object with a data value of 25. The next Node object it is pointing to does not exist (its value is set to null) anotherElement is also a Node object with a data value of 30. Its next Node is pointing to oneElement The chain of Node objects is called a “Linked List” –We can create any number of Node objects at any time –We can add Node objects to the Linked List at any time making this data structure handle dynamic memory usage Question: which object is considered to be at the “head” of the list?

Linked Lists Learning Linked Lists It is critical for your learning to draw pictures when understanding Linked List algorithms Now that we have a list data structure like an array, we can compare them and see what the pros and cons are We will use consistent notation (Big O) and look at the same 4 common functions (Search, Insert, Update and Delete) Initial impression: what do you think the pros and cons will be and how do you think they will compare to arrays?

Linked Lists The Linked List class: public class Node { public int data; public Node next; } public class LinkedList { public Node head = null; public void insert(int value); public boolean update(int oldValue, int newValue); public boolean delete(int value); public Node search(int value); public void printList(); }

Linked Lists Unordered Arrays or Unordered Linked Lists Recall the performance of the 4 functions with unsorted arrays. All are O(n) with insert performing at O(1) Based on your initial impression of how Linked Lists, do you think we will see a performance improvement? Let’s add to the Linked List class code treating the list as unordered Since insert is O(1), let’s first see if the insert algorithm makes for worse performance

Linked Lists Insert The algorithm for unordered linked list insert is as follows: –Create a new Node –Make the new Node’s “next” property point to the “head” of the Linked List –Make the “head” of the Linked List the new Node

Linked Lists Unordered insert: public void insert(int value) { Node newNode = new Node(); newNode.data = value; newNode.next = head; head = newNode; }

Linked Lists Insert analysis That’s it! Now since we used the compare operation in the insert analysis of the unsorted arrays, we have to do the same thing here As it turns out, there isn’t even one compare operation performed –With the array, we needed to check if there is available space –Since memory is used only when needed, that check is not necessary (assuming there is enough memory as a whole) –If we used different operations to compare (function calls or assignment operations), the performance comparison can be nitpicky –In all cases, though, the performance is the same regardless of how big the linked list gets We stay at O(1) and we also use memory only when needed. The dynamic memory usage is a big win over arrays with Linked Lists so we can assume if performance is equal, the main benefit is the dynamic memory usage Also note how this algorithm effectively performs a “shift” of elements when a new Node is inserted. This effect is seen more when we deal with sorted Linked Lists…

Linked Lists Search Unordered arrays search at O(n), and you can probably guess with Linked Lists, it’s going to be the same because of the nature of the data The algorithm for unordered linked list search: –Create a temporary Node that points to the head of the list –While the temp Node is not null If the data at that node is the value you are searching for, return the temp Node – the value was found! Else, go to the next Node by assigning temp to the node’s “next” property – this process is called “traversing” the list –If we reach this point, the value was not found in the list and we return null

Linked Lists Unordered search: public Node search(int value) { Node temp = head; while (temp != null) { if (temp.data == value) return temp; temp = temp.next; } return null; }

Linked Lists Search analysis We have a loop using a comparison operation and in the worst case (if the search value does not exist), the performance is O(n) The performance is actually O(2n) if you want to be precise, is that the same with the unordered array? Note the need to use a temp Node object –Question: Why couldn’t we traverse the list using the head variable? –Answer: If we did that, we would lose visibility to the head of the list. Once you go to the next Node, there’s no going back –Perhaps we can modify the Node definition to include a second Node pointer that represents the “previous” Node. We will look at that too, later on… So search is the same too. Now update and delete both use a search so we’re also at least looking at an O(n) performance here as well Starting with update, the same search algorithm applies with a change in value occurring if the Node is found instead of returning the Node itself

Linked Lists Unordered update: public boolean update(int oldValue, int newValue) { Node temp = search(oldValue); if (temp == null) return false; temp.data = newValue; return true; }

Linked Lists Update analysis and then, delete We have another O(n) algorithm. This makes 3 out of the 4 algorithms the same performance between unordered arrays and linked lists. It’s starting to look like Linked Lists are better suited for unordered data structures because of the dynamic memory usage (if memory management is of primary concern) Let’s look at delete. A pattern you will see with all data structures we look at is that the delete function tends to be the most complex For reviewing this algorithm, let’s attack this one by looking at the code first

Linked Lists Unordered delete: public boolean delete(int value) { Node current = head; // Situation #1 if (current == null) return false; // Situation #2 if (current.data == value) { head = current.next; current = null; return true; }

Linked Lists Delete analysis, part 1 With delete functions for the data structures, you usually see them handled by dealing with 3 key situations: 1.An empty list 2.A list where the element to delete is the first 3.A list where the element to delete is elsewhere in the list, or not at all In the first situation, this is an easy one to handle. The list is empty, so we’re done! However, it is very important to address this: –An empty list means the head is null –Whenever you access an object’s property like “current.data”, the code will first dereference current –If current is null, it can’t go anywhere making the “.data” part of the code unusable and results in an “accessing null pointer exception” –The code syntax, however, is correct making it a run time error –This is easy to miss during debugging because it is natural to test the code with lists that contain data Never forget the empty list situation!!

Linked Lists Delete analysis, part 1 The other situations can now safely assume at least one element exists in the list (making code like “current.data” safe to execute) Situation 2 is where the element to delete is the at the head A proper delete here means we have to reassign the head pointer to a new Node With this data structure, that new head Node is the current head’s “next” Node Note that by assigning a Node object like “current” to null effectively deletes that Node (in C++, you have to do a little more work) –This also means any object pointing to that Node will also be pointing to null –This stresses the importance of drawing pictures when it comes to the joys of pointers and dynamic memory management

Linked Lists Unordered search: // Situation #3 current = head.next; Node previous = head; while (current != null) { if (current.data == value) { previous.next = current.next; current = null; return true; } current = current.next; previous = previous.next; } return false; }

Linked Lists Delete analysis, part 2 In the 3 rd situation, we have to traverse the list to see if the element exists (and is also where the O(n) performance will come into play) We cannot just set the “current” Node to the next one though because we need visibility to the Node behind the current one We need the visibility because if we find the Node that is supposed to be deleted, the Linked List chain must remain intact Before the current Node can be set to null (and thus, deleted), the “previous” Node’s next pointer must first be set to the “current” Node’s next pointer Note that similar to the insert algorithm, this delete also effectively “shifts” elements to the left Also note that during the loop, if the current Node is not the one to delete, both current and previous have to traverse If the end of the list is reached (when current is pointing to null), all situations are tested. The search value not found for deletion

Linked Lists Delete performance As far as Big O categories go, this is another O(n) performance Putting minute details aside between these 4 algorithms for unsorted arrays and Linked Lists, the performances are the same Linked Lists give you dynamic memory allocation so in situations where that is important, use of them is preferred over arrays. Situations such as: –When you are concerned about unused space that potentially is needed for other things (remember memory can also be actual disk space) –When you are uncertain of the total amount of elements you’ll need This is all useful for unsorted situations…

Unordered Arrays vs. Linked Lists Summary: Worst CaseUnsorted ArraysUnsorted Linked Lists SearchO(n) InsertO(1) UpdateO(n) DeleteO(n) Static memory usageDynamic memory usage

Recall: Sorted Arrays Summary (Using Binary Search): Sorted Arrays (Binary Search)Worst CaseBest Case SearchO(log n)(not discussed, but O(1)) InsertO(log n) + O(n)O(n/2) UpdateO(log n) + O(n)(not discussed, but O(1)) DeleteO(log n) + O(n)O(n/2)

Linked Lists Sorted linked lists theory The O(n) in the worst case of the sorted array functions is due to a need to shift all elements in the worst case With a linked list, we have already seen with the insert and delete algorithm that with proper node management, there is no “shift” eliminating the O(n) performance The initial thought, then, is that the performance for sorted linked lists is reduced to O(log n) for all 4 functions Question: Is this a correct assessment?

Linked Lists Unfortunately, no Because of the nature of the Linked List structure for a Node only having visibility to its next Node, determining and directly accessing the “middle” of the chain of nodes is challenging Modifying the Linked List structure may help, but then you will have to find a way to map the entire list to simulate direct random access. At that point, you basically have an array Question: Because of this, what does the search performance degrade to? Question 2: How do the best/worst case performances of sorted arrays compare against sorted linked lists?

Sorted Arrays vs. Linked Lists Summary: Worst Case (Arrays)Worst Case (LL) Best Case (Arrays) Best Case (LL) SearchO(log n)O(n)O(1) InsertO(log n) + O(n)O(n)O(n/2)O(1) UpdateO(log n) + O(n)O(n)O(1) DeleteO(log n) + O(n)O(n)O(n/2)O(1)

Sorted Linked Lists vs. Arrays Give and Take In the worst cases, arrays and linked lists share an O(n) for the shift and search operations respectively for the maintenance functions Arrays also add an O(log n) for the binary search suggesting sorted linked lists perform better when insert, update and delete are performed In the best cases, linked lists are O(1) and don’t require any kind of shift for insert and delete suggesting sorted linked lists also perform better in those scenarios In the worst case, though, a sorted linked list searches for an element at O(n) because the nature of the structure doesn’t allow for the binary search algorithm to be utilized Sorted arrays win with search, and they win significantly

Sorted Linked Lists vs. Arrays Final notes If the order of the data is not necessary, linked lists and arrays perform the same, but linked lists allow for dynamic memory usage If order matters, linked lists perform slightly better than arrays as long as the need to search for elements is not significant Once you need to perform searches, though, sorted arrays are the winners. If only there was a way to do an O(log n) search with a dynamic memory structure like a linked list…