C#集合遍歷時(shí)刪除和增加元素的方法
本文實(shí)例講述了C#集合遍歷時(shí)刪除和增加元素的方法。分享給大家供大家參考,具體如下:
大多數(shù)時(shí)候,遍歷集合元素的時(shí)候并不需要對(duì)元素進(jìn)行增加或者刪除操作,但有些時(shí)候則需要,比如,如果集合中盛放的元素是社會(huì)上所有的人,那么有人死亡則元素刪除,有人出生則是集合元素的增加。對(duì)于這種情況,遍歷不能按照原來(lái)那種方式去做了,而且C#中的集合對(duì)于這類有增刪動(dòng)作的遍歷,也不支持foreach循環(huán)。
有三種辦法可以解決這一問(wèn)題。
第一種方法:使用C#的LinkedList<>雙鏈表。我原來(lái)設(shè)想,把原來(lái)鏈表需要?jiǎng)h除的元素直接remove掉,那些新添加的元素,先裝入到一個(gè)臨時(shí)鏈表中,等循環(huán)結(jié)束,再用Add把臨時(shí)鏈表的頭結(jié)點(diǎn)添加到原來(lái)鏈表的尾部即可,這樣算法的復(fù)雜度也較低,但是,出乎意料的是,C#的雙鏈表,無(wú)法將屬于另外一個(gè)鏈表的結(jié)點(diǎn)添加到本鏈表中,其Next屬性也只讀。無(wú)奈,只能一邊循環(huán),一邊在原鏈表尾端添加結(jié)點(diǎn),這樣就需要標(biāo)記處循環(huán)結(jié)束的位置,即需要在原來(lái)的未改動(dòng)的鏈表的尾部結(jié)點(diǎn)處結(jié)束循環(huán),而不是在改動(dòng)后的鏈表的尾部結(jié)點(diǎn)處結(jié)束。這樣就要求在循環(huán)開始之前,先獲得尾部結(jié)點(diǎn)的引用。程序如下(鏈表中有0-29的整數(shù)值結(jié)點(diǎn),遍歷時(shí)遇到3的整數(shù)倍,就在鏈表尾端添加一個(gè)0值結(jié)點(diǎn),遇到2的整數(shù)倍就刪除結(jié)點(diǎn))
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; namespace 集合遍歷時(shí)刪除或增加元素 { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private LinkedList<int> list = new LinkedList<int>(); //初始化,添加0-29的整數(shù)進(jìn)入鏈表 private void button1_Click(object sender, EventArgs e) { for (int i = 0; i < 30; i++) { this.list.AddLast(i); } } //遍歷鏈表,做如下操作: //遇到能被3整除的,就在該鏈表后增加一個(gè)0元素,遇到能被2整除的就刪除該元素 private void button2_Click(object sender, EventArgs e) { LinkedListNode<int> nodeNow = this.list.First;//鏈表第一個(gè)元素 LinkedListNode<int> nodeLast = this.list.Last;//原鏈表的最后一個(gè)元素,循環(huán)結(jié)束的標(biāo)記 LinkedListNode<int> nodeTmp;//臨時(shí)結(jié)點(diǎn) //循環(huán)結(jié)束的條件是,等當(dāng)前結(jié)點(diǎn)是原鏈表的最后一個(gè)結(jié)點(diǎn) while (nodeNow != nodeLast) { //如果能被3整除時(shí),則在鏈表后加一個(gè)0 if (nodeNow.Value % 3 == 0) { this.list.AddLast(0); } //如果能被2整除,則刪除該元素 if (nodeNow.Value % 2 == 0) { //如果nodeNow被刪除了,那么一定不能用Next獲取下一個(gè)要判斷的元素 //因?yàn)橐呀?jīng)自動(dòng)向下一個(gè)移動(dòng)了,這是就要在刪除nodeNow之前, //獲取它的Next,賦給nodeTmp,待nodeNow刪除之后,再把nodeTmp的內(nèi)存賦給nodeNow nodeTmp = nodeNow.Next; this.list.Remove(nodeNow); nodeNow = nodeTmp; } else { //如果不能被2整除,則在鏈表中保留該元素,并獲得下一個(gè)并進(jìn)行判斷 nodeNow = nodeNow.Next; } } //最后不要忘記對(duì)nodeLast(原鏈表最后一個(gè)元素)本身進(jìn)行處理,上面的while循環(huán)沒(méi)有包括這個(gè)nodeLast if (nodeNow.Value % 3 == 0) { this.list.AddLast(0); } if (nodeNow.Value % 2 == 0) { this.list.Remove(nodeNow); } } //測(cè)試結(jié)果 private void button3_Click(object sender, EventArgs e) { foreach (int i in this.list) { Console.WriteLine(i); } } } }
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; namespace 集合遍歷時(shí)刪除或增加元素 { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private LinkedList<int> list = new LinkedList<int>(); //初始化,添加0-29的整數(shù)進(jìn)入鏈表 private void button1_Click(object sender, EventArgs e) { for (int i = 0; i < 30; i++) { this.list.AddLast(i); } } //遍歷鏈表,做如下操作: //遇到能被3整除的,就在該鏈表后增加一個(gè)0元素,遇到能被2整除的就刪除該元素 private void button2_Click(object sender, EventArgs e) { LinkedListNode<int> nodeNow = this.list.First;//鏈表第一個(gè)元素 LinkedListNode<int> nodeLast = this.list.Last;//原鏈表的最后一個(gè)元素,循環(huán)結(jié)束的標(biāo)記 LinkedListNode<int> nodeTmp;//臨時(shí)結(jié)點(diǎn) //循環(huán)結(jié)束的條件是,等當(dāng)前結(jié)點(diǎn)是原鏈表的最后一個(gè)結(jié)點(diǎn) while (nodeNow != nodeLast) { //如果能被3整除時(shí),則在鏈表后加一個(gè)0 if (nodeNow.Value % 3 == 0) { this.list.AddLast(0); } //如果能被2整除,則刪除該元素 if (nodeNow.Value % 2 == 0) { //如果nodeNow被刪除了,那么一定不能用Next獲取下一個(gè)要判斷的元素 //因?yàn)橐呀?jīng)自動(dòng)向下一個(gè)移動(dòng)了,這是就要在刪除nodeNow之前, //獲取它的Next,賦給nodeTmp,待nodeNow刪除之后,再把nodeTmp的內(nèi)存賦給nodeNow nodeTmp = nodeNow.Next; this.list.Remove(nodeNow); nodeNow = nodeTmp; } else { //如果不能被2整除,則在鏈表中保留該元素,并獲得下一個(gè)并進(jìn)行判斷 nodeNow = nodeNow.Next; } } //最后不要忘記對(duì)nodeLast(原鏈表最后一個(gè)元素)本身進(jìn)行處理,上面的while循環(huán)沒(méi)有包括這個(gè)nodeLast if (nodeNow.Value % 3 == 0) { this.list.AddLast(0); } if (nodeNow.Value % 2 == 0) { this.list.Remove(nodeNow); } } //測(cè)試結(jié)果 private void button3_Click(object sender, EventArgs e) { foreach (int i in this.list) { Console.WriteLine(i); } } } }
第二種方法:使用C#的List<>,List<>是基于數(shù)組的順序表,增加、刪除動(dòng)作時(shí)間復(fù)雜度較高,不如鏈表的效率高。其基本原來(lái)同第一種方法相似,也需要使用一個(gè)int型的變量標(biāo)記原順序表的尾部元素,當(dāng)刪除一個(gè)元素時(shí),這個(gè)變量需要自減。代碼略。
第三種方法,自定義單鏈表泛型類(鏈表類見(jiàn)//www.jb51.net/article/87610.htm)。跟第一種方法比的好處,就是能夠靈活實(shí)現(xiàn)兩個(gè)鏈表的合并,只需要把第二個(gè)鏈表的頭結(jié)點(diǎn)設(shè)置成第一個(gè)鏈表的尾結(jié)點(diǎn)的Next的結(jié)點(diǎn)(或直接Add)就可以了。其實(shí)對(duì)于C#的雙鏈表,我并不是很清楚,為什么AddLast()方法,無(wú)法將一個(gè)鏈表的元素添加到另一個(gè)鏈表中,而只能添加一個(gè)不屬于任何鏈表的結(jié)點(diǎn)(有人說(shuō)第一種方法,其實(shí)可以使用結(jié)點(diǎn)Clone,但是這樣無(wú)非還是增加算法的空間和時(shí)間復(fù)雜度,違背了使用鏈表的本意)。C#之所以不支持這種做法的原因可能是,MS擔(dān)心你加入的結(jié)點(diǎn),位于一個(gè)環(huán)狀鏈表上,這樣會(huì)導(dǎo)致原鏈表的Last屬性、Count屬性等無(wú)法計(jì)算(形成死循環(huán))。測(cè)試代碼如下:
//兩個(gè)鏈表的合并 LinkedList<int> list = new LinkedList<int>(); for (int i = 0; i < 10; i++) { list.Add(i); } LinkedList<int> list2 = new LinkedList<int>(); for (int i = 10; i < 20; i++) { list2.Add(i); } list.Add(list2.Head); Node<int> n = list.Head; while(n!=null) { Console.WriteLine(n.Data); n = n.Next; } Console.ReadLine(); Console.WriteLine(list.GetLength()); Console.ReadLine(); //兩個(gè)鏈表的合并 LinkedList<int> list = new LinkedList<int>(); for (int i = 0; i < 10; i++) { list.Add(i); } LinkedList<int> list2 = new LinkedList<int>(); for (int i = 10; i < 20; i++) { list2.Add(i); } list.Add(list2.Head); Node<int> n = list.Head; while(n!=null) { Console.WriteLine(n.Data); n = n.Next; } Console.ReadLine(); Console.WriteLine(list.GetLength()); Console.ReadLine();
更多關(guān)于C#相關(guān)內(nèi)容感興趣的讀者可查看本站專題:《C#遍歷算法與技巧總結(jié)》、《C#程序設(shè)計(jì)之線程使用技巧總結(jié)》、《C#操作Excel技巧總結(jié)》、《C#中XML文件操作技巧匯總》、《C#常見(jiàn)控件用法教程》、《WinForm控件用法總結(jié)》、《C#數(shù)據(jù)結(jié)構(gòu)與算法教程》、《C#數(shù)組操作技巧總結(jié)》及《C#面向?qū)ο蟪绦蛟O(shè)計(jì)入門教程》
希望本文所述對(duì)大家C#程序設(shè)計(jì)有所幫助。
上一篇:C#操作SQLite數(shù)據(jù)庫(kù)方法小結(jié)(創(chuàng)建,連接,插入,查詢,刪除等)
欄 目:C#教程
下一篇:C#簡(jiǎn)單查詢SQLite數(shù)據(jù)庫(kù)是否存在數(shù)據(jù)的方法
本文標(biāo)題:C#集合遍歷時(shí)刪除和增加元素的方法
本文地址:http://mengdiqiu.com.cn/a1/C_jiaocheng/6384.html
您可能感興趣的文章
- 01-10C#操作IIS方法集合
- 01-10C#遍歷文件夾后上傳文件夾中所有文件錯(cuò)誤案例分析
- 01-10C#實(shí)現(xiàn)過(guò)濾sql特殊字符的方法集合
- 01-10C#中用foreach語(yǔ)句遍歷數(shù)組及將數(shù)組作為參數(shù)的用法
- 01-10詳解C#中使用對(duì)象或集合的初始值設(shè)定項(xiàng)初始化的操作
- 01-10C#常見(jiàn)的幾種集合 ArrayList,Hashtable,List&lt;T&gt;,
- 01-10C#中Dictionary泛型集合7種常見(jiàn)的用法
- 01-10C#中判斷一個(gè)集合是否是另一個(gè)集合的子集的簡(jiǎn)單方法
- 01-10C#后臺(tái)接受前臺(tái)JSON字符串裝換成字典集合處理
- 01-10C#如何遍歷Dictionary


閱讀排行
- 1C語(yǔ)言 while語(yǔ)句的用法詳解
- 2java 實(shí)現(xiàn)簡(jiǎn)單圣誕樹的示例代碼(圣誕
- 3利用C語(yǔ)言實(shí)現(xiàn)“百馬百擔(dān)”問(wèn)題方法
- 4C語(yǔ)言中計(jì)算正弦的相關(guān)函數(shù)總結(jié)
- 5c語(yǔ)言計(jì)算三角形面積代碼
- 6什么是 WSH(腳本宿主)的詳細(xì)解釋
- 7C++ 中隨機(jī)函數(shù)random函數(shù)的使用方法
- 8正則表達(dá)式匹配各種特殊字符
- 9C語(yǔ)言十進(jìn)制轉(zhuǎn)二進(jìn)制代碼實(shí)例
- 10C語(yǔ)言查找數(shù)組里數(shù)字重復(fù)次數(shù)的方法
本欄相關(guān)
- 01-10C#通過(guò)反射獲取當(dāng)前工程中所有窗體并
- 01-10關(guān)于ASP網(wǎng)頁(yè)無(wú)法打開的解決方案
- 01-10WinForm限制窗體不能移到屏幕外的方法
- 01-10WinForm繪制圓角的方法
- 01-10C#實(shí)現(xiàn)txt定位指定行完整實(shí)例
- 01-10WinForm實(shí)現(xiàn)仿視頻播放器左下角滾動(dòng)新
- 01-10C#停止線程的方法
- 01-10C#實(shí)現(xiàn)清空回收站的方法
- 01-10C#通過(guò)重寫Panel改變邊框顏色與寬度的
- 01-10C#實(shí)現(xiàn)讀取注冊(cè)表監(jiān)控當(dāng)前操作系統(tǒng)已
隨機(jī)閱讀
- 08-05dedecms(織夢(mèng))副欄目數(shù)量限制代碼修改
- 04-02jquery與jsp,用jquery
- 01-11ajax實(shí)現(xiàn)頁(yè)面的局部加載
- 01-11Mac OSX 打開原生自帶讀寫NTFS功能(圖文
- 01-10SublimeText編譯C開發(fā)環(huán)境設(shè)置
- 08-05織夢(mèng)dedecms什么時(shí)候用欄目交叉功能?
- 01-10delphi制作wav文件的方法
- 01-10C#中split用法實(shí)例總結(jié)
- 01-10使用C語(yǔ)言求解撲克牌的順子及n個(gè)骰子
- 08-05DEDE織夢(mèng)data目錄下的sessions文件夾有什