目录
一、涉及到的知识点
1.插入算法
2.示例中current 和 _current 的作用
3.current 和 _current 能否合并为一个变量
4.单向链表节点类的三个属性
(1)Next属性:
(2) Value属性:
(3)Previous属性:
二、Insert()方法实例
一、涉及到的知识点
1.插入算法
在单向链表的当前位置插入一个新的节点,在插入新节点之前,需要找到当前节点。如果当前节点为空,需要找到链表的最后一个节点,然后将最后一个节点设置为当前节点。这样,新节点就可以插入到链表的末尾。
· 在插入新节点时,需要正确设置新节点的 Next 和 Previous 属性。设置新节点的 Next 和 Previous 属性具体如下:
newNode.Next = current.Next;
newNode.Previous = current;
current.Next = newNode;
_current = newNode;
这样设置确保了新节点被正确地插入到链表中,并且链表的其他部分也得到正确更新。
2.示例中current 和 _current 的作用
在实例程序中,current 和 _current 的作用是有区别的。它们主要用于在插入新节点时跟踪链表中的当前节点。让我来解释一下它们各自的用途:
- current:是一个临时变量,用于在插入新节点之前找到链表中的当前节点。如果链表不为空,它会从链表头节点开始遍历,直到找到最后一个节点。在这个过程中,current 会被不断更新为当前节点的下一个节点。最后,current 会被设置为最后一个节点。
- _current:是一个静态变量,用于在整个链表操作过程中跟踪当前节点。在插入新节点时,_current 会被设置为新插入的节点。这样,在后续的操作中,可以使用 _current 来访问链表中的当前节点。
3.current 和 _current 能否合并为一个变量
在源程序中将 current 和 _current 可以合并为一个变量。但是,将它们分开好处更多:
- 代码的可读性:使用两个不同的变量名可以更清楚地表明它们在代码中的不同作用。使用 _current 作为静态变量可以清楚地表明它在整个链表操作过程中的作用,而使用 current 作为局部变量可以清楚地表明它在插入新节点过程中的作用。
- 代码的简洁性:将它们分开可以使代码更简洁。如果将它们合并为一个变量,那么在插入新节点之前需要不断地更新这个变量。而将它们分开,只需要在找到最后一个节点后,将 _current 设置为 current,就可以完成链表的插入操作。
总之,虽然可以将 current 和 _current 统一为一个变量,但将它们分开可以使代码更易读、更简洁。
4.单向链表节点类的三个属性
在C#中,单向链表节点(通常称为节点或列表节点)通常使用一个公共类来表示,该类具有三个主要属性:
(1)Next属性:
此属性表示链表中当前节点的下一个节点。在单向链表中,只能从头节点开始向前遍历节点,因此每个节点仅需维护一个指向其后继节点的引用。Next属性通常是一个指向ListNode类型对象的引用。在链表的末尾,Next属性将为null。
public class ListNode
{public int Value { get; set; }public ListNode Next { get; set; }public ListNode(int value){Value = value;}
}
或
public class ListNode(int value)
{public int Value { get; set; } = value;public ListNode? Next { get; set; } = null;public ListNode? Previous { get; set; } = null;
}
(2) Value属性:
此属性表示当前节点所存储的值。在链表中,每个节点都存储一个值,该值可以是任何类型,如int、double、string等。Value属性通常是一个泛型类型T,以便在不同类型的链表中重用相同的节点类。
public class ListNode<T>
{public T Value { get; set; }public ListNode<T> Next { get; set; }public ListNode(T value){Value = value;}
}
或
public class ListNode<T>(T value){public T Value { get; set; } = value;public ListNode<T>? Next { get; set; }}
(3)Previous属性:
在某些情况下,需要使用双向链表,即每个节点不仅维护一个指向其后继节点的引用,还维护一个指向其前驱节点的引用。在这种情况下,Previous属性表示链表中当前节点的前一个节点。Previous属性通常是一个指向ListNode类型对象的引用。在链表的头部,Previous属性将为null。
public class ListNode<T>
{ public T Value { get; set; } public ListNode<T> Next { get; set; } public ListNode<T> Previous { get; set; }public ListNode(T value) { Value = value; }
}
二、Insert()方法实例
// 单向链表在当前位置插入新数据的方法
namespace _131_10
{public class ListNode(int value){public int Value { get; set; } = value;public ListNode? Next { get; set; } = null;public ListNode? Previous { get; set; } = null;}public class LinkedList{private static ListNode? _head;private static ListNode? _current;public LinkedList() => _head = null;/// <summary>/// 在当前位置插入数据,/// 不对数据排序,也不比较数据/// </summary>public static void Insert(int value){// 创建一个新的节点var newNode = new ListNode(value);// 如果链表为空,将新节点设置为头节点if (_head == null){_head = newNode;_current = newNode;return;}// 找到当前节点var current = _current;if (current == null){//current = _head;_current = _head;while (_current.Next != null){_current = _current.Next;}current = _current;}// 在当前位置插入新节点newNode.Next = current.Next;newNode.Previous = current;current.Next = newNode;_current = newNode;}public static void Display(){var current = _head;while (current != null){Console.Write(current.Value + " ");current = current.Next;}Console.WriteLine();}class Program{static void Main(string[] args){ArgumentNullException.ThrowIfNull(args);// 链表数据初始化_head = new(5){Next = new ListNode(2)};_head.Next.Next = new ListNode(8){Next = new ListNode(1)};Display();Console.WriteLine("**初始数据**");_current = _head.Next.Next; //设置当前节点为第三个节点(值为8)Insert(9); //在当前位置插入数据9Display(); Console.WriteLine("**插入9**");}}}
}
//运行结果:
/*
5 2 8 1
**初始数据**
5 2 8 9 1
**插入9***/