双向链表也叫双链表

双向链表也叫双链表

双向链表也叫双链表

每个节点都有两个指针,分别指向 直接前驱节点、直接后继节点

双向链表中任意一个节点,都可以通过通过它的前驱节点和后继节点,访问其他节点

节点如下

节点定义

ListNode

// 节点的值

T element;

// 前置节点

ListNode preNode;

// 后置节点

ListNode nextNode;

链表提供以下方法

项目 Value
PushFront(T t) 将元素插入到链表第一个位置
PushBack(T t) 将元素插入到链表最后一个位置
Front() 第一个节点
Back() 最后一个节点
MakeEmpty() 清空链表
IsEmpty() 判断链表是否为空
Size() 获取链表中数据个数
Find(T t) 查找节点
Delete(T t) 删除节点
Delete(ListNode node) 删除节点
InsertAsNext(ListNode node, ListNode next) 将 next 插入到 node 后
Begin() 迭代器开始
End() 迭代器结束
Deduplicate() 无序链表删除重复元素
Uniquify() 有序链表删除重复元素
List Traverse() 迭代遍历获取所有元素
Swap(ListNode node1, ListNode node2) 交换两个节点的值
Sort(Comparison comparison) 排序,comparison 是比较函数

C# 代码实现如下

csharp 复制代码
    /// <summary>
    /// 链表节点
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public class ListNode<T> where T : IComparable<T>
    {
        // 节点的值
        private T element;
        // 前置节点
        private ListNode<T> preNode;
        // 后置节点
        private ListNode<T> nextNode;

        public ListNode()
        {

        }

        public ListNode(T v)
        {
            element = v;
        }

        public ListNode(T v, ListNode<T> pre, ListNode<T> next)
        {
            element = v;
            preNode = pre;
            nextNode = next;
        }

        public T Element
        {
            get { return element; }
            set { element = value; }
        }

        public ListNode<T> PreNode
        {
            get { return preNode; }
            set { preNode = value; }
        }

        public ListNode<T> NextNode
        {
            get { return nextNode; }
            set { nextNode = value; }
        }
    }

    /// <summary>
    /// 链表迭代器
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public class LinkListIterator<T> where T : IComparable<T>
    {
        private ListNode<T> node;

        public LinkListIterator(ListNode<T> node)
        {
            this.node = node;
        }

        public ListNode<T> Node
        {
            get { return node; }
        }

        public T Element
        {
            get
            {
                return node.Element;
            }
        }

        /// <summary>
        /// 重写 == 方法
        /// </summary>
        /// <param name="iteratorL"></param>
        /// <param name="iteratorR"></param>
        /// <returns></returns>
        public static bool operator ==(LinkListIterator<T> iteratorL, LinkListIterator<T> iteratorR)
        {
            return null != iteratorL.node && null != iteratorR.node && iteratorL.node == iteratorR.node;
        }

        /// <summary>
        /// 重写 != 方法
        /// </summary>
        /// <param name="iteratorL"></param>
        /// <param name="iteratorR"></param>
        /// <returns></returns>
        public static bool operator !=(LinkListIterator<T> iteratorL, LinkListIterator<T> iteratorR)
        {
            return null == iteratorL.node || null == iteratorR.node || iteratorL.node != iteratorR.node;
        }

        /// <summary>
        /// 重写 ++ 方法
        /// </summary>
        /// <param name="iterator"></param>
        /// <returns></returns>
        public static LinkListIterator<T> operator ++(LinkListIterator<T> iterator)
        {
            iterator.node = iterator.node.NextNode;
            return iterator;
        }

        /// <summary>
        /// 重写 -- 方法
        /// </summary>
        /// <param name="iterator"></param>
        /// <returns></returns>
        public static LinkListIterator<T> operator --(LinkListIterator<T> iterator)
        {
            iterator.node = iterator.node.PreNode;
            return iterator;
        }

        public override bool Equals(object obj)
        {
            return base.Equals(obj);
        }

        public override int GetHashCode()
        {
            return base.GetHashCode();
        }
    }

    /// <summary>
    /// 链表
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public class LinkList<T> where T : IComparable<T>
    {
        /// <summary>
        /// 头节点
        /// </summary>
        private ListNode<T> _header;
        /// <summary>
        /// 尾节点
        /// </summary>
        private ListNode<T> _trailer;  
        // 除去 头、尾,节点的个数
        private int _size;

        public LinkList()
        {
            // 为了减少操作上的复杂度
            // 头节点和尾节点一直存在,添加、删除都是在 头节点、尾节点 中间操作
            _header = new ListNode<T>();
            _trailer = new ListNode<T>();

            _header.PreNode = null;
            _header.NextNode = _trailer;

            _trailer.PreNode = _header;
            _trailer.NextNode = null;
        }

        /// <summary>
        /// 迭代器开始
        /// </summary>
        /// <returns></returns>
        public LinkListIterator<T> Begin()
        {
            return new LinkListIterator<T>(_header.NextNode);
        }

        /// <summary>
        /// 迭代器结束
        /// </summary>
        /// <returns></returns>
        public LinkListIterator<T> End()
        {
            return new LinkListIterator<T>(_trailer);
        }

        /// <summary>
        /// 第一个元素
        /// </summary>
        public ListNode<T> Front()
        {
            return Size() > 0 ? _header.NextNode : null;
        }

        /// <summary>
        /// 最后一个元素
        /// </summary>
        public ListNode<T> Back()
        {
            return Size() > 0 ? _trailer.PreNode : null;
        }

        /// <summary>
        /// 清空链表
        /// </summary>
        public void MakeEmpty()
        {
            _header.NextNode = _trailer;
            _trailer.PreNode = _header;

            _size = 0;
        }

        /// <summary>
        /// 链表为空
        /// </summary>
        public bool IsEmpty()
        {
            return _header.NextNode == _trailer;
        }

        /// <summary>
        /// 链表元素个数
        /// </summary>
        public int Size()
        {
            return _size;
        }

        /// <summary>
        /// 查找元素指针位置
        /// </summary>
        public ListNode<T> Find(T t)
        {
            ListNode<T> temp = _header.NextNode;
            while (temp != _trailer)
            {
                if (temp.Element.CompareTo(t) == 0)
                {
                    return temp;
                }
                temp = temp.NextNode;
            }
            return null;
        }

        /// <summary>
        /// 删除元素
        /// </summary>
        public void Delete(T t)
        {
            ListNode<T> node = Find(t);
            Delete(node);
        }

        public void Delete(ListNode<T> node)
        {
            if (null != node)
            {
                node.PreNode.NextNode = node.NextNode;
                node.NextNode.PreNode = node.PreNode;
                --_size;
            }
        }

        /// <summary>
        /// 将元素插入到链表第一个位置
        /// </summary>
        /// <param name="t"></param>
        public void PushFront(T t)
        {
            ListNode<T> newNode = new ListNode<T>(t);
            InsertAsPre(_header.NextNode, newNode);
        }

        /// <summary>
        /// 将元素插入到链表最后一个位置
        /// </summary>
        /// <param name="t"></param>
        public void PushBack(T t)
        {
            ListNode<T> newNode = new ListNode<T>(t);
            InsertAsPre(_trailer, newNode);
        }

        private void InsertAsPre(ListNode<T> node, ListNode<T> next)
        {
            InsertAsNext(node.PreNode, next);
        }

        /// <summary>
        /// 将 next 插入到 node 后
        /// </summary>
        /// <param name="node"></param>
        /// <param name="next"></param>
        public void InsertAsNext(ListNode<T> node, ListNode<T> next)
        {
            if (node == _trailer)
            {
                return;
            }
            next.PreNode = node;
            next.NextNode = node.NextNode;

            node.NextNode.PreNode = next;
            node.NextNode = next;

            ++_size;
        }

        /// <summary>
        /// 无序链表删除重复元素
        /// </summary>
        public void Deduplicate()
        {
            for (ListNode<T> node = _header.NextNode; node != _trailer; node = node.NextNode)
            {
                for (ListNode<T> temp = node.NextNode; temp != _trailer; temp = temp.NextNode)
                {
                    if (node.Element.CompareTo(temp.Element) == 0)
                    {
                        Delete(temp);
                    }
                }
            }
        }

        /// <summary>
        /// 有序链表删除重复元素
        /// </summary>
        public void Uniquify()
        {
            ListNode<T> node = _header.NextNode;
            while ( node != _trailer)
            {
                ListNode<T> next = node.NextNode;
                if (next != _trailer && next.Element.CompareTo(node.Element) == 0)
                {
                    Delete(next);
                    continue;
                }
                node = node.NextNode;
            }
        }

        /// <summary>
        /// 遍历
        /// </summary>
        public List<T> Traverse()
        {
            List<T> list = new List<T>();
            for (LinkListIterator<T> iterator = Begin(); iterator != End(); ++iterator)
            {
                list.Add(iterator.Element);
            }
            return list;
        }

        /// <summary>
        /// 交换两个节点位置
        /// </summary>
        public void Swap(ListNode<T> node1, ListNode<T> node2)
        {
            if (node1.NextNode == node2)
            {
                Swap(node1.PreNode, node2.NextNode, node1, node2);
            }
            else if (node2.NextNode == node1)
            {
                Swap(node2.PreNode, node1.NextNode, node2, node1);
            }
            else
            {
                Swap(node1.PreNode, node2.NextNode, node1, node2);
            }
        }

        /// <summary>
        /// 交换两个节点位置
        /// </summary>
        /// <param name="pre"></param>
        /// <param name="next"></param>
        /// <param name="node1"></param>
        /// <param name="node2"></param>
        private void Swap(ListNode<T> pre, ListNode<T> next, ListNode<T> node1, ListNode<T> node2)
        {
            Delete(node1);
            Delete(node2);

            InsertAsNext(pre, node2);
            InsertAsPre(next, node1);
        }

        /// <summary>
        /// 排序
        /// </summary>
        public void Sort(Comparison<T> comparison)
        {
            ListNode<T> begin = _header.NextNode;
            if (null == begin || begin.NextNode == _trailer)
            {
                return;
            }

            for (ListNode<T> temp = begin.NextNode; temp != _trailer; temp = temp.NextNode)
            {
                T element = temp.Element;
                ListNode<T> preNode = temp.PreNode;
                while (preNode != _header.NextNode.PreNode && comparison(preNode.Element, element) > 0)
                {
                    preNode.NextNode.Element = preNode.Element;
                    preNode = preNode.PreNode;
                }

                preNode.NextNode.Element = element;
            }
        }
    }
相关推荐
吞下星星的少年·-·3 小时前
The 2026 ICPC Asia East Continent Online Contest (II)(构造)
数据结构·算法
Msshu1236 小时前
2~5串锂电快充优选|XSP36 Type‑C升压/升降压快充管理芯片
数据结构·随机森林·贪心算法·排序算法·线性回归·启发式算法
动词ing9 小时前
【学习笔记】数据结构栈与队列(栈先进后出+队列先进先出+括号匹配+消消乐模型)
数据结构·笔记·学习
a187927218319 小时前
【算法】链表(二):链表上的双指针——变速、异链与定距,和一份路程账本
数据结构·算法·leetcode·链表·go·指针·环形链表
zcmodeltech10 小时前
火电厂模型能演示冷态启动和故障处理吗?——基于STM32与Modbus RTU的集控实训控制系统设计
数据结构·stm32·单片机·嵌入式硬件·能源
Doubbbbbbble云11 小时前
区间合并问题的常见算法模式与优化思路4
java·数据结构·算法
David猪大卫11 小时前
【C++修炼】哈希表的实现
数据结构·c++·笔记·学习·算法·哈希算法·散列表
linx29513 小时前
单元九 · 零基础路线图-第 7–9 周·类与 RAII
c语言·开发语言·数据结构·c++·嵌入式硬件·算法
布莱克60513 小时前
C++ 七大排序算法详解:选择、冒泡、插入、计数、堆、快速与归并排序
数据结构·c++·算法·排序算法
科学实验家14 小时前
最小生成树:Prim,kruskal
数据结构·c++·算法