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 集合遍历时删除或增加元素
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private LinkedList<int> list = new LinkedList<int>();
//初始化,添加0-29的整数进入链表
private void button1_Click(object sender, EventArgs e)
{
for (int i = 0; i < 30; i++)
{
this.list.AddLast(i);
}
}
//遍历链表,做如下操作:
//遇到能被3整除的,就在该链表后增加一个0元素,遇到能被2整除的就删除该元素
private void button2_Click(object sender, EventArgs e)
{
LinkedListNode<int> nodeNow = this.list.First;//链表第一个元素
LinkedListNode<int> nodeLast = this.list.Last;//原链表的最后一个元素,循环结束的标记
LinkedListNode<int> nodeTmp;//临时结点
//循环结束的条件是,等当前结点是原链表的最后一个结点
while (nodeNow != nodeLast)
{
//如果能被3整除时,则在链表后加一个0
if (nodeNow.Value % 3 == 0)
{
this.list.AddLast(0);
}
//如果能被2整除,则删除该元素
if (nodeNow.Value % 2 == 0)
{
//如果nodeNow被删除了,那么一定不能用Next获取下一个要判断的元素
//因为已经自动向下一个移动了,这是就要在删除nodeNow之前,
//获取它的Next,赋给nodeTmp,待nodeNow删除之后,再把nodeTmp的内存赋给nodeNow
nodeTmp = nodeNow.Next;
this.list.Remove(nodeNow);
nodeNow = nodeTmp;
}
else
{
//如果不能被2整除,则在链表中保留该元素,并获得下一个并进行判断
nodeNow = nodeNow.Next;
}
}
//最后不要忘记对nodeLast(原链表最后一个元素)本身进行处理,上面的while循环没有包括这个nodeLast
if (nodeNow.Value % 3 == 0)
{
this.list.AddLast(0);
}
if (nodeNow.Value % 2 == 0)
{
this.list.Remove(nodeNow);
}
}
//测试结果
private void button3_Click(object sender, EventArgs e)
{
foreach (int i in this.list)
{
Console.WriteLine(i);
}
}
}
}
第二种方法:使用C#的List<>,List<>是基于数组的顺序表,增加、删除动作时间复杂度较高,不如链表的效率高。其基本原来同第一种方法相似,也需要使用一个int型的变量标记原顺序表的尾部元素,当删除一个元素时,这个变量需要自减。代码略。
第三种方法,自定义单链表泛型类(链表类见http://www.easck.com/article/87610.htm)。跟第一种方法比的好处,就是能够灵活实现两个链表的合并,只需要把第二个链表的头结点设置成第一个链表的尾结点的Next的结点(或直接Add)就可以了。其实对于C#的双链表,我并不是很清楚,为什么AddLast()方法,无法将一个链表的元素添加到另一个链表中,而只能添加一个不属于任何链表的结点(有人说第一种方法,其实可以使用结点Clone,但是这样无非还是增加算法的空间和时间复杂度,违背了使用链表的本意)。C#之所以不支持这种做法的原因可能是,MS担心你加入的结点,位于一个环状链表上,这样会导致原链表的Last属性、Count属性等无法计算(形成死循环)。测试代码如下:










