C#单向链表的实现

C#数据结构——单向链表的实现

单向链表的简单说明:链表是一种特殊的数据结构,能够动态的存储一种结构类型数据。在开发复杂的系统时,经常会使用链表存储数据。在本实例中,笔者设计了一个单向链表,并将其编译为类库,以供大家在以后的开发中使用。

关键技术

链表是一种重要的数据结构,该结构由节点组成。每个节点包含两部分数据,第一部分是节点本身的数据,第二部分是指向下一个节点的指针。对于单向链表,链表中存在两个特殊的节点,分别为“头节点”和“尾节点”。头节点本身没有数据,只存储下一个节点的指针,尾节点只存储数据。单向链表结构如图1所示。
这里写图片描述

本例中为了描述节点,笔者设计了一个节点类,代码如下:

public class ListNode   // 结点类
{
     public ListNode(int NewValue)
     {
        Value=NewValue;
     }
     public ListNode Previous;      //前一个
     public ListNode Next;      //后一个
     public int Value;              //值
}

其中,私有成员Value用于储存节点本身的数据,Next用于存储下一个节点的指针,Previous用于存储上一个节点的指针。对于链表的操作,无非是进行节点的查找、插入和删除操作。
(1)查找节点
在进行节点查找时,通常根据节点的数据查找节点。要实现节点的查找,首先需要解决的问题就是遍历链表中的所有节点。可以从链表头节点开始,利用循环的方式向下查找,如果当前节点指向的下一个节点不为空,则将下一个节点设置为当前节点。
(2)插入节点
插入节点需要考虑两种情况。第一种情况是在链表尾节点处插入节点,这种情况比较简单,只要将当前尾节点的FNextNode(指向下一个节点的指针)指向新插入的节点就可以了。第二种情况是在链表的中间位置插入节点,首先需要确定在哪个节点后插入新的节点,这就应该由用户来确定了,本例中为了演示的需要,笔者将树视图控件中的当前选项设置为当前节点。然后需要记录当前节点的下一个节点(避免发生“脱节”),可以定义一个临时的节点进行记录。将当前节点的下一个节点指向新添加的节点,再将新添加节点的下一个节点指向临时节点,整个插入节点的流程如图2所示。
这里写图片描述
(3)删除节点
删除节点与插入节点类似,也需要考虑两种情况。第一种情况是删除尾节点,这种情况操作相对比较简单,首先找到尾节点之前的一个节点,将该节点指向的下一个节点设置为空,然后释放尾节点资源。第二种情况是删除链表中间部分的节点。首先需要找到当前节点的上一个节点,并定义一个临时节点PriorNode进行记录,然后再定义一个临时节点TempNode记录当前节点的下一个节点,最后将PriorNode的下一个节点指向TempNode,并释放当前节点,整个流程如图3所示。
这里写图片描述

设计过程

(1)打开VisualStudio开发环境,新建一个类库项目,命名为UnilateralismChainTable。
(2)将“Class1.cs”文件重命名为“Clist.cs”。
(3)程序主要代码如下:
在构造函数中初始化,并定义指针变量。代码如下:

//构造函数
public Clist()
{
    ListCountValue = 0;//初始化
    Head = null;
    Tail = null;
}
private ListNode Head;//头指针
private ListNode Tail;//尾指针
private ListNode Current;//当前指针
private int ListCountValue;//链表数据的个数

尾部添加数据的代码如下:

public void Append(int DataValue)
{
    ListNode NewNode = new ListNode(DataValue);
    if (IsNull())//如果头指针为空
    {
        Head = NewNode;
        Tail = NewNode;
    }
    else
    {
        Tail.Next = NewNode;
        NewNode.Previous = Tail;
        Tail = NewNode;
    }
    Current = NewNode;
    ListCountValue += 1;//链表数据个数加一
}

删除当前的数据的代码如下:

public void Delete()
{
    if (!IsNull())//若为空链表
    {
        if (IsBof())//若删除头
        {
            Head = Current.Next;
            Current = Head;
            ListCountValue -= 1;
            return;
        }
        if (IsEof())//若删除尾
        {
            Tail = Current.Previous;
            Current = Tail;
            ListCountValue -= 1;
            return;
        }
        Current.Previous.Next = Current.Next;//若删除中间数据
        Current = Current.Previous;
        ListCountValue -= 1;
        return;
    }
}

移动数据的代码如下:

{
    if (!IsEof()) Current = Current.Next;//向后移动一个数据
}
public void MovePrevious()
{
    if (!IsBof()) Current = Current.Previous;//向前移动一个数据
}
public void MoveFrist()
{
    Current = Head;//移动到第一个数据
}
public void MoveLast()
{
    Current = Tail;//移动到最后一个数据
}
public bool IsNull()
{
    if (ListCountValue == 0)//判断是否为空链表
        return true;
    return false;
}
public bool IsEof()
{
    if (Current == Tail)//判断是否为到达尾
        return true;
    return false;
}
public bool IsBof()
{
    if (Current == Head)//判断是否为到达头部
        return true;
    return false;
}
public int GetCurrentValue()
{
    return Current.Value;//获取节点值
}
public int ListCount
{
    get
    {
        return ListCountValue;//取得链表的数据个数
    }
}
//清空链表
public void Clear()
{
    MoveFrist();
    while (!IsNull())
    {
        Delete();//若不为空链表,从尾部删除
    }
}

在当前位置前插入数据的代码如下:

public void Insert(int DataValue)
{
    ListNode NewNode = new ListNode(DataValue);
    if (IsNull())
    {
        Append(DataValue);//如果为空表,则添加
        return;
    }
    if (IsBof())
    {
        //为头部插入
        NewNode.Next = Head;
        Head.Previous = NewNode;
        Head = NewNode;
        Current = Head;
        ListCountValue += 1;
        return;
    }
    //中间插入
    NewNode.Next = Current;
    NewNode.Previous = Current.Previous;
    Current.Previous.Next = NewNode;
    Current.Previous = NewNode;
    Current = NewNode;
    ListCountValue += 1;
}

升序插入的代码如下:

public void InsertAscending(int InsertValue)
{
    //参数:InsertValue 插入的数据
    if (IsNull())//为空链表
    {
        Append(InsertValue);//添加
        return;
    }
    MoveFrist();//移动到头
    if ((InsertValue < GetCurrentValue()))
    {
        Insert(InsertValue);//满足条件,则插入,退出
        return;
    }
    while (true)
    {
        if (InsertValue < GetCurrentValue())
        {
            Insert(InsertValue);//满足条件,则插入,退出
            break;
        }
        if (IsEof())
        {
            Append(InsertValue);//尾部添加
            break;
        }
        MoveNext();//移动到下一个指针
    }
}

降序插入的代码如下:

public void InsertUnAscending(int InsertValue)
{
    //参数:InsertValue 插入的数据
    if (IsNull())//为空链表
    {
        Append(InsertValue);//添加
        return;
    }
    MoveFrist();//移动到头
    if (InsertValue > GetCurrentValue())
    {
        Insert(InsertValue);//满足条件,则插入,退出
        return;
    }
    while (true)
    {
        if (InsertValue > GetCurrentValue())
        {
            Insert(InsertValue);//满足条件,则插入,退出
            break;
        }
        if (IsEof())
        {
            Append(InsertValue);//尾部添加
            break;
        }
        MoveNext();//移动到下一个指针
    }
}

技巧心得

算法的概念:算法是解决问题的方法和步骤,它实际上就是用自然语言或其他方式描述的一个计算机程序,编写计算机程序也就是把用某种方式描述的算法,通过程序设计语言重新对其进行描述。

  • 15
    点赞
  • 91
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

洋洋脚踝的金铃响了

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值