340 likes | 394 Views
Data Structures and Algorithm Analysis. Dr. Ken Cosh Linked Lists. Review. Previously Complexity Analysis Computational & Asymptotic Analysis Big-O Notation Properties of Big-O Big Ω and Big Θ Amortized Analysis NP-Complete Problems Pointers & Dynamic Arrays Arrays of Arrays
E N D
Data Structures and Algorithm Analysis Dr. Ken Cosh Linked Lists
Review • Previously • Complexity Analysis • Computational & Asymptotic Analysis • Big-O Notation • Properties of Big-O • Big Ω and Big Θ • Amortized Analysis • NP-Complete Problems • Pointers & Dynamic Arrays • Arrays of Arrays • Classes with Pointers • Destructors • Copy Constructors
This Week • A new Data Structure • Linked Lists • Singly • Doubly • Circular • Skip Lists • Self Organising Lists • Sparse Tables
Linked Lists • Linked Lists • Why to use linked lists? • How to use linked lists? • Different Types of linked list.
Arrays • But first, lets review arrays. • A very useful structure provided by programming languages • However, arrays have at least 2 limitations; • The size has to be known at compilation. • The data in the array are separated in the computers memory by the same distance. • These limitations make ‘inserting’ an item inside the array difficult.
Linked Lists • Linked Lists can be used to get around the limitations of arrays by linking data independently from where it is stored in the computers memory. • To create a linked list, each piece of data in the set of data, simply has to also store the address of the next piece of data in the set.
Data Data Data Data Data A Simple Linked List P 0
Singly Linked Lists • The example on the previous page was an example of a singly linked list. • A pointer (P) to the first element in the list • Each element stores some data, and a pointer to the next element in the list • The final element points towards NULL (0), to indicate it is the final element. • The data stored in a linked list can be anything from a simple integer to a user defined class.
class Node { public: Node() { next = 0; } Node(int i, Node *in=0) { info = i; next = in; } int info; Node *next; }; This basic node has an integer (info), and a pointer to the next node in the linked list. There are 2 constructors, One for creating an empty list, which points towards NULL One for creating a new node in a list, with info i, again pointing towards NULL Node Code
Creating a linked list of Node Node *p = new Node(1); • Creates a pointer ‘p’ pointing to a new dynamic object of Node type p->next = new Node(2); • Creates the second node in the list. p->next->next = new Node(3); • Creates the third node in the list.
->next • We need a way to avoid needing excessive and error-prone use of; …->next->next->next->next->next->next->next… • So we need to add some useful member functions, to perform tasks such as; • Insertion • Deletion • Searching
Insertion • For a basic Linked list, we have two choices for insertion; • head_insert() • tail_insert() • Otherwise known as; • push_front() • push_back()
p Step 1 Step 2 p Data Data Data Data Data Data Data Data Data Data Data 0 0 p Step 3 p Step 4 0 0 head_insert
tail_insert • To insert a node at the end (tail) of a list, we first need a pointer to the last node in the list. • It is often a good idea to maintain 2 pointers, one to the head of a linked list, and one to the tail of a linked list. • Using the tail pointer, the steps are similar to head_insert.
Deletion • Deleting Nodes from a list is another important function. • Deleting from the head of the list • Deleting from the tail of the list • Deleting from somewhere in the middle of the list. • For each it is important not to lose the list – i.e. maintain a pointer to the rest of the list when deleting the head node etc. • Discuss how you would solve each function.
Considerations • Will the code work in all of these cases? • Attempting to delete a node from an empty list. • Deleting the only node from a one node list. • Attempting to delete a node which isn’t in the list.
Searching • Searching a singly linked list involves starting at the head and following the pointers through the list until either the node is found or the tail is reached. • A temporary pointer is used, tmp, where at each step it is pointed to the following node, tmp->next.
Doubly Linked Lists • The delete from tail function highlighted a difficulty inherent in singly linked lists. • In order to find the last element in a list, we have to scan through the entire list till we find the element pointing to NULL, we then have to delete this element, while tracking the previous element and pointing that to NULL. • If we are dealing with a long list, or frequent tail_delete function calls, it may be useful to have a Doubly Linked List.
Data Data Data Doubly Linked List Tail Head 0 0
Doubly Linked Lists • The two key changing functions for Doubly Linked are to add and delete from the tail of a doubly linked list. • Work through each of these functions taking care not to lose the list.
Circular Linked Lists • Another type of Linked List is a circular linked list • Here the final node in the list points back to the first node. • This can be useful for tracking things continually in sequence
Data Data Data Doubly Circular Linked Lists Tail Note that only one entry point (Tail) is required
Searching Inefficiency • With the linked lists we have encountered so far, there is a certain searching inefficiency. • If we want to find a particular node we have to start at a position and work through every node in the list until either we find the node we are looking for, or we reach the end of the list. • Skip Lists were introduced to offer an alternative searching structure.
Skip Lists • In a Skip List, each node can have a different number of pointers – some may have 1, some have 2 etc. • Using different pointers we can skip different nodes in the list until we find the element we are searching for.
1 2 5 12 13 16 19 23 27 33 39 47 54 67 Skip List Suppose we were to search the above Skip List for the number 17. Starting at the top level, with node #1 – we reach node #27. Returning to the next level, we go from node #1 to node #13 to node #27. Next the third level from node #13 reaches node #19, and finally the fourth level is nodes #13, #16, #19, so we can then tell that the node is not in the list.
Skip Lists • Skip Lists are efficient for searching, assuming they are configured correctly. • However, there are difficulties when it comes to other functionality • Adding or deleting a node from part way through a skip list would demand a redesign of the whole skip list to maintain efficiencies.
Arrays vs Linked Lists • Linked Lists have the advantage over arrays as they allow dynamic allocation of the necessary amount of memory; • Memory can be added or deleted at any point in a linked list • Arrays have advantages over linked lists firstly because they allow random access; • We can access the 10th element in an array quicker than the 10th element in a linked list. • Arrays can also sometimes take up less memory; • Linked lists can take up more space to store all the necessary pointers • Sometimes Arrays can waste memory if the array isn’t full • So how would you choose between an array and a linked list?
List Organisation • Clearly a list which is better organised will be more efficient than a disorganised list. • Therefore there are ways to reorder the linked list to maximise its efficiency. • Items that are more likely to be searched for can be placed at the start of the linked list, so they will be found first. • Options include; • Move-To-Front • Transpose • Count • Ordering • Amortised Cost Analysis can be used to predict which method should be used.
List Organisation Methods • Move-To-Front • Each time a node is searched for it is moved to the head of the list. • Transpose • Each time a node is searched, swap it with the previous node. • Count • Add a data element to each node, containing a count of the number of times it has been accessed – then order the list by the count. • Ordering • Use a natural criteria for list ordering, such as alphabetic order. • The first 3 methods aim to self organise the list, rearranging its order dynamically – new additions are automatically tail_inserted.
<list> • The Standard Template Library contains a library called <list>, which contains many of the functions we have discussed, and more. • The contents of the library are introduced on page 111 of the course text. • Take some time to familiarise yourselves with the list library.
Deque • A Deque is a double ended Queue – i.e. a list which allows access to both ends of the list, or a doubly linked list. • The STL also contains a deque class, which extends the functionality of the <list> library. • The <deque> class excludes some functions from the list class, including the merge function.