-
说起数据结构想必大家都已经耳熟能详了吧,无论是最基础的“数组”,还是“列表”以及“字典”,它们都是数据结构,而我今天要说的“链表”也是一种数据结构。
-
什么是链表?
简单来说就是多个数据每两两之间就会通过一根“链条”连接,这就是链表,就跟自行车的那根铁链条一样。 -
什么是单向链表?什么是双向链表?什么又是循环链表?
这个也很容易理解,拿交通来说,单行道就是单向链表;双行道是双向链表;至于循环链表可能就是那种大转盘小转盘吧。 -
——单向链表可以通过一个数据找到下一个数据,再通过下一个数据找到下下个数据,但不能反向查找,也就是只能一条道走到黑了
-
——双向链表可以通过这个数据找到下一个数据,也可以通过下一个数据反向查找回这一个数据,每两个数据之间都能相互查找
-
——循坏链表就是可以通过最后一个查找到第一个,所以其实双向链表抽象一下也就是循环链表了,只是查找回来会多走一遍而已
-
链表组成——节点
综上所述,链表其实就是由多个数据组成,但也不再只是一个单纯的数据,因为它多了一个或多个“指向”,所以我们一般将其称为“节点”。 -
示例——单向链表
为什么要用单向链表呢?因为它简单呀!
首先,我们要写一个节点类(结构体也是可以滴),而这个节点我们主要有两个东西,第一个为这个节点本身所存储的值,第二个则是“指向”,其实就是另一个“节点”,代码如下所示:
public class ListNode<T>//链表节点
{
public T value;//值
public ListNode<T> next;//链向下一个节点
public ListNode(T value)
{
this.value = value;
}
}
- 我这里用的是泛型,大家一开始学习都话可以指定的,比如“int”,“string”啥的。
- 节点类写好后,我们只是把它用来存储数据而已,真正的操作并不在这里面进行,我们需要再新建一个类,我将其取名为“MyList”,而里面具体则需要有“链表头”,“链表尾”,以及“节点数量”,当然这只是一个比较简单的,代码如下:
public class MyList<T>
{
ListNode<T> listHead;//表头
ListNode<T> listTail;//表尾
public int count;//节点数量
public MyList()
{
listHead = null;
listTail = null;
count = 0;
}
}
- 表头跟表尾也是节点,只是这两个节点比较特殊,需要着重考虑
- 主体写好过后,我们需要有一个可以添加数据(节点)的方法,取名为“MyAdd”,代码如下:
public void MyAdd(T value)//从尾部添加
{
ListNode<T> addNode = new ListNode<T>(value);
if (listHead == null)//空表
{
listHead = addNode;
listTail = addNode;
}
else
{
listTail.next = addNode;
listTail = addNode;
}
count++;
}
-
这里主要判断一下链表是否为空表状态,当"表头"为空则表示当前链表为空表,空表状态下加入第一个数据(节点),那么"表头""表尾"都将是这条数据;当链表不为空表,那么加入数据(节点)时我们只需要将““表尾"的"指向"等于我们新加入的这个数据(节点),而后再将"表尾"等于新加入的数据(节点)就好;
这里要注意的是:最后我们是要把"表尾"等于我们新加入的数据,而不是新加入的数据等于"表尾”,否则将毫无意义,当然最终的节点数量我们也得+1! -
在写其他功能之前,我们先写一个根据索引取得节点的私有方法,因为这个功能我们需要很常用,具体代码如下:
private ListNode<T> GetListNodeByIndex(int