亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

C#集合本質(zhì)之鏈表的用法詳解

 更新時(shí)間:2022年08月17日 08:41:58   作者:Darren?Ji  
本文詳細(xì)講解了C#集合本質(zhì)之鏈表的用法,文中通過(guò)示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下

鏈表的由來(lái)和定義

在現(xiàn)實(shí)生活中,我們把不同的商品放在一個(gè)購(gòu)物車中。而在面向?qū)ο蟮氖澜缋?,有時(shí)候,也需要把不同類型的數(shù)據(jù)放到一起,組成一個(gè)集合。集合中的元素并不是彼此孤立的,在C#中,如何表達(dá)集合元素間的關(guān)系呢?

借助"自引用類"可以確立集合元素間的關(guān)系。比如有這樣一個(gè)自引用類:

public class Node
{
    public int Data{get;set;}
    public Node Next{get;set;}
    public Node(int dataValue)
    {}
}

Node類的最大特點(diǎn)是:存在一個(gè)Node類型的屬性,這個(gè)屬性指向Node的另一個(gè)實(shí)例,Next屬性也稱為"引用鏈"。放到集合的場(chǎng)景中來(lái)說(shuō)就是:把多個(gè)Node實(shí)例放到一個(gè)集合中,每一個(gè)Node實(shí)例包含一個(gè)Next屬性指向下一個(gè)Node實(shí)例。而該集合中的最后一個(gè)Node實(shí)例會(huì)指向null。用圖表示就是:

鏈表就是自引用類對(duì)象的線性集合,即序列。

由于每個(gè)自引用對(duì)象是由引用鏈鏈接起來(lái),所以叫鏈表。堆棧與隊(duì)列是約束版的鏈表,而二叉查找數(shù)是非線性數(shù)據(jù)結(jié)構(gòu)。

鏈表的節(jié)點(diǎn)或元素雖然在邏輯上是連續(xù)的、線性的,當(dāng)其內(nèi)存不是連續(xù)存儲(chǔ)的;數(shù)組元素在內(nèi)存中是連續(xù)的,所以我們才可以通過(guò)索引來(lái)訪問(wèn)數(shù)組元素。

創(chuàng)建一個(gè)單向鏈表

首先創(chuàng)建一個(gè)節(jié)點(diǎn),是一個(gè)自引用類:

namespace LinkedListLibrary
{
    public class ListNode
    {
        //當(dāng)前節(jié)點(diǎn)對(duì)象
        public object Data { get; private set; }
        //Next屬性也稱為鏈,指向另一個(gè)ListNode對(duì)象實(shí)例,這樣就把2個(gè)ListNode對(duì)象實(shí)例鏈接起來(lái)了
        public ListNode Next { get; set; }
        public ListNode(object dataValue): this(dataValue, null)
        {
            
        }
        public ListNode(object dataValue, ListNode nextNode)
        {
            Data = dataValue;
            Next = nextNode;
        }
    }
}

再模擬一個(gè)鏈表,如下:

namespace LinkedListLibrary
{
    public class List
    {
        private ListNode firstNode;
        private ListNode lastNode;
        private string name;
        public List(string listName)
        {
            name = listName;
            firstNode = lastNode = null;
        }
        public List() : this("list"){}
     
         ......
        //如果第一個(gè)節(jié)點(diǎn)是null,那就說(shuō)明集合為空
        public bool IsEmpty()
        {
            return firstNode == null;
        }
    }
}

以上,如果第一個(gè)節(jié)點(diǎn)為null,那就說(shuō)明該鏈表為空。List類提供了IsEmpty方法用來(lái)判斷鏈表是否為空。List還包含另外5個(gè)重要的方法,下面展開(kāi)來(lái)說(shuō)。

在鏈表的的第一個(gè)節(jié)點(diǎn)前插入。

        //在最前面插入元素、節(jié)點(diǎn)
        public void InsertAtFront(object insertItem)
        {
            if (IsEmpty())//如果集合為空,加進(jìn)來(lái)一個(gè)元素,相當(dāng)于第一個(gè)節(jié)點(diǎn)和第二個(gè)節(jié)點(diǎn)相同,都是新加的元素
            {
                firstNode = lastNode = new ListNode(insertItem);
            }
            else //如果集合不為空,第一個(gè)節(jié)點(diǎn)就是新加的元素,原先的第一個(gè)節(jié)點(diǎn)變?yōu)橄乱粋€(gè)節(jié)點(diǎn)
            {
                firstNode = new ListNode(insertItem, firstNode);
            }
        }

以上,當(dāng)集合不為空的情況下,實(shí)際上是把新添加的節(jié)點(diǎn)設(shè)為第一個(gè)節(jié)點(diǎn),并把新的第一個(gè)節(jié)點(diǎn)的引用鏈指向原先的第一個(gè)節(jié)點(diǎn)。

在鏈表的最后一個(gè)節(jié)點(diǎn)后插入。

        public void InsertAtBack(object insertItem)
        {
            if (IsEmpty())//如果原先集合為空,第一個(gè)節(jié)點(diǎn)和最后一個(gè)節(jié)點(diǎn)就是新加的節(jié)點(diǎn)
            {
                firstNode = lastNode = new ListNode(insertItem);
            }
            else//如果原先的集合不為空,最后一個(gè)節(jié)點(diǎn)的屬性值就是新加的節(jié)點(diǎn)
            {
                lastNode = lastNode.Next = new ListNode(insertItem);
            }
        }

以上,當(dāng)集合不為空的情況下,實(shí)際上是把新添加的節(jié)點(diǎn)設(shè)置成最后一個(gè)節(jié)點(diǎn),并把新的最后一個(gè)節(jié)點(diǎn)的引用鏈指向null。

移除鏈表最前面的節(jié)點(diǎn)。

        //移除最前面的元素、節(jié)點(diǎn)
        //即重新設(shè)置第一個(gè)節(jié)點(diǎn)的Next屬性
        public object RemoveFromFront()
        {
            if (IsEmpty())
                throw new EmptyListException(name);
            //從第一個(gè)節(jié)點(diǎn)中取出節(jié)點(diǎn)對(duì)象
            object removeItem = firstNode.Data;
            if (firstNode == lastNode) //如果集合中只有一個(gè)元素
            {
                firstNode = lastNode = null;
            }
            else //正常情況下,把firstNode的Next屬性所指向的節(jié)點(diǎn)賦值給第一個(gè)節(jié)點(diǎn)
            {
                firstNode = firstNode.Next;
            }
            return removeItem;
        }

以上,本質(zhì)是把原先排在第二位置的節(jié)點(diǎn)設(shè)置成第一個(gè)節(jié)點(diǎn)。

移除鏈表最后面的節(jié)點(diǎn)。

        //移除最后面的元素、節(jié)點(diǎn)
        public object RemoveFromBack()
        {
            if (IsEmpty())
            {
                throw new EmptyListException();
            }
            //從最后一個(gè)節(jié)點(diǎn)中獲取節(jié)點(diǎn)對(duì)象
            object removeItem = lastNode.Data;
            if (firstNode == lastNode)//如果當(dāng)前集合只有一個(gè)節(jié)點(diǎn)
            {
                firstNode = lastNode = null;
            }
            else
            {
                //先把第一個(gè)節(jié)點(diǎn)作為當(dāng)前節(jié)點(diǎn)
                ListNode current = firstNode; 
                //改變除最后一個(gè)節(jié)點(diǎn)之外的節(jié)點(diǎn)的值
                while (current.Next != lastNode)
                {
                    current = current.Next;
                }
                //最后current變成倒數(shù)第二個(gè)節(jié)點(diǎn)
                lastNode = current;
                current.Next = null;//最后一個(gè)節(jié)點(diǎn)的Next屬性為null,即沒(méi)有指向另一個(gè)節(jié)點(diǎn)
            }
            return removeItem;
        }

以上,從第一個(gè)節(jié)點(diǎn)開(kāi)始,一直循環(huán)到倒數(shù)第二個(gè)節(jié)點(diǎn),current就像一個(gè)指針,每指到一個(gè)節(jié)點(diǎn),就把該節(jié)點(diǎn)的下面一個(gè)節(jié)點(diǎn)設(shè)置為當(dāng)前節(jié)點(diǎn)。最后,把倒數(shù)第二個(gè)節(jié)點(diǎn)設(shè)置為最后一個(gè)節(jié)點(diǎn)。 把Current的引用鏈設(shè)置為null,讓其能被垃圾回收機(jī)制回收。

打印鏈表。

        //打印顯示
        public void Display()
        {
            if (IsEmpty())
            {
                Console.WriteLine("集合" + name + "為空");
            }
            else
            {
                Console.WriteLine("集合的名稱是:" + name);
                //先把第一個(gè)節(jié)點(diǎn)作為當(dāng)前節(jié)點(diǎn)
                ListNode current = firstNode;
                while (current != null)
                {
                    //把當(dāng)前節(jié)點(diǎn)對(duì)象打印出來(lái)
                    Console.Write(current.Data + " ");
                    //把下一個(gè)節(jié)點(diǎn)設(shè)置為當(dāng)前節(jié)點(diǎn)
                    current = current.Next;
                }
                Console.WriteLine("\n");
            }
        }   

以上,從第一個(gè)節(jié)點(diǎn)開(kāi)始,一直循環(huán)到最后一個(gè)節(jié)點(diǎn),current就像一個(gè)指針,每打印一個(gè)節(jié)點(diǎn),就把當(dāng)前節(jié)點(diǎn)設(shè)置為下一個(gè)節(jié)點(diǎn),一直循環(huán)下去。

EmptyListException用來(lái)拋出鏈表為空的異常。

namespace LinkedListLibrary
{
    public class EmptyListException : Exception
    {
        public EmptyListException() : base("當(dāng)前集合為空"){}
        public EmptyListException(string name) : base("集合" + name + "為空"){}
        public EmptyListException(string exception, Exception inner) : base(exception, inner){}
    }
}

客戶端調(diào)用:

using LinkedListLibrary;
namespace ListTest
{
    class Program
    {
        static void Main(string[] args)
        {
            List list = new List();
            bool aBoolean = true;
            char aChar = 'a';
            int anInt = 12;
            string aStr = "hi";
            list.InsertAtFront(aBoolean);
            list.Display();
            list.InsertAtFront(aChar);
            list.Display();
            list.InsertAtBack(anInt);
            list.Display();
            list.InsertAtBack(aStr);
            list.Display();
            object removeObject;
            try
            {
                removeObject = list.RemoveFromFront();
                Console.WriteLine(removeObject + "被刪除了...");
                list.Display();
                removeObject = list.RemoveFromFront();
                Console.WriteLine(removeObject + "被刪除了...");
                list.Display();
                removeObject = list.RemoveFromBack();
                Console.WriteLine(removeObject + "被刪除了...");
                list.Display();
                removeObject = list.RemoveFromBack();
                Console.WriteLine(removeObject + "被刪除了...");
                list.Display();
            }
            catch (EmptyListException emptyListException)
            {
                Console.Error.WriteLine("\n" + emptyListException);
            }
            Console.ReadKey();
        }
    }
}

其它鏈表

以上,創(chuàng)建的是單向鏈表,其特點(diǎn)是第一個(gè)節(jié)點(diǎn)開(kāi)始包含引用鏈,每個(gè)節(jié)點(diǎn)的引用鏈指向下一個(gè)節(jié)點(diǎn),最后一個(gè)節(jié)點(diǎn)的引用鏈為null。單向鏈表只能從一個(gè)方向遍歷。

環(huán)形單向鏈表與單向鏈表的區(qū)別是:其最后一個(gè)節(jié)點(diǎn)的引用鏈指向第一個(gè)節(jié)點(diǎn)。環(huán)形單向鏈表也只能從一個(gè)方向遍歷,只不過(guò)遍歷到最后一個(gè)節(jié)點(diǎn)后,又回到第一個(gè)節(jié)點(diǎn)重新開(kāi)始遍歷。

雙向鏈表的第一個(gè)節(jié)點(diǎn)只包含指向下一個(gè)節(jié)點(diǎn)的引用鏈,最后一個(gè)節(jié)點(diǎn)只包含指向上一個(gè)節(jié)點(diǎn)的引用鏈,其它節(jié)點(diǎn)同時(shí)包含指向前一個(gè)節(jié)點(diǎn)和后一個(gè)節(jié)點(diǎn)的引用鏈。雙向鏈表支持向前和向后遍歷。

環(huán)形雙向鏈表與雙向鏈表的區(qū)別是:第一個(gè)節(jié)點(diǎn)向后引用鏈指向最后一個(gè)節(jié)點(diǎn),而最后一個(gè)節(jié)點(diǎn)的向前引用鏈指向第一個(gè)節(jié)點(diǎn)。

以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,謝謝大家對(duì)腳本之家的支持。如果你想了解更多相關(guān)內(nèi)容請(qǐng)查看下面相關(guān)鏈接

相關(guān)文章

  • c#防止多次運(yùn)行代碼收集分享

    c#防止多次運(yùn)行代碼收集分享

    原文:經(jīng)過(guò)我的測(cè)試,還比較好用,但是有個(gè)問(wèn)題,如果不注銷,用另一個(gè)用戶進(jìn)入,則程序不能判斷出已運(yùn)行。所以只限于用在單用戶環(huán)境,還是不太完美
    2013-09-09
  • C# SendMail發(fā)送郵件功能實(shí)現(xiàn)

    C# SendMail發(fā)送郵件功能實(shí)現(xiàn)

    這篇文章主要為大家詳細(xì)介紹了C# SendMail發(fā)送郵件功能實(shí)現(xiàn),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-06-06
  • C# 中使用正則表達(dá)式匹配字符的含義

    C# 中使用正則表達(dá)式匹配字符的含義

    正則表達(dá)式的作用用來(lái)描述字符串的特征。本文重點(diǎn)給大家介紹C# 中使用正則表達(dá)式匹配字符的含義,非常不錯(cuò),具有一定的參考借鑒價(jià)值,需要的朋友參考下吧
    2018-10-10
  • C#獲取ListView鼠標(biāo)下的Item實(shí)例

    C#獲取ListView鼠標(biāo)下的Item實(shí)例

    下面小編就為大家?guī)?lái)一篇C#獲取ListView鼠標(biāo)下的Item實(shí)例。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-01-01
  • C#/VB.NET中從?PDF?文檔中提取所有表格

    C#/VB.NET中從?PDF?文檔中提取所有表格

    這篇文章主要介紹了C#/VB.NET中從PDF文檔中提取所有表格,文章圍繞主題展開(kāi)詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的小伙伴可以參考一下
    2022-08-08
  • C#啟動(dòng)和停止windows服務(wù)的實(shí)例代碼

    C#啟動(dòng)和停止windows服務(wù)的實(shí)例代碼

    這篇文章介紹了C#啟動(dòng)和停止windows服務(wù)的實(shí)例代碼,有需要的朋友可以參考一下
    2013-09-09
  • 使用c#在word文檔中創(chuàng)建表格的方法詳解

    使用c#在word文檔中創(chuàng)建表格的方法詳解

    本篇文章是對(duì)使用c#在word文檔中創(chuàng)建表格的方法進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下
    2013-05-05
  • C#異步調(diào)用實(shí)例小結(jié)

    C#異步調(diào)用實(shí)例小結(jié)

    這篇文章主要介紹了C#異步調(diào)用的方法,實(shí)例分析了C#同步調(diào)用及異步調(diào)用的常用技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下
    2015-08-08
  • C#中文隨機(jī)數(shù)實(shí)現(xiàn)方法

    C#中文隨機(jī)數(shù)實(shí)現(xiàn)方法

    這篇文章主要介紹了C#中文隨機(jī)數(shù)實(shí)現(xiàn)方法,涉及C#針對(duì)中文及隨機(jī)數(shù)的相關(guān)操作技巧,需要的朋友可以參考下
    2015-06-06
  • C#中常量和只讀變量的區(qū)別小結(jié)

    C#中常量和只讀變量的區(qū)別小結(jié)

    本篇文章主要是對(duì)C#中常量和只讀變量的區(qū)別進(jìn)行了詳細(xì)的介紹,需要的朋友可以過(guò)來(lái)參考下,希望對(duì)大家有所幫助
    2014-01-01

最新評(píng)論