The Generic Linked List Collection class Modern Collections
- Slides: 28
The Generic Linked. List<> Collection class Modern Collections Classes
Table Of Contents
Generic Linked. List<> Overview
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 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
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 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 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: // 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
. 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. 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 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 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. 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
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 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?
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
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<>, 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() 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 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<>
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
- Singly linked list vs doubly linked list
- Singly linked list vs doubly linked list
- Apa itu single linked list
- Generic linked list java
- Using system.collections
- Using system collections generic
- Are all the methods in the collections class static?
- Landsat collection 1 vs collection 2
- D/a 30 days after sight
- Jenis linked list
- Singly vs doubly linked list
- Polynomial addition using linked list in c++
- Tan is a lover of linked list
- Xor linked list c
- Traverse a linked list c++
- Linked list in mips
- Definition of linked list
- Linked list diagram in java
- Advantages of singly linked list
- Language
- Circular linked list adalah
- Concurrent linked list
- Single linked list non circular
- List adt
- Difference between linked list and queue
- Circular linked list advantages
- Linked list sentinel
- Insertion in linked list algorithm
- Singly linked list in data structure