一个C#链表实例
链表,主要是"链"每个类中,都包含一个指向后一个节点的指针
csharp
class ListNode
{
public string Name { get; set; }
public ListNode Next;
public ListNode(string name)
{
this.Name = name;
this.Next = null;
}
}
基本练成链子,对于插入,仅仅是对应节点的Next
赋值,但要注意,保存头结点指针。
csharp
ListNode Head = new ListNode("Mr.Green");
Head.Next = new ListNode("Mr.Black");
Head.Next.Next = new ListNode("Mrs. Blue");
PrintList(Head,"构建的基础链表为:");
ListNode IHead = new ListNode("Mr.Brown");
IHead.Next = Head;
Head = IHead;
PrintList(Head, "向链表L表头插入一个单元后构建的基础链表为:");
ListNode list1 = Head;
while (list1.Next != null)
{
list1 = list1.Next;
}
list1.Next = new ListNode("Ms.White");
PrintList(Head, "向链表L表尾插入一个单元后构建的基础链表为:");
ListNode insertPos = Head;
while (insertPos.Next != null && insertPos.Next.Name != "Mr.Black")
{
insertPos = insertPos.Next;
}
insertPos.Next = new ListNode("Dr.Martin");
PrintList(Head, "向链表L表中Mr.Black前插入一个单元后构建的基础链表为:");
排序算法,冒泡算法这里可以使用,但不推荐,这里使用归并排序,也是本文章记录的核心内容。
排序分为三部分,找终点、拆两半、合并
csharp
static ListNode SortList(ListNode head)
{
if (head == null || head.Next == null) return head;
// 当链表只有一个节点时,无需再分割和排序
if (head.Next == null)
{
return head;
}
// 获取链表中间节点
ListNode middle = GetMiddle(head);
ListNode nextToMiddle = middle.Next;
middle.Next = null;
// 分别对左半部分和右半部分链表进行递归排序
ListNode left = SortList(head);
ListNode right = SortList(nextToMiddle);
// 合并两个已排序的子链表
return Merge(left, right);
}
static ListNode GetMiddle(ListNode head)
{
if (head == null || head.Next == null)
{
return head;
}
ListNode slow = head, fast = head;
// 当链表长度为奇数时,fast会先到达终点,slow会停留在中间节点
while (fast != null && fast.Next != null && fast.Next.Next != null)
{
slow = slow.Next;
fast = fast.Next.Next;
}
return slow;
}
static ListNode Merge(ListNode left, ListNode right)
{
if (right == null)
{
return left;
}
if (left == null)
{
return right;
}
// 根据节点值进行合并,选择较小的节点放在前面
if (left.Name.CompareTo(right.Name) <= 0)
{
// 将左节点链接到左节点的下一个节点与右节点合并的结果
left.Next = Merge(left.Next, right);
// 返回当前较小节点作为合并后的新链表的当前节点
return left;
}
else
{
// 将右节点链接到左节点与右节点的下一个节点合并的结果
right.Next = Merge(left, right.Next);
// 返回当前较小节点(此处可能是右节点)作为合并后的新链表的当前节点
return right;
}
}
其中,找终点算法是一种 快慢找终点,但要注意奇偶问题,否则在递归中会溢出。