Skip to Content
Course content

119: Implementing a Linked List in C#

Click on the "Edit" button in the top corner of the screen to edit your slide content.

I've always found that the best way to understand linked lists isn't by looking at a diagram of boxes and arrows, but by feeling the pain of the alternative. Let's imagine we're building a music playlist manager. We want to be able to add songs, remove them, and move them around without rewriting the entire list every time.

The Wall we hit with Arrays

If we used a standard array or even a List<T> under the hood, adding a song to the middle of a 10,000-song playlist is actually an expensive operation. The computer has to shift every single subsequent element one slot to the right to make room. It's a lot of unnecessary copying. I tried doing this in a prototype earlier, and while it's fast for small lists, the memory shuffling is just inefficient for a structure that's meant to be fluid.

So, what if we didn't store everything in one contiguous block of memory? What if each song just knew who the next song was?

Building the Atomic Unit: The Node

Let's try to define a "Node." Think of this as a wrapper. It doesn't just hold the song data; it holds a pointer to another node of the same type. I'll start with something simple:

public class SongNode
{
    public string SongTitle { get; set; }
    public SongNode Next { get; set; }

    public SongNode(string title)
    {
        SongTitle = title;
        Next = null; // By default, it's the end of the line
    }
}

Now, if I just create a few of these in a Main method, I can manually link them. node1.Next = node2; node2.Next = node3;. It works, but it's tedious. If I lose the reference to node1, I've effectively lost the entire playlist because I have no way to get back to the start. That's a disaster waiting to happen. We need a manager class.

Creating the Playlist Manager

I'll create a Playlist class. Its only real job is to keep track of where the list starts—the "Head." As long as I have the head, I can follow the Next chain to find anything else.

public class Playlist
{
    private SongNode head;

    public void PrintPlaylist()
    {
        SongNode current = head;
        while (current != null)
        {
            Console.WriteLine(current.SongTitle);
            current = current.Next;
        }
    }
}

Wait, I just realized I can't actually add anything to this yet. If I just create a Add(string title) method and set head = new SongNode(title), I'll just be overwriting the start of my list every time. I need to append to the end.

The Logic of Traversing

To add a song to the end, I have to start at the head and "walk" down the chain until I find a node where Next is null. That's the current end. Then I just plug my new song in there.

Let's try to implement that. I'll run into a problem immediately: what if the list is empty? If head is null, I can't walk down a chain that doesn't exist. I'll need a guard clause for that.

public void AddSong(string title)
{
    SongNode newNode = new SongNode(title);

    if (head == null)
    {
        head = newNode;
        return;
    }

    SongNode current = head;
    while (current.Next != null)
    {
        current = current.Next;
    }

    current.Next = newNode;
}

Now it's working. I can add "Bohemian Rhapsody," then "Stairway to Heaven," and the PrintPlaylist method will follow the trail. The beauty here is that if I want to insert a song in the middle, I don't have to shift 1,000 elements. I just find the node before the insertion point, point its Next to my new node, and point the new node's Next to the rest of the chain. It's like unhooking two train cars and snapping a new one in between them.




📋 Practical Task

Exercise: Implementing the "Remove Song" Feature

Your playlist manager is almost complete, but it's missing a way to delete songs. Your task is to add a method called RemoveSong(string title) to the Playlist class.

Requirements:

  • The method should search for a song by its title.
  • If the song to be removed is the head, the head should be updated to the second node in the list.
  • If the song is in the middle or at the end, you must "skip" it by connecting the node before the target to the node after the target.
  • If the song isn't found, the list should remain unchanged.

Starter Code:

public class SongNode
{
    public string SongTitle { get; set; }
    public SongNode Next { get; set; }
    public SongNode(string title) { SongTitle = title; Next = null; }
}

public class Playlist
{
    private SongNode head;

    public void AddSong(string title)
    {
        SongNode newNode = new SongNode(title);
        if (head == null) { head = newNode; return; }
        SongNode current = head;
        while (current.Next != null) { current = current.Next; }
        current.Next = newNode;
    }

    // TODO: Implement RemoveSong(string title) here

    public void PrintPlaylist()
    {
        SongNode current = head;
        while (current != null)
        {
            Console.WriteLine(current.SongTitle);
            current = current.Next;
        }
    }
}
Rating
0 0

There are no comments for now.

to be the first to leave a comment.