C#單鏈表(數據結構)


學習單鏈表的源碼項目:http://files.cnblogs.com/xmfdsh/CSharp%E5%8D%95%E9%93%BE%E8%A1%A8.rar

鏈表是用一組任意的存儲單元來存儲線性表中的數據元素(在存儲單元中可以是連續的,也可以是不連續的)。鏈表在存儲數據元素時,除了存儲數據元素本身的信息外,還要存儲與它相鄰的數據元素的存儲地址信息。這兩部分信息組成該數據元素的存儲映像,稱為節點。

節點的形象圖如下:

首先定義一個類Node來表示這些節點:

public class Node<T>
    {
        private T data;        //數據域
        private Node<T> next;  //引用域

        #region 構造函數
        /// <summary>
        /// 構造函數
        /// </summary>
        /// <param name="val"></param>
        /// <param name="p"></param>
        public Node(T val, Node<T> p)
        {
            data = val;
            next = p;
        }
        public Node(Node<T> p)
        {
            next = p;
        }
        public Node(T val)
        {
            data = val;
            next = null;
        }
        public Node()
        {
            data = default(T);
            next = null;
        } 
        #endregion
        
        //數據域屬性
        public T Data
        {
            get
            {
                return data;
            }
            set
            {
                data = value;
            }
        }
        //引用域屬性
        public Node<T> Next
        {
            get
            {
                return next;
            }
            set
            {
                next = value;
            }
        }
    }

通常,我們把鏈表化成用箭頭相連接的節點序列,節點間的箭頭表示引用域中存儲的地址。具體單鏈表的形式表示如下:

網上找到 圖片,把循環列表 和 雙向鏈表都弄上去了,也好提前了解下

因此要定義一個類表示整個鏈表,其中中間當然運用到了之前寫Node類,類中的屬性如下:

       private Node<T> head;//單鏈表頭引用
        //頭引用屬性
        public Node<T> Head
        {
            get
            {
                return head;
            }
            set
            {
                head = value;
            }
        }
        //構造函數
        public LinkList()
        {
            head = null;
        }

接下來就是實現之前講的順序表中定義好的接口 http://www.cnblogs.com/xmfdsh/p/3698456.html

        //求單鏈表長度
        public int GetLength()
        {
            Node<T> p = head;
            int len = 0;
            while(p!=null)
            {
                len++;
                p = p.Next;
            }
            return len;
        }
        //清空單鏈表
        public void Clear()
        {
            head = null;
        }

        public bool IsEmpty()
        {
            if(head==null)
            {
                return true;
            }
            else
            {
                return false;
            }
        }

        public bool IsFull()
        {
            throw new NotImplementedException();
        }
        //在單鏈表末尾添加新元素
        public void Append(T item)
        {
            Node<T> q = new Node<T>(item);
            Node<T> p = new Node<T>();
            if(head==null)
            {
                head = q;
                return;
            }
            p = head;
            while(p.Next!=null)
            {
                p = p.Next;
            }
            p.Next = q;
        }
        //在單鏈表第i個節點位置插入一個item的節點
        public void Insert(T item, int i)
        {
            if(IsEmpty()||i<1)
            {
                Console.WriteLine("鏈表為空或插入位置不允許");
                return;
            }
            if (i == 1)
            {
                Node<T> q = new Node<T>(item);
                q.Next = head;
                head = q;
                return;
            }
            Node<T> p = head;
            Node<T> r = new Node<T>();
            int j = 1;
            while (p.Next != null && j < i)
            {
                r = p;
                p = p.Next;
                j++;
            }
            if (j == i)
            {
                Node<T> q = new Node<T>(item);
                q.Next = p;
                r.Next = q;
            }
        }
        //刪除單鏈表第i節點
        public T Delete(int i)
        {
            if(IsEmpty()||i<1)
            {
                Console.WriteLine("鏈表為空或刪除位置不允許");
                return default(T);
            }
            Node<T> q = new Node<T>();
            if (i == 1)
            {
                q = head;
                head = head.Next;
                return q.Data;
            }
            Node<T> p = head;
            int j = 1;
            while (p.Next != null && j < i)
            {
                j++;
                q = p;
                p = p.Next;
            }
            if (j == i)
            {
                q.Next = p.Next;
                return p.Data;
            }
            else
            {
                Console.WriteLine("刪除的節點不存在");
                return default(T);
            }

        }
        //獲取單鏈表第i個數據元素
        public T GetElem(int i)
        {
            if (IsEmpty() || i < 1)
            {
                Console.WriteLine("鏈表為空或者獲取位置不允許");
                return default(T);
            }
            Node<T> p = new Node<T>();
            p = head;
            int j = 1;
            while (p.Next != null && j < i)
            {
                p = p.Next;
                j++;
            }
            if (j == i)
            {
                return p.Data;
            }
            else
            {
                Console.WriteLine("要獲取的節點不存在");
                return default(T);
            }
        }
        //在單鏈表中查找值為value的節點
        public int Locate(T value)
        {
            if (IsEmpty())
            {
                Console.WriteLine("鏈表為空");
                return -1;
            }
            Node<T> p = new Node<T>();
            p = head;
            int i = 1;
            while (!p.Data.Equals(value) && p.Next != null)
            {
                p = p.Next;
                i++;
            }
            return i;
        }

實現這些接口都不難,還是要理解鏈表的具體操作原理,只是記代碼是沒用的,不用多久就忘的差不多,p.Next等這些地方可以聯想到C中的指針,不過C中的指針有時挺危險的,C#中的也許就安全多了吧。

然后再玩玩一些經典題目,首先就是單鏈表倒置

        //-----------------------------------單鏈表擴展方法---------------------------------------------
        /// <summary>
        /// 單鏈表倒置
        /// </summary>
        /// <param name="H"></param>
        public void ReversLinkList(LinkList<T> H)
        {
            Node<T> p = H.head;
            Node<T> q = new Node<T>();
            H.head.Next = null;
            while (p != null)
            {
                q = p;
                p = p.Next;
                q.Next = H.head.Next;
                H.head.Next = q;
            }
        }

再做個題目:構造單鏈表Hb,要求Hb只包含Ha表中所有值不相同節點

        /// <summary>
        /// 構造單鏈表Hb,要求Hb只包含Ha表中所有值不相同節點
        /// </summary>
        /// <param name="Ha"></param>
        /// <returns></returns>
        public LinkList<T> Purge(LinkList<T> Ha)
        {
            LinkList<T> Hb = new LinkList<T>();
            Node<T> p = Ha.head;
            Node<T> q = new Node<T>();
            Node<T> s = new Node<T>();

            s = p;
            p = p.Next;
            s.Next = null;
            Hb.head.Next = s;
            while (p != null)
            {
                s = p;
                p = p.Next;
                q = Hb.head;
                while(q!=null&&!(q.Data.Equals(s.Data)))
                {
                    q = q.Next;
                }
                if(q==null)
                {
                    s.Next = Hb.head;
                    Hb.head = s;
                }
            }
            return Hb;
        }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM