C# 双向链表实现

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace CSharpLinkedList
{
    class Program
    {
        static void Main(string[] args)
        {
            var test = new CSharpLinkedList<int>();
            var data = Enumerable.Range(1, 50).ToList();
            foreach (var i in data)
            {
                test.AddLast(i);
            }
            Console.WriteLine(test.Count);
            test.Print();
            foreach (var i in data.Where(d => d % 2 == 0))
            {
                test.Remove(i);
            }
            Console.WriteLine(test.Count);

            test.Print();

            foreach (var i in data.Where(d => d % 3 == 0))
            {
                test.Remove(i);
            }
            Console.WriteLine(test.Count);

            test.Print();

            Console.ReadKey();
        }
    }

     /// <summary>
     /// 双向链表
     /// </summary>
     /// <typeparam name="T"></typeparam>
    public class CSharpLinkedList<T> : IEnumerable<T>
    {
        //双向链表的头节点。通过它可以访问到链表所有的节点
        //C#选择不把头节点暴露为公共的,这样可以使得用户不能在初始化链表时传入头节点
        //防止传入了头节点却忘了设置它的prev和next导致之后插入删除发生错误的问题
        //头节点必须通过AddFirst或AddLast方法插入,在那两个方法里,设置头节点的prev和next
        internal CSharpLinkedListNode<T> head;

        //C#的链表内部维护一个长度,使得统计长度的时间复杂度为常数
        private int count;

        //对外的
        public int Count
        {
            get { return count; }
        }

        //链表第一个成员
        public CSharpLinkedListNode<T> First
        {
            get { return head; }
        }

        //链表最后一个成员
        public CSharpLinkedListNode<T> Last
        {
            get
            {
                if (head != null)
                {
                    return head.prev;
                }
                return null;
            }
        }

        //构造函数什么都不需要做
        public CSharpLinkedList()
        {
        }

        public CSharpLinkedListNode<T> Find(T value)
        {
            var next = head;
            var comparer = EqualityComparer<T>.Default;
            if (next != null)
            {
                //如果传入的不是null,遍历链表
                if (value != null)
                {
                    //泛型不能直接比较,需要引入EqualityComparer
                    while (!comparer.Equals(next.item, value))
                    {
                        next = next.next;
                        //双向链表转回头意味着遍历结束
                        if (next == head)
                        {
                            return null;
                        }
                    }
                    return next;
                }
                //如果传入的是null,遍历链表,返回第一个值为null的节点
                while (next.item != null)
                {
                    next = next.next;
                    //双向链表转回头意味着遍历结束
                    if (next == head)
                    {
                        return null;
                    }
                }
                return next;
            }
            return null;
        }

        internal void InsertNodeToEmptyList(CSharpLinkedListNode<T> node)
        {
            head = node;
            head.next = head;
            head.prev = head;
            count++;
        }
        internal void InsertNodeBefore(CSharpLinkedListNode<T> node, CSharpLinkedListNode<T> newNode)
        {
            newNode.next = node;
            newNode.prev = node.prev;
            node.prev.next = newNode;
            node.prev = newNode;
            count++;
        }
        //在链表开头插入节点(插入到head节点之前)
        public void AddFirst(CSharpLinkedListNode<T> node)
        {
            //空链表
            if (head == null)
            {
                InsertNodeToEmptyList(node);
            }
            else
            {
                InsertNodeBefore(head, node);
            }
        }

        //在链表开头插入值为value的节点(插入到head节点之前)
        public void AddFirst(T value)
        {
            AddFirst(new CSharpLinkedListNode<T>(value));
        }
        //在链表结尾插入节点
        public void AddLast(CSharpLinkedListNode<T> node)
        {
            //空链表
            if (head == null)
            {
                InsertNodeToEmptyList(node);
            }
            else
            {
                //链表的结尾就是链表head节点的前一个节点
                InsertNodeBefore(head, node);
            }
        }

        //在链表开头插入值为value的节点(插入到head节点之前)
        public void AddLast(T value)
        {
            AddLast(new CSharpLinkedListNode<T>(value));
        }
        //在某个节点前面插入一个值
        public void AddBefore(CSharpLinkedListNode<T> node, CSharpLinkedListNode<T> newNode)
        {
            InsertNodeBefore(node, node);

            //设置头节点
            if (node == head)
            {
                head = newNode;
            }
        }

        //在某个节点后面插入一个值
        public void AddAfter(CSharpLinkedListNode<T> node, CSharpLinkedListNode<T> newNode)
        {
            InsertNodeBefore(node.next, newNode);
        }
        public void Remove(CSharpLinkedListNode<T> node)
        {
            //链表仅有这个节点
            if (node.next == node)
            {
                head = null;
            }
            else
            {
                node.prev.next = node.next;
                node.next.prev = node.prev;

                //如果删除的是开头
                if (node == head)
                {
                    head = head.next;
                }
            }
            //干掉node发出来的两根指针,使它成为垃圾
            node.Invalidate();
            count--;
        }

        //传入值的重载形式
        public void Remove(T value)
        {
            var node = Find(value);
            if (node != null)
            {
                Remove(node);
            }
        }

        public void Print()
        {
            var current = First;
            do
            {
                Console.Write(current.item.ToString());
                current = current.next;
                if(current != First)
                {
                    Console.Write("->");
                }
            } while (current != First);

            Console.Write("\n");
        }

        public IEnumerator<T> GetEnumerator()
        {
            //传入链表本身
            return new CSharpLinkedListEnumerator(this);
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }

        //实现CSharpLinkedListEnumerator,继承IEnumerator<T>接口
        public class CSharpLinkedListEnumerator : IEnumerator<T>
        {
            private T current;
            public T Current
            {
                get { return current; }
            }

            object IEnumerator.Current
            {
                get { return current; }
            }

            //数据源
            private readonly CSharpLinkedList<T> list;

            //当前节点
            private CSharpLinkedListNode<T> node;

            //当前位置
            private int _position = -1;

            //初始化
            public CSharpLinkedListEnumerator(CSharpLinkedList<T> data)
            {
                list = data;
                node = list.head;
            }

            //访问下一个
            public bool MoveNext()
            {
                _position++;
                if (_position == list.count)
                {
                    return false;
                }

                current = node.item;
                node = node.next;
                return true;
            }

            //不需要实现
            public void Reset()
            {
                throw new NotImplementedException();
            }

            //不需要代码,C#知道该如何做
            public void Dispose()
            {
            }
        }
    }

    /// <summary>
    /// 双向链表节点
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public class CSharpLinkedListNode<T>
    {
        //这两个字段是私有的,防止用户不通过公共方法来胡乱篡改
        internal CSharpLinkedListNode<T> next;
        internal CSharpLinkedListNode<T> prev;

        //节点的值
        public T item { get; set; }

        public CSharpLinkedListNode(T value)
        {
            item = value;
        }

        //令一个节点成为垃圾
        public void Invalidate()
        {
            this.prev = null;
            this.next = null;
        }

    }

}

  

猜你喜欢

转载自www.cnblogs.com/ZHXI/p/12917421.html