C#手写简单的LinkedList(参考源码)

1、定义自己的MyLinkedListNode类(基本照抄了源码)

namespace DataStructure
{
    public 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 this.list; }
        }

        public MyLinkedListNode<T> Next
        {
            get
            {
                if (this.next != null && this.next != this.list.head)
                    return this.next;
                return null;
            }
        }

        public MyLinkedListNode<T> Previous
        {
            get
            {
                if (this.prev != null && this != this.list.head)
                    return this.prev;
                return null;
            }
        }

        public T Value
        {
            get { return this.item; }
            set { this.item = value; }
        }

        internal void Invalidate()
        {
            this.list = null;
            this.next = null;
            this.prev = null;
        }
    }
}

2、定义自己的MyLinkedList类(大部分照抄了源码)

using System;

namespace DataStructure
{
    public class MyLinkedList<T>
    {
        internal MyLinkedListNode<T> head;

        internal int count;

        public int Count
        {
            get { return this.count; }
        }

        public MyLinkedListNode<T> First
        {
            get { return this.head; }
        }

        public MyLinkedListNode<T> Last
        {
            get
            {
                if (this.head != null)
                    return this.head.prev;
                return (MyLinkedListNode<T>) null;
            }
        }

        public MyLinkedListNode<T> AddAfter(MyLinkedListNode<T> node, T value)
        {
            this.ValidateNode(node);
            MyLinkedListNode<T> newNode = new MyLinkedListNode<T>(node.list, value);
            this.InternalInsertNodeBefore(node.next, newNode);
            return newNode;
        }

        public void AddAfter(MyLinkedListNode<T> node, MyLinkedListNode<T> newNode)
        {
            this.ValidateNode(node);
            this.ValidateNewNode(newNode);
            this.InternalInsertNodeBefore(node.next, newNode);
            newNode.list = this;
        }

        public MyLinkedListNode<T> AddBefore(MyLinkedListNode<T> node, T value)
        {
            this.ValidateNode(node);
            MyLinkedListNode<T> newNode = new MyLinkedListNode<T>(node.list, value);
            this.InternalInsertNodeBefore(node, newNode);
            if (node == this.head)
                this.head = newNode;
            return newNode;
        }

        public void AddBefore(MyLinkedListNode<T> node, MyLinkedListNode<T> newNode)
        {
            this.ValidateNode(node);
            this.ValidateNewNode(newNode);
            this.InternalInsertNodeBefore(node, newNode);
            newNode.list = this;
            if (node != this.head)
                return;
            this.head = newNode;
        }

        public MyLinkedListNode<T> AddFirst(T value)
        {
            MyLinkedListNode<T> newNode = new MyLinkedListNode<T>(this, value);
            if (this.head == null)
            {
                this.InternalInsertNodeToEmptyList(newNode);
            }
            else
            {
                this.InternalInsertNodeBefore(this.head, newNode);
                this.head = newNode;
            }

            return newNode;
        }

        public void AddFirst(MyLinkedListNode<T> node)
        {
            this.ValidateNewNode(node);
            if (this.head == null)
            {
                this.InternalInsertNodeToEmptyList(node);
            }
            else
            {
                this.InternalInsertNodeBefore(this.head, node);
                this.head = node;
            }

            node.list = this;
        }

        public MyLinkedListNode<T> AddLast(T value)
        {
            MyLinkedListNode<T> newNode = new MyLinkedListNode<T>(this, value);
            if (this.head == null)
                this.InternalInsertNodeToEmptyList(newNode);
            else
                this.InternalInsertNodeBefore(this.head, newNode);
            return newNode;
        }

        public void AddLast(MyLinkedListNode<T> node)
        {
            this.ValidateNewNode(node);
            if (this.head == null)
                this.InternalInsertNodeToEmptyList(node);
            else
                this.InternalInsertNodeBefore(this.head, node);
            node.list = this;
        }

        public void Clear()
        {
            MyLinkedListNode<T> linkedListNode1 = this.head;
            while (linkedListNode1 != null)
            {
                MyLinkedListNode<T> linkedListNode2 = linkedListNode1;
                linkedListNode1 = linkedListNode1.Next;
                linkedListNode2.Invalidate();
            }

            this.head = null;
            this.count = 0;
        }

        public bool Contains(T value)
        {
            return this.Find(value) != null;
        }

        public MyLinkedListNode<T> Find(T value)
        {
            MyLinkedListNode<T> linkedListNode = this.head;

            if (linkedListNode != null)
            {
                while (!linkedListNode.item.Equals(value))
                {
                    linkedListNode = linkedListNode.next;
                    if (linkedListNode == this.head)
                    {
                        return null;
                    }
                }

                return linkedListNode;
            }

            return null;
        }

        public bool Remove(T value)
        {
            MyLinkedListNode<T> node = this.Find(value);
            if (node == null)
                return false;
            this.InternalRemoveNode(node);
            return true;
        }

        public void Remove(MyLinkedListNode<T> node)
        {
            this.ValidateNode(node);
            this.InternalRemoveNode(node);
        }

        private void InternalInsertNodeBefore(MyLinkedListNode<T> node, MyLinkedListNode<T> newNode)
        {
            newNode.next = node;
            newNode.prev = node.prev;
            node.prev.next = newNode;
            node.prev = newNode;
            ++this.count;
        }

        private void InternalInsertNodeToEmptyList(MyLinkedListNode<T> newNode)
        {
            newNode.next = newNode;
            newNode.prev = newNode;
            this.head = newNode;
            ++this.count;
        }

        internal void InternalRemoveNode(MyLinkedListNode<T> node)
        {
            if (node.next == node)
            {
                this.head = null;
            }
            else
            {
                node.next.prev = node.prev;
                node.prev.next = node.next;
                if (this.head == node)
                    this.head = node.next;
            }

            node.Invalidate();
            --this.count;
        }

        internal void ValidateNode(MyLinkedListNode<T> node)
        {
            if (node == null)
                throw new Exception("MyLinkedListNode为null");
            if (node.list != this)
                throw new Exception("node所在的MyLinkedList不是这个");
        }

        internal void ValidateNewNode(MyLinkedListNode<T> node)
        {
            if (node == null)
                throw new Exception("MyLinkedListNode为null");
            if (node.list != null)
                throw new Exception("node所在的MyLinkedList不是这个");
        }

        public override string ToString()
        {
            MyLinkedListNode<T> linkedListNode = this.head;
            if (linkedListNode != null)
            {
                string str="";
                do
                {
                    str += " " + linkedListNode.item;
                    linkedListNode = linkedListNode.next;
                } while (linkedListNode != this.head);

                return str;
            }
            return null;
        }
    }
}

注意:参考代码可以得知,C#中的LinkedList内部是一个双向循环链表。LinkedListNode在内部相互连接形成了一个双向环。在LinkedList中只是指定了head,没有去指定last。而查找Last时只需通过head.prev就可以得到。而我们在外部使用时使用的是Next会去判断内部的next是否为head,如果是就返回null。外部使用的Previous会去判断当前节点是不是head,如果是就返回null。这样在外部访问时头尾的链接就断开了。(仔细阅读源码就能构很好的理解双向循环链表以及它的优点了)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章