c# 实现单链表

单链表(Linked List)

说明

单链表是一种有序的列表
以节点的方式来进行存储(链式存储)
每个节点包含 data 域和 next 域
当节点没有下一个节点是,next为null
各个节点不一定连续存放
分为带头节点的和不带头节点的,根据需求来确定。

图解

在这里插入图片描述

节点代码

    class Node
    {
        public int ID { get; set; }
        public string Name { get; set; }
        public Node Next { get; set; }

        public Node(int iniID, string iniName)
        {
            this.ID = iniID;
            this.Name = iniName;
        }

        public override string ToString()
        {
            return $"[ID: {ID}, Name: {Name}]";
        }
    }

[注]
此处重写了 Node 的 ToString 方法,方便打印节点信息

链表代码框架

    class SingleLinkedList
    {
        private Node Head = new Node(0, "");

        public void Add(Node newNode);

        public void InsertByOrder(Node newNode);

        public void Delete(int ID);

        public void Update(Node newNode);

        public void Find(int ID);
    }

直接添加到链表末尾

目标

将传入的节点插入到当前链表的末尾

思路

从 Head 开始遍历,找到链表末尾,将最后一个节点的 next 指向新节点即可

代码
public void Add(Node newNode)
{
    var temp = Head;
    while (true)
    {
        if (temp.Next == null)
        {
            temp.Next = newNode;
            break;
        }
        temp = temp.Next;
    }
}

根据节点内某属性来按照特定顺序的添加

目标

将传入的节点插入到当前链表,并且要求链表中的节点依据ID从小到大的顺序排列

思路

[注] 本例按照ID从小到大的顺序
1.通过一个辅助变量找到待添加的位置
2.
newNode.Next = temp.Next;
temp.Next = newNode;

图解

在这里插入图片描述

代码
 public void InsertByOrder(Node newNode)
 {
     var temp = Head;
     bool flag = false;  //用于表示当前链表中是否已经存在对应ID的节点

     while (true)
     {
         if (temp.Next == null)
         {
             break;
         }
         if (temp.Next.ID == newNode.ID)
         {
             flag = true;
             break;
         }
         else if (temp.Next.ID > newNode.ID)
         {
             break;
         }
         temp = temp.Next;
     }
     if (flag)
     {
         Console.WriteLine("当前ID已有,添加失败");
         return;
     }
     else
     {
         newNode.Next = temp.Next;
         temp.Next = newNode;
     }

 }

目标

传入 int 类型的 iD 值,查找对应ID值的节点,并将其从链表中删除,如果未找到则删除失败

思路

1.根据辅助变量找到待删除节点的前一节点
2. temp.next = temp.next.next;
[注] 如果辅助变量指向待删除节点的话,因为是单链表,无法访问前一节点,因此无法删除

图解

删除节点前

删除节点前

删除节点后

在这里插入图片描述

代码

public void Delete(int ID)
{
    if (Head.Next == null)
    {
        Console.WriteLine("链表为空");
        return;
    }
    var temp = Head;
    var flag = false;	//用于表示当前链表中是否已经有对应ID值的节点

    while (true)
    {
        if (temp.Next == null)
        {
            break;
        }
        if (temp.Next.ID == ID)
        {
            flag = true;
            break;
        }
        temp = temp.Next;
    }

    if (flag)
    {
        temp.Next = temp.Next.Next;
    }
    else
    {
        Console.WriteLine("未找到");
    }
}

目标

传入一个新的节点,通过ID找到待修改的节点,将旧节点的信息替换

思路

遍历查找即可

代码

public void Update(Node newNode)
{
    if (Head.Next == null)
    {
        Console.WriteLine("链表为空");
        return;
    }

    var temp = Head.Next;
    bool flag = false;	//表示是否找到对应ID的节点
    while (true)
    {
        if (temp == null)
        {
            break;
        }
        if (temp.ID == newNode.ID)
        {
            flag = true;
            break;
        }
        temp = temp.Next;
    }
    if (flag)
    {
        temp.Name = newNode.Name;
    }
    else
    {
        Console.WriteLine("未找到对应节点");
    }
}

目标

通过传入的ID 值找到链表中匹配的节点,并将节点返回

思路

遍历即可

代码

public Node Find(int ID)
{
    if (Head.Next == null)
    {
        Console.WriteLine("链表为空");
        return null;
    }

    var temp = Head.Next;
    bool flag = false;	//表示是否找到对应节点

    while (true)
    {
        if (temp == null)
        {
            break;
        }
        if (temp.ID == ID)
        {
            flag = true;
            break;
        }
        temp = temp.Next;
    }
    if (flag)
    {
        return temp;
    }
    else
    {
        Console.WriteLine("没找到");
        return null;
    }
}

完整代码

class SingleLinkedList
{
    public Node Head { get; }

    public SingleLinkedList()
    {
        this.Head = new Node(0, "");
    }

    public void Add(Node newNode)
    {
        var temp = Head;
        while (true)
        {
            if (temp.Next == null)
            {
                temp.Next = newNode;
                break;
            }
            temp = temp.Next;
        }
    }

    public void InsertByOrder(Node newNode)
    {
        var temp = Head;
        bool flag = false;  //用于表示当前链表中是否已经存在对应ID的节点

        while (true)
        {
            if (temp.Next == null)
            {
                break;
            }
            if (temp.Next.ID == newNode.ID)
            {
                flag = true;
                break;
            }
            else if (temp.Next.ID > newNode.ID)
            {
                break;
            }
            temp = temp.Next;
        }
        if (flag)
        {
            Console.WriteLine("当前ID已有,添加失败");
            return;
        }
        else
        {
            newNode.Next = temp.Next;
            temp.Next = newNode;
        }

    }

    public void Delete(int ID)
    {
        if (Head.Next == null)
        {
            Console.WriteLine("链表为空");
            return;
        }
        var temp = Head;
        var flag = false;

        while (true)
        {
            if (temp.Next == null)
            {
                break;
            }
            if (temp.Next.ID == ID)
            {
                flag = true;
                break;
            }
            temp = temp.Next;
        }

        if (flag)
        {
            temp.Next = temp.Next.Next;
        }
        else
        {
            Console.WriteLine("未找到");
        }
    }

    public void Update(Node newNode)
    {
        if (Head.Next == null)
        {
            Console.WriteLine("链表为空");
            return;
        }

        var temp = Head.Next;
        bool flag = false;
        while (true)
        {
            if (temp == null)
            {
                break;
            }
            if (temp.ID == newNode.ID)
            {
                flag = true;
                break;
            }
            temp = temp.Next;
        }
        if (flag)
        {
            temp.Name = newNode.Name;
        }
        else
        {
            Console.WriteLine("未找到对应节点");
        }
    }

    public Node Find(int ID)
    {
        if (Head.Next == null)
        {
            Console.WriteLine("链表为空");
            return null;
        }

        var temp = Head.Next;
        bool flag = false;

        while (true)
        {
            if (temp == null)
            {
                break;
            }
            if (temp.ID == ID)
            {
                flag = true;
                break;
            }
            temp = temp.Next;
        }
        if (flag)
        {
            return temp;
        }
        else
        {
            Console.WriteLine("没找到");
            return null;
        }
    }
}

补充

队列反转

[注]创建一个新的头节点,遍历当前链表,使用头插法将当前链表所有节点插入新的头节点中,最后让链表头节点的 next 指向 新头节点的 next 即可。

代码

public void Reverse()
{
    if (Head.Next == null || Head.Next.Next == null)
    {
        return;
    }
    var reverseHead = new Node(0, "");
    var cur = Head.Next;
    Node next = null;

    while (cur != null)
    {
        next = cur.Next;
        cur.Next = reverseHead.Next;
        reverseHead.Next = cur;
        cur = next;
    }

    Head.Next = reverseHead.Next;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值