说明:C#有自己封装的双向循环链表LinkedList<>,足以满足日常工作需要。这里只是学习数据结构“单链表”的手搓代码,理解精神即可。
PS:这篇文章第一版写的有点烂,这是第二版,好看点。
PSS: 本文的重点是代码代码代码!而不是数据结构的一些基础概念和分类;
完全没接触过的同学,可以去看B站王卓教授的视频。
1.什么是链表?
- 用一组物理位置任意的存储单元来存放线性表的数据元素。
- 存储单元可以是连续的,也可以是不连续的,甚至是零散分布在内存中;
- 链表中元素的逻辑次序和物理次序不一定相同。(即内存靠前的不一定逻辑次序靠前)

说明:
- 如图,链表第一个元素是0031,即“赵”,赵的下一个是0007,即“钱”,钱的下一个是0013,即“孙”,依此类推。
- 物理上这些地址连续吗?很明显,不连续。
- 物理次序和逻辑次序有关系嘛?很明显,没关系。赵是第一个,物理地址却在其他元素的下面。
2.为什么使用链表?
- 对比顺序表(例如数组),链表没有容量上限,可以无限扩容(不考虑内存的情况下)。而数组在初始化时便敲定了最大容量,无法扩容。
- 已知某结点的情况下,删除、插入的时间复杂度为O(1),效率同比顺序表非常高。
- 也就是说,对于某些情况下,使用链表会带来更高的效率,那为什么不用呢?
3.链表有哪几种?
- 单(向)链表
- 双(向)链表
- 循环链表
4.什么是“单向”链表?
- 每个结点只有下一个结点的指针域,则由这类结点构成的链表叫单向链表。
- 就是说: 你通过当前结点,只能向一个方向去找下一个结点,你找不到上一个,所以叫“单向”。

说明: 比如说你有a2的引用,你可以拿到a3,但你拿不到a1。
5.什么是“双向”链表?
- 每个结点除了保留下一个结点的指针域外,还保留了上一个结点的指针域。
- 就是说:你通过当前结点,不仅可以拿到下一个结点,也能拿到上一个结点,你可以在前后两个方向获取元素,所以叫“双向”。

说明: 比如说你有a2的引用,你可以拿到a3,而且你也能拿到a1。
6.什么是“循环”链表?
- 循环链表的概念与“单、双”链表并非互斥关系,反而可以相互包容;
- 例如: 你可以实现 循环单链表 or 循环双链表。
- 那么,为什么叫“循环”呢? 因为,最后一个结点的Next指针一般是空的,因为的确没有结点了嘛,但是你的Next指针指向第一个元素,形成了一个环状结构。


7.单链表代码实现
namespace YoyoCode
{
internal class SinglyLinkedList<T>
{
//首元结点
public SinglyLinkedListNode<T> First;
//尾结点
public SinglyLinkedListNode<T> Last;
//结点数量
public int NodeCount = 0;
/// <summary>
/// 是否为空
/// </summary>
/// <returns>bool,链表是否为空</returns>
public bool IsEmpty()
{
return NodeCount == 0 ? true : false;
}
/// <summary>
/// 清空链表
/// </summary>
public void Clear()
{
First = null;
Last = null;
NodeCount = 0;
}
/// <summary>
/// 头插法
/// </summary>
/// <param name="value">类型为T的值</param>
public void AddFirst(T value)
{
SinglyLinkedListNode<T> node = new SinglyLinkedListNode<T>(value);
if (IsEmpty())
{
First = node;
Last = node;
}
else
{
node.Next= First;
First= node;
}
NodeCount++;
}
/// <summary>
/// 尾插法
/// </summary>
/// <param name="value">类型为T的值</param>
public void AddLast(T value)
{
SinglyLinkedListNode<T> node = new SinglyLinkedListNode<T>(value);
if (IsEmpty())
{
First = node;
Last = node;
}
else
{
Last.Next = node;
Last = node;
}
NodeCount++;
}
/// <summary>
/// 在对应的索引插入元素
/// </summary>
/// <param name="idx">索引,从0开始</param>
public bool AddAt(T value, int idx)
{
if (idx < 0 || idx > NodeCount)
{
return false;
}
if (idx == 0)
{
AddFirst(value);
return true;
}
if (idx == NodeCount)
{
AddLast(value);
return true;
}
//其他情况
SinglyLinkedListNode<T> prev = First;
SinglyLinkedListNode<T> cur = First.Next;
SinglyLinkedListNode<T> node = new SinglyLinkedListNode<T>(

本文介绍了链表的基本概念,包括单链表、双向链表和循环链表,并提供了C#语言的单链表和双链表的代码实现,强调了链表在内存管理和操作效率上的优势。同时,文章包含了一个简单的循环单链表的代码示例,帮助读者更好地理解链表的结构和操作。

5586

被折叠的 条评论
为什么被折叠?



