您好,登錄后才能下訂單哦!
這篇文章主要介紹了C#集合本質之鏈表怎么使用的相關知識,內容詳細易懂,操作簡單快捷,具有一定借鑒價值,相信大家閱讀完這篇C#集合本質之鏈表怎么使用文章都會有所收獲,下面我們一起來看看吧。
在現實生活中,我們把不同的商品放在一個購物車中。而在面向對象的世界里,有時候,也需要把不同類型的數據放到一起,組成一個集合。集合中的元素并不是彼此孤立的,在C#中,如何表達集合元素間的關系呢?
借助"自引用類"可以確立集合元素間的關系。比如有這樣一個自引用類:
public class Node { public int Data{get;set;} public Node Next{get;set;} public Node(int dataValue) {} }
Node類的最大特點是:存在一個Node類型的屬性,這個屬性指向Node的另一個實例,Next屬性也稱為"引用鏈"。放到集合的場景中來說就是:把多個Node實例放到一個集合中,每一個Node實例包含一個Next屬性指向下一個Node實例。而該集合中的最后一個Node實例會指向null。用圖表示就是:
鏈表就是自引用類對象的線性集合,即序列。
由于每個自引用對象是由引用鏈鏈接起來,所以叫鏈表。堆棧與隊列是約束版的鏈表,而二叉查找數是非線性數據結構。
鏈表的節點或元素雖然在邏輯上是連續的、線性的,當其內存不是連續存儲的;數組元素在內存中是連續的,所以我們才可以通過索引來訪問數組元素。
首先創建一個節點,是一個自引用類:
namespace LinkedListLibrary { public class ListNode { //當前節點對象 public object Data { get; private set; } //Next屬性也稱為鏈,指向另一個ListNode對象實例,這樣就把2個ListNode對象實例鏈接起來了 public ListNode Next { get; set; } public ListNode(object dataValue): this(dataValue, null) { } public ListNode(object dataValue, ListNode nextNode) { Data = dataValue; Next = nextNode; } } }
再模擬一個鏈表,如下:
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"){} ...... //如果第一個節點是null,那就說明集合為空 public bool IsEmpty() { return firstNode == null; } } }
以上,如果第一個節點為null,那就說明該鏈表為空。List類提供了IsEmpty方法用來判斷鏈表是否為空。List還包含另外5個重要的方法,下面展開來說。
在鏈表的的第一個節點前插入。
//在最前面插入元素、節點 public void InsertAtFront(object insertItem) { if (IsEmpty())//如果集合為空,加進來一個元素,相當于第一個節點和第二個節點相同,都是新加的元素 { firstNode = lastNode = new ListNode(insertItem); } else //如果集合不為空,第一個節點就是新加的元素,原先的第一個節點變為下一個節點 { firstNode = new ListNode(insertItem, firstNode); } }
以上,當集合不為空的情況下,實際上是把新添加的節點設為第一個節點,并把新的第一個節點的引用鏈指向原先的第一個節點。
在鏈表的最后一個節點后插入。
public void InsertAtBack(object insertItem) { if (IsEmpty())//如果原先集合為空,第一個節點和最后一個節點就是新加的節點 { firstNode = lastNode = new ListNode(insertItem); } else//如果原先的集合不為空,最后一個節點的屬性值就是新加的節點 { lastNode = lastNode.Next = new ListNode(insertItem); } }
以上,當集合不為空的情況下,實際上是把新添加的節點設置成最后一個節點,并把新的最后一個節點的引用鏈指向null。
移除鏈表最前面的節點。
//移除最前面的元素、節點 //即重新設置第一個節點的Next屬性 public object RemoveFromFront() { if (IsEmpty()) throw new EmptyListException(name); //從第一個節點中取出節點對象 object removeItem = firstNode.Data; if (firstNode == lastNode) //如果集合中只有一個元素 { firstNode = lastNode = null; } else //正常情況下,把firstNode的Next屬性所指向的節點賦值給第一個節點 { firstNode = firstNode.Next; } return removeItem; }
以上,本質是把原先排在第二位置的節點設置成第一個節點。
移除鏈表最后面的節點。
//移除最后面的元素、節點 public object RemoveFromBack() { if (IsEmpty()) { throw new EmptyListException(); } //從最后一個節點中獲取節點對象 object removeItem = lastNode.Data; if (firstNode == lastNode)//如果當前集合只有一個節點 { firstNode = lastNode = null; } else { //先把第一個節點作為當前節點 ListNode current = firstNode; //改變除最后一個節點之外的節點的值 while (current.Next != lastNode) { current = current.Next; } //最后current變成倒數第二個節點 lastNode = current; current.Next = null;//最后一個節點的Next屬性為null,即沒有指向另一個節點 } return removeItem; }
以上,從第一個節點開始,一直循環到倒數第二個節點,current就像一個指針,每指到一個節點,就把該節點的下面一個節點設置為當前節點。最后,把倒數第二個節點設置為最后一個節點。 把Current的引用鏈設置為null,讓其能被垃圾回收機制回收。
打印鏈表。
//打印顯示 public void Display() { if (IsEmpty()) { Console.WriteLine("集合" + name + "為空"); } else { Console.WriteLine("集合的名稱是:" + name); //先把第一個節點作為當前節點 ListNode current = firstNode; while (current != null) { //把當前節點對象打印出來 Console.Write(current.Data + " "); //把下一個節點設置為當前節點 current = current.Next; } Console.WriteLine("\n"); } }
以上,從第一個節點開始,一直循環到最后一個節點,current就像一個指針,每打印一個節點,就把當前節點設置為下一個節點,一直循環下去。
EmptyListException用來拋出鏈表為空的異常。
namespace LinkedListLibrary { public class EmptyListException : Exception { public EmptyListException() : base("當前集合為空"){} public EmptyListException(string name) : base("集合" + name + "為空"){} public EmptyListException(string exception, Exception inner) : base(exception, inner){} } }
客戶端調用:
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(); } } }
以上,創建的是單向鏈表,其特點是第一個節點開始包含引用鏈,每個節點的引用鏈指向下一個節點,最后一個節點的引用鏈為null。單向鏈表只能從一個方向遍歷。
環形單向鏈表與單向鏈表的區別是:其最后一個節點的引用鏈指向第一個節點。環形單向鏈表也只能從一個方向遍歷,只不過遍歷到最后一個節點后,又回到第一個節點重新開始遍歷。
雙向鏈表的第一個節點只包含指向下一個節點的引用鏈,最后一個節點只包含指向上一個節點的引用鏈,其它節點同時包含指向前一個節點和后一個節點的引用鏈。雙向鏈表支持向前和向后遍歷。
環形雙向鏈表與雙向鏈表的區別是:第一個節點向后引用鏈指向最后一個節點,而最后一個節點的向前引用鏈指向第一個節點。
關于“C#集合本質之鏈表怎么使用”這篇文章的內容就介紹到這里,感謝各位的閱讀!相信大家對“C#集合本質之鏈表怎么使用”知識都有一定的了解,大家如果還想學習更多知識,歡迎關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。