上一篇文章介绍的是线性表的实现方式一:顺序表,顺序表是以数组为核心存储数据,和List集合的逻辑类似,顺序表的特点是逻辑上相邻的数据,物理位置上也相邻,所以顺序表在查找和读取数据是否方便,但是在插入和删除时却很麻烦,需要移动大量数据。但是今天的实现的单链表的可以填补顺序表的缺点,虽然他没能继承顺序表的优点,所以没有完美的结构,还是合适的最好。
- 线性表 (抽象的结构:数据一对一的线性关系)
- 顺序表(线性表的实现方式之一)
- 链式表(线性表的实现方式之一)
- 单链表(单项连接的链式表)
- 双向链表(双项连接的链式表)
- 循环链表(首尾相接的链式表)
今天要实现的是单链表
不同于顺序表式是以数组为储存数据的容器,单链表用的是最简单的一个变量存储数据。我画了个图简单展示一下:
这里先介绍一个基本概念:当一个数据失去引用的时候,他本身就失去了存在的意义,就会被内存回收机制当作垃圾回收。知道了这个时候,我们看这是一个类:用来存储数据的基本单位,这个类里面包含了一个储存数据的变量和一个指向下一个类的引用,正是这些引用让我的数据链在了一起,保证不会被当作垃圾回收。这里我也化了一个简单的示意图。
这样我们就只需要掌握第一个类的引用,就可以操作所有的数据
上代码
第一步、定义一个线性表的接口
第一步和之前顺序表的第一步是一样的,都是先定义一个接口,而且接口是差不多的,毕竟要实现的功能是一样的,只是方法不一样。(这里少了顺序表中10和11的功能,因为单链表不是通过数组存储数据,所以用不上)
//线性表接口定义:线性表的实现有 顺序表、链式表{单链表、双向链表、循环链表}
interface IListDs<T>
{
int GetLength();//1.求长度
void Clear();//2.清空操作
bool IsEmpty();//3.判断线性表是否为空
void Add(T item);//4.添加数据
void Insert(T item, int index);//5.插入数据
T Delete(int index);//6.删除数据
T GetElement(int index);/7./取数据
T this[int index] { get; }//8.索引器取数据
int Locate(T value);//9.按照值查找数据
}
第二部、定义存储数据基本单位的___一个类
这个类的作用上面已经介绍了。就是存数据和引用。这里我们定义一个Node类。类里面声明了一个T变量,他就是用来存储数据的,和一个 Node类型的变量,这就是引用,用来指向下一个元素(类/数据)
/// <summary>
/// 单链表的结点类,单链表中的元素都是储存在结点中的
/// </summary>
/// <typeparam name="T"></typeparam>
class Node<T>
{
private T data;//储存数据的变量(数据域)
private Node<T> next;//指针(引用),用来指向下一个元素/类/数据(引用域)
/// <summary>
/// 默认构造函数,指针为空,数据为类型的默认值
/// </summary>
public Node()
{
data = default(T);
next = null;
}
/// <summary>
/// 构造函数,头结点赋值
/// </summary>
/// <param name="value"></param>
public Node(T value)
{
data = value;
next = null;
}
/// &l