The Generic Linked List Collection class Modern Collections

  • Slides: 28
Download presentation
The Generic Linked. List<> Collection class Modern Collections Classes

The Generic Linked. List<> Collection class Modern Collections Classes

Table Of Contents

Table Of Contents

Generic Linked. List<> Overview

Generic Linked. List<> Overview

Linked. List<> stores data in a ‘chain’ of nodes The Stack static void Main(string[]

Linked. List<> stores data in a ‘chain’ of nodes The Stack static void Main(string[] args) Main() { Linked. List<int> num. List = new Linked. List<int>(); num. List. Add. First(10); num. List. Add. Last(20); Linked. List<int> object num. List. Add. Last(30); Internal reference to first and last nodes in the list foreach( int num in num. List) { null Console. Write. Line(num); } 10 null 20 30

Overview Linked. List<> class allows you to create, add, remove, and move nodes within

Overview Linked. List<> class allows you to create, add, remove, and move nodes within the list The Stack Main() This saves you time by not having to implement (write) it yourself You can use this to access items one at a time (as you walk along the chain). num. List You can get the individual nodes themselves You can quickly add / remove individual items (as they spliced into / out of the chain) Linked. List<int> First Last 2 1 You CANNOT jump to a location quickly (in contrast to arrays and the basic List)

Warm Up Code

Warm Up Code

Let’s start by looking at code that doesn’t interact with the nodes themselves

Let’s start by looking at code that doesn’t interact with the nodes themselves

Add. First() method, foreach loop The Stack // Part 1 Main() • Create a

Add. First() method, foreach loop The Stack // Part 1 Main() • Create a Linked. List of int’s • Then add a couple ints num. List Linked. List<int> num. List = new Linked. List<int>(); num. List. Add. First(1); num. List. Add. First(2); • Foreach can be used to access foreach (int num in num. List) every element in the list Linked. List<int> { First Last null 2 1 Console. Write. Line(num); • OUTPUT: 2 1 }

Add. Last() method The Stack • OUTPUT: Main() num. List contents: // Part 2

Add. Last() method The Stack • OUTPUT: Main() num. List contents: // Part 2 2, 1, 3, 4, 5 num. List. Add. Last(3); num. List. Add. Last(4); num. List. Add. Last(5); Print. List(num. List); Linked. List<int> First Last 2 1 3 4 5

Remove. First(), Remove. Last(), Remove() The Stack • OUTPUT: Main() num. List contents: //

Remove. First(), Remove. Last(), Remove() The Stack • OUTPUT: Main() num. List contents: // Part 3 1, 3, 4 num. List. Remove. First(); List contents: num. List. Remove. Last(); 1, 4 Print. List(num. List); num. List. Remove(3); // NOTE: Removing via the VALUE // Need to find value – O(N) Linked. List<int> First Last Print. List(num. List); 2 1 3 4 5

Now let’s look at code that chooses to be uses the nodes directly

Now let’s look at code that chooses to be uses the nodes directly

. First, . Next, . Previous instance variables • OUTPUT: First node’s value: 1

. First, . Next, . Previous instance variables • OUTPUT: First node’s value: 1 Next node’s value: 4 Previous node’s value: null ref. To. Node // Part 4 Linked. List. Node<int> ref. To. Node; // no node created yet ref. To. Node = num. List. First; Console. Write. Line(“First node’s value: {0}", ref. To. Node. Value); if (ref. To. Node. Next != null) Console. Write. Line("Next node’s value: {0}", ref. To. Node. Next. Value); Linked. List<int> First Last else Console. Write. Line("Next node’s value: null"); if (ref. To. Node. Previous != null ) Console. Write. Line("Previous node’s value: {0}", ref. To. Node. Previous. Value); 1 4 else Console. Write. Line("Previous node’s value: null");

Add. After(), Add. Before() • OUTPUT: List contents: // Part 5 num. List. Add.

Add. After(), Add. Before() • OUTPUT: List contents: // Part 5 num. List. Add. After(ref. To. Node, 6); 1, 6, 4 List contents: Print. List(num. List); 7, 1, 6, 4 num. List. Add. Before(ref. To. Node, 7); Print. List(num. List); Linked. List<int> First Last ref. To. Node 7 1 6 4

Remove(node) OUTPUT: // Part 6 ref. To. Node points to 1 ref. To. Node

Remove(node) OUTPUT: // Part 6 ref. To. Node points to 1 ref. To. Node STILL points to 1 Console. Write. Line("ref. To. Node points to {0}", ref. To. Node. Value); First list: List contents: num. List. Remove(ref. To. Node); // NOTE: Removing via the NODE 7, 6, 4 // Don’t have to find, so it’s Linked. List<int> Console. Write. Line("ref. To. Node STILL points to {0}", ref. To. Node. Value); First Last ref. To. Node Console. Write("First list: "); Print. List(num. List); 7 1 O(1) 6 4

Moving a node to a different list is fine OUTPUT: // Part 7 Second

Moving a node to a different list is fine OUTPUT: // Part 7 Second list: List contents: Linked. List<int> second. List = new Linked. List<int>(); 1 second. List. Add. First(ref. To. Node); Console. Write("Second list: "); Print. List(second. List); Linked. List<int> First Last null 7 6 4 ref. To. Node null 1

Find() OUTPUT: Found 4 Did NOT find 8 // Part 8 Linked. List. Node<int>

Find() OUTPUT: Found 4 Did NOT find 8 // Part 8 Linked. List. Node<int> find. It = num. List. Find(4); if (find. It != null) Console. Write. Line("Found 4"); Linked. List<int> else First Last Console. Write. Line("Did NOT find 4"); find. It Linked. List. Node<int> find. It = num. List. Find(8); if (find. It != null) 7 6 4 null Console. Write. Line("Found 8"); else Console. Write. Line("Did NOT find 8");

Methods You Must Memorize

Methods You Must Memorize

Useful Methods And Properties The Count property (how many items are in the list)

Useful Methods And Properties The Count property (how many items are in the list) Add. First(), Add. Last(): Adding new values, or a Linked. List. Node, to either end of the list Remove. First(), Remove. Last(), Remove(T) foreach loop . First, . Last properties on the List . Next, . Previous, . Value properties on the Linked. List. Node Find() Add. After(), Add. Before() Add value, or LLNode, to the list Remove(Linked. List. Node<>)

More Useful Methods Contains: Find an element by doing a linear search Linked. List

More Useful Methods Contains: Find an element by doing a linear search Linked. List doesn’t have a Sort method Linked. List doesn’t have a Binary. Search Because you can’t jump to an arbitrary spot Specifically, it’s O(N) to jump to the middle So even if the list was sorted it would take O(N • lg. N) to execute …Or you could do a linear search for O(N) ☺

How is List<> implemented? How can we figure this out on our own?

How is List<> implemented? How can we figure this out on our own?

Search The Web This particular data structure is very public about how it’s structured.

Search The Web This particular data structure is very public about how it’s structured. Interesting to note that you’re not allowed to manipulate the internal structures yourself You can call Add. Before to add a node before an existing node HOWEVER, you can’t change First/Last/Next/Previous yourself

Method Running Times in Big Oh notation

Method Running Times in Big Oh notation

Running times for list-based Add methods The running time for Add. First( value. To.

Running times for list-based Add methods The running time for Add. First( value. To. Add ) : “This method is an O(1) operation. ”, according to the docs on MSDN Because you’re adding the new element to the very start of the list, and because the Linked. List class keeps track of First, it takes a constant amount of time add the new node in In other words, you’re adding a single node from a known location, as demonstrated previously The running time for Add. Last( value. To. Add ): “This method is an O(1) operation. ” Similar to Add. First, you’re adding the new node to the end of the list, and the list tracks the last node (as you’ve seen in previous pictures) In other words, you’re adding a single node from a known location, as demonstrated previously

Running times for node-based Add methods The running time for Add. After(Linked. List. Node<>,

Running times for node-based Add methods The running time for Add. After(Linked. List. Node<>, value. To. Add): “This method is an O(1) operation. ”, according to the docs on MSDN Because you’re adding the new element to the very start of the list, and because the Linked. List class keeps track of First, it takes a constant amount of time add the new node in In other words, you’re adding a single node from a known location, as demonstrated previously The running time for Add. Before(Linked. List. Node<>, value. To. Add): “This method is an O(1) operation. ” Similar to Add. First, you’re adding the new node to the end of the list, and the list tracks the last node (as you’ve seen in previous pictures) In other words, you’re adding a single node from a known location, as demonstrated previously

Running times for Removes: The running time for Remove. First() and for Remove. Last()

Running times for Removes: The running time for Remove. First() and for Remove. Last() is O(1) For both, the ONLY remark is: “This method is an O(1) operation. ” ☺ You’re removing a single node from a known location, as demonstrated previously Remove(T) is O(N), because it has to walk through the list to find the thing to remove Example: “num. List. Remove(3); ” “This method performs a linear search; therefore, this method is an O(n) operation, where n is Count. ” You need to search through the list to find the thing to remove, as demonstrated previously Remove(Linked. List. Node<T>) is O(1) Example: “num. List. Remove(ref. To. Node); ” “This method is an O(1) operation. ” You’re removing a single node from a known location, as demonstrated previously

Running times: What the docs say Find(T) is O(N), because it has to walk

Running times: What the docs say Find(T) is O(N), because it has to walk through the list to find the thing to return “This method performs a linear search; therefore, this method is an O(n) operation, where n is Count. ” You need to search through the list to find the thing to remove, as demonstrated previously

When to use Linked. List<>

When to use Linked. List<>

Why /why not use a Linked. List<>? It’s good when you want to access

Why /why not use a Linked. List<>? It’s good when you want to access the values sequentially (i. e. , walk through the values in order) and you want to add new items into the middle as you walk through the list Fast (constant-time) insertion or removal But only at the start/end of the list, or near a node that you previously found In contrast, the array-based List<> can only add things to the end O(1) for adding to the end O(N) to shuffle everything down when adding to the middle) Slower (linear-time) access to the elements The best you can do for finding an element is O(N) / linear time Each <thing> we store requires a node, so it’s bad for storing a lot of small things For example, storing a lot of individual characters would be very inefficient