zoukankan      html  css  js  c++  java
  • C# LinkdeList链表源码分析 自定义LinkdeList链表

    C# LinkdeList链表源码分析 自定义LinkdeList链表

    源码地址

    https://referencesource.microsoft.com/#System/compmod/system/collections/generic/linkedlist.cs

    关键点

    • 双链表:每个节点包含上一节点信息和下一节点信息
    • 循环链表:头节点的上一节点信息为尾节点
    • 插入删除O(1)
    • 遍历0(N)
    • 获取Count属性O(1)
    • 使用场景:频繁插入删除数据 遍历的适合插入删除数据
      • 日志系统
      • 定时器

    自定义LinkdeList链表

    using System;
    using System.Collections.Generic;
    using System.Diagnostics;
    using System.Runtime.Serialization;
    
    /// <summary>
    /// 自定义链接
    /// 双重:每个节点都指向上个节点和下个节点
    /// 循环:首尾相连
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public class MyLinkedList<T>
    {
        internal MyLinkedListNode<T> head;
        internal int count;
        internal int version;
    
        private SerializationInfo siInfo;
    
        const String VersionName = "Version";
        const String CountName = "Count";
        const String ValuesName = "Data";
    
        public MyLinkedList()
        {
        }
    
        public MyLinkedList(IEnumerable<T> collection)
        {
            if (collection == null)
            {
                throw new ArgumentNullException("collection");
            }
    
            foreach (T item in collection)//循环添加项
            {
                AddLast(item);
            }
        }
    
        protected MyLinkedList(SerializationInfo info, StreamingContext context)
        {
            siInfo = info;
        }
    
        /// <summary>
        /// 获取链表数量
        /// </summary>
        public int Count
        {
            get { return count; }
        }
    
        /// <summary>
        /// 获取第一个节点
        /// </summary>
        public MyLinkedListNode<T> First
        {
            get { return head; }
        }
    
        /// <summary>
        /// 获取最后一个节点
        /// </summary>
        public MyLinkedListNode<T> Last
        {
            get { return head == null ? null : head.prev; }
        }
    
        /// <summary>
        /// 添加在node节点之后
        /// </summary>
        /// <param name="node">本链表的节点</param>
        /// <param name="value">新值</param>
        /// <returns></returns>
        public MyLinkedListNode<T> AddAfter(MyLinkedListNode<T> node, T value)
        {
            ValidateNode(node);//验证node节点是否是本链表
            MyLinkedListNode<T> result = new MyLinkedListNode<T>(node.list, value);//新建链表
            InternalInsertNodeBefore(node.next, result);//插入链表
            return result;
        }
        /// <summary>
        /// 添加在node节点之后
        /// </summary>
        /// <param name="node">本链表的节点</param>
        /// <param name="newNode">新节点</param>
        public void AddAfter(MyLinkedListNode<T> node, MyLinkedListNode<T> newNode)
        {
            ValidateNode(node);
            ValidateNewNode(newNode);//验证新节点是否为空
            InternalInsertNodeBefore(node.next, newNode);
            newNode.list = this;//赋值新节点的链表为本身
        }
    
        /// <summary>
        ///  添加在node节点之前
        /// </summary>
        /// <param name="node">本链表的节点</param>
        /// <param name="value">新值</param>
        /// <returns></returns>
        public MyLinkedListNode<T> AddBefore(MyLinkedListNode<T> node, T value)
        {
            ValidateNode(node);
            MyLinkedListNode<T> result = new MyLinkedListNode<T>(node.list, value);
            InternalInsertNodeBefore(node, result);
            if (node == head)
            {
                head = result;//如果插入的是头节点  则替换头节点
            }
            return result;
        }
    
        /// <summary>
        /// 添加在node节点之前
        /// </summary>
        /// <param name="node">本链表的节点</param>
        /// <param name="newNode">新节点</param>
        public void AddBefore(MyLinkedListNode<T> node, MyLinkedListNode<T> newNode)
        {
            ValidateNode(node);
            ValidateNewNode(newNode);
            InternalInsertNodeBefore(node, newNode);
            newNode.list = this;
            if (node == head)
            {
                head = newNode;
            }
        }
    
        /// <summary>
        /// 添加到头节点
        /// </summary>
        /// <param name="value">新值</param>
        /// <returns></returns>
        public MyLinkedListNode<T> AddFirst(T value)
        {
            MyLinkedListNode<T> result = new MyLinkedListNode<T>(this, value);
            if (head == null)
            {
                InternalInsertNodeToEmptyList(result);//头节点为空 赋值头节点
            }
            else
            {
                InternalInsertNodeBefore(head, result);
                head = result;//赋值头节点
            }
            return result;
        }
    
        /// <summary>
        /// 添加到头节点
        /// </summary>
        /// <param name="node">新节点</param>
        public void AddFirst(MyLinkedListNode<T> node)
        {
            ValidateNewNode(node);
    
            if (head == null)
            {
                InternalInsertNodeToEmptyList(node);
            }
            else
            {
                InternalInsertNodeBefore(head, node);
                head = node;
            }
            node.list = this;
        }
    
        /// <summary>
        /// 添加节点到末尾
        /// </summary>
        /// <param name="value">新值</param>
        /// <returns></returns>
        public MyLinkedListNode<T> AddLast(T value)
        {
            MyLinkedListNode<T> result = new MyLinkedListNode<T>(this, value);
            if (head == null)
            {
                InternalInsertNodeToEmptyList(result);//头节点为空 赋值头节点
            }
            else
            {
                InternalInsertNodeBefore(head, result);//插入节点
            }
            return result;
        }
    
        /// <summary>
        /// 添加节点到末尾
        /// </summary>
        /// <param name="node">新节点</param>
        public void AddLast(MyLinkedListNode<T> node)
        {
            ValidateNewNode(node);//验证新节点
    
            if (head == null)
            {
                InternalInsertNodeToEmptyList(node);
            }
            else
            {
                InternalInsertNodeBefore(head, node);
            }
            node.list = this;
        }
    
        /// <summary>
        /// 清理链表
        /// </summary>
        public void Clear()
        {
            MyLinkedListNode<T> current = head;
            while (current != null)
            {
                MyLinkedListNode<T> temp = current;
                current = current.Next; //遍历下一项
                temp.Invalidate();
            }
    
            head = null;
            count = 0;
            version++;
        }
    
        /// <summary>
        /// 判断是否包含项
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public bool Contains(T value)
        {
            return Find(value) != null;
        }
    
        /// <summary>
        /// 拷贝到数组
        /// </summary>
        /// <param name="array">数组容器</param>
        /// <param name="index">数组开始拷贝的索引</param>
        public void CopyTo(T[] array, int index)
        {
            if (array == null)
            {
                throw new ArgumentNullException("array");
            }
    
            if (index < 0 || index > array.Length)
            {
                throw new ArgumentOutOfRangeException("index", "index < 0 || index > array.Length");
            }
    
            if (array.Length - index < Count)
            {
                throw new ArgumentException("array.Length - index < Count");
            }
    
            MyLinkedListNode<T> node = head;
            if (node != null)
            {
                do
                {
                    array[index++] = node.item;//赋值到数组中
                    node = node.next;
                } while (node != head);
            }
        }
    
        /// <summary>
        /// 查找值的节点
        /// </summary>
        /// <param name="value">查找值</param>
        /// <returns></returns>
        public MyLinkedListNode<T> Find(T value)
        {
            MyLinkedListNode<T> node = head;
            EqualityComparer<T> c = EqualityComparer<T>.Default;//T类型的对比函数
            if (node != null)//头节点不为空
            {
                if (value != null)//查找值不为空
                {
                    do
                    {
                        if (c.Equals(node.item, value))
                        {
                            return node;
                        }
                        node = node.next;
                    } while (node != head);
                }
                else
                {
                    do
                    {
                        if (node.item == null)//查找值为空则判断 节点值是否为空
                        {
                            return node;
                        }
                        node = node.next;
                    } while (node != head);
                }
            }
            return null;
        }
    
        /// <summary>
        /// 查找值的节点从后
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public MyLinkedListNode<T> FindLast(T value)
        {
            if (head == null) return null;
    
            MyLinkedListNode<T> last = head.prev;//缓存最后一个节点
            MyLinkedListNode<T> node = last;
            EqualityComparer<T> c = EqualityComparer<T>.Default;
            if (node != null)
            {
                if (value != null)
                {
                    do
                    {
                        if (c.Equals(node.item, value))
                        {
                            return node;
                        }
    
                        node = node.prev;//赋值上一节点
                    } while (node != last);
                }
                else
                {
                    do
                    {
                        if (node.item == null)
                        {
                            return node;
                        }
                        node = node.prev;
                    } while (node != last);
                }
            }
            return null;
        }
    
        /// <summary>
        /// 获取循环枚举数
        /// </summary>
        /// <returns></returns>
        public Enumerator GetEnumerator()
        {
            return new Enumerator(this);
        }
    
        /// <summary>
        /// 获取序列化数据
        /// </summary>
        /// <param name="info"></param>
        /// <param name="context"></param>
        public virtual void GetObjectData(SerializationInfo info, StreamingContext context)
        {
            if (info == null)
            {
                throw new ArgumentNullException("info");
            }
            info.AddValue(VersionName, version);
            info.AddValue(CountName, count); 
            if (count != 0)
            {
                T[] array = new T[Count];
                CopyTo(array, 0);
                info.AddValue(ValuesName, array, typeof(T[]));
            }
        }
    
        /// <summary>
        /// 反序列化
        /// </summary>
        /// <param name="sender"></param>
        public virtual void OnDeserialization(Object sender)
        {
            if (siInfo == null)
            {
                return; 
            }
    
            int realVersion = siInfo.GetInt32(VersionName);
            int count = siInfo.GetInt32(CountName);
    
            if (count != 0)
            {
                T[] array = (T[])siInfo.GetValue(ValuesName, typeof(T[]));
    
                if (array == null)
                {
                    throw new SerializationException("array == null");
                }
                for (int i = 0; i < array.Length; i++)
                {
                    AddLast(array[i]);
                }
            }
            else
            {
                head = null;
            }
    
            version = realVersion;
            siInfo = null;
        }
    
        /// <summary>
        /// 删除值对应的节点
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public bool Remove(T value)
        {
            MyLinkedListNode<T> node = Find(value);
            if (node != null)
            {
                InternalRemoveNode(node);
                return true;
            }
            return false;
        }
    
        /// <summary>
        /// 删除节点
        /// </summary>
        /// <param name="node"></param>
        public void Remove(MyLinkedListNode<T> node)
        {
            ValidateNode(node);
            InternalRemoveNode(node);
        }
    
        /// <summary>
        /// 删除头节点
        /// </summary>
        public void RemoveFirst()
        {
            if (head == null) { throw new InvalidOperationException("head == null"); }
            InternalRemoveNode(head);
        }
    
        /// <summary>
        /// 删除尾节点
        /// </summary>
        public void RemoveLast()
        {
            if (head == null) { throw new InvalidOperationException("head == null"); }
            InternalRemoveNode(head.prev);
        }
    
    
    
        /// <summary>
        /// 内部插入节点之前
        /// </summary>
        /// <param name="node"></param>
        /// <param name="newNode"></param>
        private void InternalInsertNodeBefore(MyLinkedListNode<T> node, MyLinkedListNode<T> newNode)
        {
            newNode.next = node;//赋值新节点的下一节点
            newNode.prev = node.prev;//赋值新节点的上一节点
            node.prev.next = newNode;//赋值node的上一节点的下一节点为新节点
            node.prev = newNode;//赋值node的上衣节点为新节点
            version++;
            count++;
        }
    
        /// <summary>
        /// 内部插入节点到空列表
        /// </summary>
        /// <param name="newNode"></param>
        private void InternalInsertNodeToEmptyList(MyLinkedListNode<T> newNode)
        {
            Debug.Assert(head == null && count == 0, "LinkedList must be empty when this method is called!");
            newNode.next = newNode;//首位相连
            newNode.prev = newNode;//首位相连
            head = newNode;//赋值新节点为该链表的头节点
            version++;
            count++;
        }
    
        /// <summary>
        /// 内部删除节点
        /// </summary>
        /// <param name="node"></param>
        internal void InternalRemoveNode(MyLinkedListNode<T> node)
        {
            Debug.Assert(node.list == this, "Deleting the node from another list!");
            Debug.Assert(head != null, "This method shouldn't be called on empty list!");
            if (node.next == node)//节点数为1
            {
                Debug.Assert(count == 1 && head == node, "this should only be true for a list with only one node");
                head = null;
            }
            else
            {
                node.next.prev = node.prev;
                node.prev.next = node.next;
                if (head == node)
                {
                    head = node.next;//删除节点为头节点
                }
            }
            node.Invalidate();
            count--;
            version++;
        }
    
        /// <summary>
        /// 验证新节点
        /// </summary>
        /// <param name="node"></param>
        internal void ValidateNewNode(MyLinkedListNode<T> node)
        {
            if (node == null)
            {
                throw new ArgumentNullException("node");
            }
    
            if (node.list != null)
            {
                throw new InvalidOperationException("node.list");
            }
        }
    
        /// <summary>
        /// 验证节点
        /// </summary>
        /// <param name="node"></param>
        internal void ValidateNode(MyLinkedListNode<T> node)
        {
            if (node == null)
            {
                throw new ArgumentNullException("node");
            }
    
            if (node.list != this)
            {
                throw new InvalidOperationException("node.list");
            }
        }
    
    
        /// <summary>
        /// 枚举数
        /// </summary>
        public struct Enumerator : IEnumerator<T>, System.Collections.IEnumerator, ISerializable, IDeserializationCallback
        {
            private MyLinkedList<T> list;
            private MyLinkedListNode<T> node;
            private int version;
            private T current;
            private int index;
    
            private SerializationInfo siInfo; //A temporary variable which we need during deserialization.
    
    
            const string LinkedListName = "LinkedList";
            const string CurrentValueName = "Current";
            const string VersionName = "Version";
            const string IndexName = "Index";
    
            internal Enumerator(MyLinkedList<T> list)
            {
                this.list = list;
                version = list.version;
                node = list.head;
                current = default(T);
                index = 0;
    
                siInfo = null;
    
            }
    
    
            internal Enumerator(SerializationInfo info, StreamingContext context)
            {
                siInfo = info;
                list = null;
                version = 0;
                node = null;
                current = default(T);
                index = 0;
            }
    
    
            public T Current
            {
                get { return current; }
            }
    
            object System.Collections.IEnumerator.Current
            {
                get
                {
                    if (index == 0 || (index == list.Count + 1))
                    {
                        throw new ArgumentNullException("index == 0 || (index == list.Count + 1)");
                    }
    
                    return current;
                }
            }
    
            public bool MoveNext()
            {
                if (version != list.version)
                {
                    throw new InvalidOperationException("version != list.version");
                }
    
                if (node == null)
                {
                    index = list.Count + 1;
                    return false;
                }
    
                ++index;
                current = node.item;
                node = node.next;
                if (node == list.head)
                {
                    node = null;
                }
                return true;
            }
    
            void System.Collections.IEnumerator.Reset()
            {
                if (version != list.version)
                {
                    throw new InvalidOperationException("version != list.version");
                }
    
                current = default(T);
                node = list.head;
                index = 0;
            }
    
            public void Dispose()
            {
            }
    
    
            void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context)
            {
                if (info == null)
                {
                    throw new ArgumentNullException("info");
                }
    
                info.AddValue(LinkedListName, list);
                info.AddValue(VersionName, version);
                info.AddValue(CurrentValueName, current);
                info.AddValue(IndexName, index);
            }
    
            void IDeserializationCallback.OnDeserialization(Object sender)
            {
                if (list != null)
                {
                    return; //Somebody had a dependency on this Dictionary and fixed us up before the ObjectManager got to it.
                }
    
                if (siInfo == null)
                {
                    throw new SerializationException("version != list.version");
                }
    
                list = (MyLinkedList<T>)siInfo.GetValue(LinkedListName, typeof(MyLinkedList<T>));
                version = siInfo.GetInt32(VersionName);
                current = (T)siInfo.GetValue(CurrentValueName, typeof(T));
                index = siInfo.GetInt32(IndexName);
    
                if (list.siInfo != null)
                {
                    list.OnDeserialization(sender);
                }
    
                if (index == list.Count + 1)
                {  // end of enumeration
                    node = null;
                }
                else
                {
                    node = list.First;
                    // We don't care if we can point to the correct node if the LinkedList was changed   
                    // MoveNext will throw upon next call and Current has the correct value. 
                    if (node != null && index != 0)
                    {
                        for (int i = 0; i < index; i++)
                        {
                            node = node.next;
                        }
                        if (node == list.First)
                        {
                            node = null;
                        }
                    }
                }
                siInfo = null;
            }
        }
    }
    
    
    /// <summary>
    /// 自定义节点
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public sealed class MyLinkedListNode<T>
    {
        internal MyLinkedList<T> list;
        internal MyLinkedListNode<T> next;
        internal MyLinkedListNode<T> prev;
        internal T item;
    
        public MyLinkedListNode(T value)
        {
            this.item = value;
        }
    
        internal MyLinkedListNode(MyLinkedList<T> list, T value)
        {
            this.list = list;
            this.item = value;
        }
    
        public MyLinkedList<T> List
        {
            get { return list; }
        }
    
        public MyLinkedListNode<T> Next
        {
            get { return next == null || next == list.head ? null : next; }
        }
    
        public MyLinkedListNode<T> Previous
        {
            get { return prev == null || this == list.head ? null : prev; }
        }
    
        public T Value
        {
            get { return item; }
            set { item = value; }
        }
    
        /// <summary>
        /// 无效数据
        /// </summary>
        internal void Invalidate()
        {
            list = null;
            next = null;
            prev = null;
        }
    }
    
  • 相关阅读:
    最大匹配之匈牙利算法模板。。 (转)
    hdu 1597 find the nth digit
    hdu 1258 Sum It Up ( dfs )
    hdu 1596 find the safest road(Dijkstra)
    C 求完数 水仙花数 完全平方数 素数 2+22+222... PI
    C 字串匹配
    C 约瑟夫环[数组]
    C 鞍点所在行是最大值所在列是最小值
    C 创建链表并将信息存储在二进制文件中再读取
    C 统计字符数 行数
  • 原文地址:https://www.cnblogs.com/zouqiang/p/13156196.html
Copyright © 2011-2022 走看看