C#数据结构-LinkedList双链表实现

using System;
using System.Collections;
using System.Collections.Generic;

namespace StructScript
{
    public class LinkedListScript<T> : ICollection<T>
    {
        //表头
        public LinkedListNode<T> mHead = null;
        //表尾
        public LinkedListNode<T> mLast = null;
        private int mCount = 0;
        public LinkedListScript() { }

        public LinkedListScript(IEnumerable<T> collection)
        {
            if (collection == null)
            {
                throw new ArgumentNullException();
            }
            foreach (T item in collection)
            {
                AddLast(item);
            }
        }

        public LinkedListNode<T> First
        {
            get
            {
                return mHead;
            }
        }

        public LinkedListNode<T> Last
        {
            get
            {
                return mLast;
            }
        }

        public LinkedListNode<T> AddAfter(LinkedListNode<T> node, T value)
        {
            if (node == null)
            {
                throw new ArgumentNullException();
            }
            LinkedListNode<T> newNode = new LinkedListNode<T>(node.list, value);
            InsertAfterNode(node, newNode);
            return newNode;
        }

        public LinkedListNode<T> AddBefore(LinkedListNode<T> node, T value)
        {
            if (node == null)
            {
                throw new ArgumentNullException();
            }
            LinkedListNode<T> newNode = new LinkedListNode<T>(node.list, value);
            InsertBeforeNode(node, newNode);
            return newNode;
        }

        public void AddAfter(LinkedListNode<T> node, LinkedListNode<T> newNode)
        {
            if (node == null || newNode == null)
            {
                throw new ArgumentNullException();
            }
            newNode.list = node.list;
            InsertAfterNode(node, newNode);
        }

        public void AddBefore(LinkedListNode<T> node, LinkedListNode<T> newNode)
        {
            if (node == null || newNode == null)
            {
                throw new ArgumentNullException();
            }
            if (Contains(newNode.Item))
            {
                throw new InvalidOperationException();
            }
            newNode.list = node.list;
            InsertBeforeNode(node, newNode);
        }

        public LinkedListNode<T> AddFirst(T value)
        {
            LinkedListNode<T> node = new LinkedListNode<T>(this, value);
            AddFirst(node);
            return node;
        }

        public LinkedListNode<T> AddLast(T value)
        {
            LinkedListNode<T> node = new LinkedListNode<T>(this, value);
            AddLast(node);
            return node;
        }

        public void AddFirst(LinkedListNode<T> node)
        {
            if (node == null)
            {
                throw new ArgumentNullException();
            }
            if (mHead == null)
            {
                InsertEmptyLinkedList(node);
            }
            else
            {
                InsertBeforeNode(mHead, node);
            }
        }

        public void AddLast(LinkedListNode<T> node)
        {
            if (node == null)
            {
                throw new ArgumentNullException();
            }
            if (mLast == null)
            {
                InsertEmptyLinkedList(node);
            }
            else
            {
                InsertAfterNode(mLast, node);
            }
        }

        public void InsertEmptyLinkedList(LinkedListNode<T> node)
        {
            node.next = null;
            node.prev = null;
            //把新增节点赋值为最新的Head, Last节点
            mHead = node;
            mLast = node;
            mCount++;
        }

        public void InsertAfterNode(LinkedListNode<T> node, LinkedListNode<T> newNode)
        {
            if (node.next == null)
            {
                newNode.next = null;
                //把新增节点的prev指向之前的Last节点
                newNode.prev = mLast;
                //把之前的Last节点的next指向新增节点
                mLast.next = newNode;
                //把新增节点赋值为最新的Last节点
                mLast = newNode;
                mCount++;
            }
            else
            {
                //把新增节点的next指向之前的node节点的next
                newNode.next = node.next;
                //把新增节点的prev指向之前的node节点
                newNode.prev = node;
                //把之前的node节点的next的prev指向新增节点
                node.next.prev = newNode;
                //把之前的node节点的next指向新增节点
                node.next = newNode;
                mCount++;
            }
        }

        public void InsertBeforeNode(LinkedListNode<T> node, LinkedListNode<T> newNode)
        {
            if (node.prev == null)
            {
                //把新增节点的next指向之前的Head节点
                newNode.next = mHead;
                newNode.prev = null;
                //把之前的Head节点的prev指向新增节点
                mHead.prev = newNode;
                //把新增节点赋值为最新的Head节点
                mHead = newNode;
                mCount++;
            }
            else
            {
                //把新增节点的next指向之前的node节点
                newNode.next = node;
                //把新增节点的prev指向之前的node节点的prev
                newNode.prev = node.prev;
                //把之前的node节点的prev的next指向新增节点
                node.prev.next = newNode;
                //把之前的node节点的prev指向新增节点
                node.prev = newNode;
                mCount++;
            }
        }

        public LinkedListNode<T> Find(T value)
        {
            if (value == null)
            {
                return null;
            }
            LinkedListNode<T> node = mHead;
            EqualityComparer<T> comparer = EqualityComparer<T>.Default;
            if (node != null)
            {
                do
                {
                    if (comparer.Equals(node.Item, value))
                    {
                        return node;
                    }
                    node = node.next;
                } while (node != null);
            }
            return null;
        }

        public LinkedListNode<T> FindLast(T value)
        {
            if (value == null)
            {
                return null;
            }
            LinkedListNode<T> node = mLast;
            EqualityComparer<T> comparer = EqualityComparer<T>.Default;
            if (node != null)
            {
                do
                {
                    if (comparer.Equals(node.Item, value))
                    {
                        return node;
                    }
                    node = node.prev;
                } while (node != null);
            }
            return null;
        }

        public int Count
        {
            get
            {
                return mCount;
            }
        }

        public void Add(T item)
        {
            AddLast(item);
        }

        public void Clear()
        {
            LinkedListNode<T> node = mHead;
            while (node != null)
            {
                LinkedListNode<T> node1 = node;
                node1.Clear();
                node1.Item = default(T);
                //当next == list.mLast时,node.Next返回null,跳出循环
                node = node.Next;
            }
            mHead = null;
            mLast = null;
            mCount = 0;
        }

        public bool Contains(T item)
        {
            return Find(item) != null;
        }

        public void CopyTo(T[] array, int arrayIndex)
        {
            LinkedListNode<T> node = mHead;
            while (node != null)
            {
                array[arrayIndex] = node.Item;
                node = node.next;
                arrayIndex++;
            }
        }

        public bool Remove(T item)
        {
            if (item == null)
            {
                throw new ArgumentNullException();
            }
            LinkedListNode<T> node = mHead;
            EqualityComparer<T> comparer = EqualityComparer<T>.Default;
            while (node != null)
            {
                if (comparer.Equals(node.Item, item))
                {
                    LinkedListNode<T> node1 = node.prev;
                    LinkedListNode<T> node2 = node.next;
                    if (node1 != null)
                    {
                        node1.next = node2;
                    }
                    else
                    {
                        mHead = node2;
                    }
                    if (node2 != null)
                    {
                        node2.prev = node1;
                    }
                    else
                    {
                        mLast = node1;
                    }
                    node.Clear();
                    mCount--;
                    return true;
                }
                node = node.next;
            }
            return false;
        }

        public void Remove(LinkedListNode<T> newNode)
        {
            if (newNode == null)
            {
                throw new ArgumentNullException();
            }
            T item = newNode.Item;
            LinkedListNode<T> node = mHead;
            EqualityComparer<T> comparer = EqualityComparer<T>.Default;
            while (node != null)
            {
                if (comparer.Equals(node.Item, item))
                {
                    LinkedListNode<T> node1 = node.prev;
                    LinkedListNode<T> node2 = node.next;
                    if (node1 != null)
                    {
                        node1.next = node2;
                    }
                    else
                    {
                        mHead = node2;
                    }
                    if (node2 != null)
                    {
                        node2.prev = node1;
                    }
                    else
                    {
                        mLast = node1;
                    }
                    node.Clear();
                    mCount--;
                    break;
                }
                node = node.next;
            }
        }

        public void RemoveFirst()
        {
            LinkedListNode<T> node = mHead.next;
            node.prev = null;
            Remove(mHead);
            mHead = node;
        }

        public void RemoveLast()
        {
            LinkedListNode<T> node = mLast.prev;
            node.next = null;
            Remove(mLast);
            mLast = node;
        }

        public IEnumerator<T> GetEnumerator()
        {
            return new Enumerator(this);
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
            return new Enumerator(this);
        }

        public struct Enumerator : IEnumerator<T>
        {
            private LinkedListScript<T> list;
            private LinkedListNode<T> node;
            private int index;
            private T current;

            public Enumerator(LinkedListScript<T> list)
            {
                this.list = list;
                node = list.mHead;
                index = 0;
                current = default(T);
            }

            public T Current
            {
                get
                {
                    if (index <= 0 || index > list.Count)
                    {
                        throw new IndexOutOfRangeException();
                    }
                    return current;
                }
            }

            object IEnumerator.Current
            {
                get
                {
                    if (index <= 0 || index > list.Count)
                    {
                        throw new IndexOutOfRangeException();
                    }
                    return current;
                }
            }

            public void Dispose()
            {

            }

            public bool MoveNext()
            {
                if (index >= 0 && index < list.Count)
                {
                    if (node != null)
                    {
                        current = node.Item;
                        node = node.next;
                        index++;
                        return true;
                    }
                }
                return false;
            }

            public void Reset()
            {
                index = 0;
                current = default(T);
            }
        }
    }

    public sealed class LinkedListNode<T>
    {
        public LinkedListScript<T> list;
        public LinkedListNode<T> next;
        public LinkedListNode<T> prev;
        private T item;

        internal LinkedListNode(LinkedListScript<T> list, T value)
        {
            this.list = list;
            item = value;
        }

        public T Item
        {
            get { return item; }
            set { item = value; }
        }

        public LinkedListNode<T> Next
        {
            get { return next == null || next == list.mLast ? null : next; }
        }

        public void Clear()
        {
            list = null;
            next = null;
            prev = null;
        }
    }
}

IConnection<T>接口实现:

using System.Collections.Generic;

namespace StructScript
{
    public interface ICollection<T> : IEnumerable<T>
    {
        /// <summary>
        /// 返回列表中项的总数
        /// </summary>       
        int Count { get; }

        /// <summary>
        /// 添加一个新的项到列表中
        /// </summary>
        void Add(T item);

        /// <summary>
        /// 从列表中清除所有的项
        /// </summary>
        void Clear();

        /// <summary>
        /// 返回列表是否包含特定的项
        /// </summary>
        bool Contains(T item);

        /// <summary>
        /// 从列表复制到数组中
        /// </summary>
        void CopyTo(T[] array, int arrayIndex);

        /// <summary>
        /// 移除特定对象的第一个匹配项
        /// </summary>
        bool Remove(T item);
    }
}

附上,测试用例:

using System;
using System.Text;
using System.Collections.Generic;

namespace StructScript
{
    class TestLinkedList
    {
        public static void Main()
        {
            // Create the link list.
            string[] words =
                { "the", "fox", "jumped", "over", "the", "dog" };
            LinkedListScript<string> sentence = new LinkedListScript<string>(words);
            Display(sentence, "The linked list values:");
            Console.WriteLine("sentence.Contains(\"jumped\") = {0}", sentence.Contains("jumped"));

            // Add the word 'today' to the beginning of the linked list.
            sentence.AddFirst("today");
            Display(sentence, "Test 1: Add 'today' to beginning of the list:");

            // Move the first node to be the last node.
            LinkedListNode<string> mark1 = sentence.First;
            sentence.RemoveFirst();
            sentence.AddLast(mark1);
            Display(sentence, "Test 2: Move first node to be last node:");

            // Change the last node be 'yesterday'.
            sentence.RemoveLast();
            sentence.AddLast("yesterday");
            Display(sentence, "Test 3: Change the last node to 'yesterday':");

            // Move the last node to be the first node.
            mark1 = sentence.Last;
            sentence.RemoveLast();
            sentence.AddFirst(mark1);
            Display(sentence, "Test 4: Move last node to be first node:");


            // Indicate, by using parentheisis, the last occurence of 'the'.
            sentence.RemoveFirst();
            LinkedListNode<string> current = sentence.FindLast("the");
            IndicateNode(current, "Test 5: Indicate last occurence of 'the':");

            // Add 'lazy' and 'old' after 'the' (the LinkedListNode named current).
            sentence.AddAfter(current, "old");
            sentence.AddAfter(current, "lazy");
            IndicateNode(current, "Test 6: Add 'lazy' and 'old' after 'the':");

            // Indicate 'fox' node.
            current = sentence.Find("fox");
            IndicateNode(current, "Test 7: Indicate the 'fox' node:");

            // Add 'quick' and 'brown' before 'fox':
            sentence.AddBefore(current, "quick");
            sentence.AddBefore(current, "brown");
            IndicateNode(current, "Test 8: Add 'quick' and 'brown' before 'fox':");

            // Keep a reference to the current node, 'fox',
            // and to the previous node in the list. Indicate the 'dog' node.
            mark1 = current;
            LinkedListNode<string> mark2 = current.prev;
            current = sentence.Find("dog");
            IndicateNode(current, "Test 9: Indicate the 'dog' node:");

            // The AddBefore method throws an InvalidOperationException
            // if you try to add a node that already belongs to a list.
            //Console.WriteLine("Test 10: Throw exception by adding node (fox) already in the list:");
            //try
            //{
            //    sentence.AddBefore(current, mark1);
            //}
            //catch (InvalidOperationException ex)
            //{
            //    Console.WriteLine("Exception message: {0}", ex.Message);
            //}
            //Console.WriteLine();

            // Remove the node referred to by mark1, and then add it
            // before the node referred to by current.
            // Indicate the node referred to by current.
            sentence.Remove(mark1);
            sentence.AddBefore(current, mark1);
            IndicateNode(current, "Test 11: Move a referenced node (fox) before the current node (dog):");

            // Remove the node referred to by current.
            sentence.Remove(current);
            IndicateNode(current, "Test 12: Remove current node (dog) and attempt to indicate it:");

            // Add the node after the node referred to by mark2.
            sentence.AddAfter(mark2, current);
            IndicateNode(current, "Test 13: Add node removed in test 11 after a referenced node (brown):");

            // The Remove method finds and removes the
            // first node that that has the specified value.
            sentence.Remove("old");
            Display(sentence, "Test 14: Remove node that has the value 'old':");

            // When the linked list is cast to ICollection(Of String),
            // the Add method adds a node to the end of the list.
            sentence.RemoveLast();
            ICollection<string> icoll = sentence;
            icoll.Add("rhinoceros");
            Display(sentence, "Test 15: Remove last node, cast to ICollection, and add 'rhinoceros':");

            Console.WriteLine("Test 16: Copy the list to an array:");
            // Create an array with the same number of
            // elements as the inked list.
            string[] sArray = new string[sentence.Count];
            sentence.CopyTo(sArray, 0);

            foreach (string s in sArray)
            {
                Console.WriteLine(s);
            }

            // Release all the nodes.
            sentence.Clear();

            Console.WriteLine();
            Console.WriteLine("Test 17: Clear linked list. Contains 'jumped' = {0}",
                sentence.Contains("jumped"));

            Console.ReadLine();
        }

        private static void Display(LinkedListScript<string> words, string test)
        {
            Console.WriteLine(test);
            foreach (string word in words)
            {
                Console.Write(word + " ");
            }
            Console.WriteLine();
            Console.WriteLine();
        }

        private static void IndicateNode(LinkedListNode<string> node, string test)
        {
            Console.WriteLine(test);
            if (node.list == null)
            {
                Console.WriteLine("Node '{0}' is not in the list.\n",
                    node.Item);
                return;
            }

            StringBuilder result = new StringBuilder("(" + node.Item + ")");
            LinkedListNode<string> nodeP = node.prev;

            while (nodeP != null)
            {
                result.Insert(0, nodeP.Item + " ");
                nodeP = nodeP.prev;
            }

            node = node.next;
            while (node != null)
            {
                result.Append(" " + node.Item);
                node = node.next;
            }

            Console.WriteLine(result);
            Console.WriteLine();
        }
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值