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。這樣在外部訪問時頭尾的鏈接就斷開了。(仔細閱讀源碼就能構很好的理解雙向循環鏈表以及它的優點了)

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