C#数据结构04:双链表

说明
(此系列帖子记录数据结构学习成果)

了解双链表

相比于单链表,双链表只是内部多了一个用于指向前继节点的指针,其他实现逻辑基本相似,只需要做下修改即可

双链表的构成

public T data; //实际存储的数据
public Node prev;//用来指向前一个节点
public Node next;//用来指向下一个节点

双链表基本结构

 class DoubleLinkedList<T>
 {
     //内部节点类
     private class Node
     {
         public T data;   //实际存储的数据
         public Node prev;//用来指向前一个节点
         public Node next;//用来指向下一个节点

         //构造函数,初始化链表
         public Node(T data ,Node prev ,Node next)
         {
             this.data= data;
             this.prev= prev;
             this.next= next;
         }
         public Node(T data)
         {
             this.data = data;
             this.prev = null;
             this.next = null;
         }

         //重写ToString
         public override string ToString()
         {
             return data.ToString();
         }
     }

     private Node Head; //记录链表得头部
     private Node Tail; //记录链表的尾部
     private int N;     //链表存储多少元素

     public DoubleLinkedList()
     {
         //初始化链表,此时全为null
         Head = null;
         Tail = null;
         N = 0;
     }

     //访问链表元素数量
     public int Count => N;
     //判断链表是否为空
     public bool IsEmpty => N == 0;
}

在Add方法中,插入中间节点

在这里插入图片描述

在定义cuurrent节点后,我们需要把current指向插入节点的位置。newNode节点是我们需要插入的节点

  • 我们需要把newNode节点先和链表建立联系,即①②
  • 再将newNode节点与表中节点建立连接后,方可执行断联操作,即③④

删除中间节点

  • 同样的道理,我们需要将删除节点的prev节点和next节点建立联系,再执行删除当前节点的操作
  • 即 current.prev.next = current.next; current.next.prev = current.prev;

        public void Add(int index, T t)
        {
            if (index <0 || index >N)
                throw new ArgumentOutOfRangeException("非法索引");

            //插入头部
            if (index == 0)
            {
                Node newNode = new Node(t);
                if (Head != null)
                {
                    Head.prev = newNode;
                    newNode.next = Head;
                }
                Head = newNode;
                //如果这是唯一一个节点,更新尾部
                if (Tail == null)
                    Tail = Head;
            }
            //尾部插入
            else if (index == N)
            {
                Node newNode = new Node(t);
                if (Tail != null)
                {
                    Tail.next = newNode;
                    newNode.prev = Tail;
                }
                Tail = newNode;
                //如果这是唯一一个节点,更新头部
                if (Head == null)
                    Head = Tail;
            }
            //链表中间插入
            else
            {
                Node newNode = new Node(t);

                //遍历节点,找到要插入位置的前一个节点
                Node current = Head;
                for (int i = 0; i < index;i++)
                    current = current.next;//此时current指向要插入的位置
                //连接节点
                newNode.prev = current.prev;
                newNode.next = current;
                current.prev.next = newNode;
                current.prev = newNode;
            }
            //增加链表长度
            N++;
        }

总代码

using System;
using System.Text;

namespace List
{
    class DoubleLinkedList<T>
    {
        //内部节点类
        private class Node
        {
            public T data;   //实际存储的数据
            public Node prev;//用来指向前一个节点
            public Node next;//用来指向下一个节点

            //构造函数,初始化链表
            public Node(T data ,Node prev ,Node next)
            {
                this.data= data;
                this.prev= prev;
                this.next= next;
            }
            public Node(T data)
            {
                this.data = data;
                this.prev = null;
                this.next = null;
            }

            //重写ToString
            public override string ToString()
            {
                return data.ToString();
            }
        }

        private Node Head; //记录链表得头部
        private Node Tail; //记录链表的尾部
        private int N;     //链表存储多少元素

        public DoubleLinkedList()
        {
            //初始化链表,此时全为null
            Head = null;
            Tail = null;
            N = 0;
        }

        //访问链表元素数量
        public int Count => N;
        //判断链表是否为空
        public bool IsEmpty => N == 0;

        //在指定位置插入一个元素
        public void Add(int index, T t)
        {
            if (index <0 || index >N)
                throw new ArgumentOutOfRangeException("非法索引");

            //插入头部
            if (index == 0)
            {
                Node newNode = new Node(t);
                if (Head != null)
                {
                    Head.prev = newNode;
                    newNode.next = Head;
                }
                Head = newNode;
                //如果这是唯一一个节点,更新尾部
                if (Tail == null)
                    Tail = Head;
            }
            //尾部插入
            else if (index == N)
            {
                Node newNode = new Node(t);
                if (Tail != null)
                {
                    Tail.next = newNode;
                    newNode.prev = Tail;
                }
                Tail = newNode;
                //如果这是唯一一个节点,更新头部
                if (Head == null)
                    Head = Tail;
            }
            //链表中间插入
            else
            {
                Node newNode = new Node(t);

                //遍历节点,找到要插入位置的前一个节点
                Node current = Head;
                for (int i = 0; i < index;i++)
                    current = current.next;//此时current指向要插入的位置
                //连接节点
                newNode.prev = current.prev;
                newNode.next = current;
                current.prev.next = newNode;
                current.prev = newNode;
            }
            //增加链表长度
            N++;
        }
        //在头部插入
        public void AddFirst(T t) => Add(0, t);
        //在尾部插入
        public void AddLast(T t) => Add(N, t);

        // 查找链表是否包含元素
        public bool Contains(T t)
        {
            Node current =Head;
            while (current != null)
            {
                if (current.data.Equals(t))
                    return true;
                current = current.next;
            }
            return false;
        }
        //查询索引处的元素
        public T Get(int index)
        {
            if (index < 0 || index >= N)
                throw new ArgumentOutOfRangeException("非法索引");

            Node current = Head;
            for (int i = 0; i < index; i++)
                current = current.next;

            return current.data;
        }

        //修改元素
        public void Set(int index, T newt)
        {
            if (index < 0 || index >= N)
                throw new ArgumentOutOfRangeException("非法索引");

            Node current = Head;
            for (int i = 0; i < index; i++)
                current = current.next;

            current.data = newt;
        }

        //删除指定位置元素
        public T RemoveAt(int index)
        {
            if (index < 0 || index >= N)
                throw new ArgumentOutOfRangeException("非法索引");

            Node current = Head;
            if (index == 0)
            {
                //删除头部
                Head = Head.next;
                if (Head !=null)
                    Head.prev = null;
                else
                    Tail = null;
            }
            else if (index == N - 1)
            {
                //删除尾部
                Tail = Tail.prev;
                if (Tail != null)
                    Tail.next = null;
                else
                    Head = null;
            }
            else
            {
                //删除中间
                for (int i = 0; i < index; i++)
                    current = current.next;

                current.prev.next = current.next;
                current.next.prev = current.prev;
            }

            N--;
            return current.data;
        }
        //查找元素删除
        public void Remove(T t)
        {
            Node current = Head;

            while (current != null)
            {
                //找到元素
                if (current.data.Equals(t))
                {
                    if (current.prev != null)
                        current.prev.next = current.next;
                    else
                        Head = current.next;

                    if (current.next != null)
                        current.next.prev = current.prev;
                    else
                        Tail = current.prev;

                    N--;
                }
                current = current.next;
            }
        }
        //重写Tostring()
        public override string ToString()
        {
            StringBuilder sb = new StringBuilder();
            Node current = Head;
            while (current != null)
            {
                sb.Append(current.data + "<->");
                current = current.next;
            }
            sb.Append("Null");
            return sb.ToString();
        }
    }
}

  • 11
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值