参考:数组、单链表和双链表介绍 以及 双向链表的C/C++/Java实现
单向链表:
由节点链接组成,在内存中不连续,每个节点包含节点自身的数据和下一节点的引用,节点链接方向是单向的,只能访问当前节点及下一节点,只能正向遍历,从头到尾遍历,增加、删除比较方便,查询比较麻烦
双向链表:
与单向链表相似, 由节点链接组成,在内存中不连续,每个节点包含节点自身的数据及上一节点、下一节点的引用,链接方向是双向的,可以访问当前节点及其上下节点,可以双向遍历,增删节点方便,还是不适合查询
C# 节点定义如下:
public class LinkNode<T>
{
public T value;
public LinkNode<T> lastNode;
public LinkNode<T> nextNode;
public LinkNode(T nodeValue, LinkNode<T> last, LinkNode<T> next)
{
value = nodeValue;
lastNode = last;
nextNode = next;
}
}
参考文章中关于增加、删除节点的方法,研究了好半天,主要还是利用index下标作为索引,发现用C#的List、Stack、Queue,都可以更加高效的实现,链表反而更加繁琐,不能发挥出链表的特长
于是利用链表的特点写了两个增删方法(实际使用还是要根据具体需求,自定义合适的方法):
public class DoubleLink<T>
{
//标记首尾节点
public LinkNode<T> headtNode { get; private set; }
public LinkNode<T> endNode { get; private set; }
//有效节点个数
public int count { get; private set; }
public DoubleLink()
{
headtNode = new LinkNode<T>(default, null, null);
endNode = new LinkNode<T>(default, headtNode, null);
headtNode.nextNode = endNode;
count = 0;
}
//在首节点之后插入节点
public void AddAfterHead(T nodeValue)
{
LinkNode<T> newNode = new LinkNode<T>(nodeValue, headtNode, headtNode.nextNode);
headtNode.nextNode.lastNode = newNode;
headtNode.nextNode = newNode;
count++;
}
//在尾节点之前插入节点
public void AddBeforeEnd(T nodeValue)
{
LinkNode<T> newNode = new LinkNode<T>(nodeValue, endNode.lastNode, endNode);
endNode.lastNode.nextNode = newNode;
endNode.lastNode = newNode;
count++;
}
//删除首节点后一个节点
public void RemoveAfterHead()
{
LinkNode<T> node = headtNode.nextNode;
node.nextNode.lastNode = headtNode;
headtNode.nextNode = node.nextNode;
count--;
}
//删除尾节点前一个节点
public void RemoveBeforeEnd()
{
LinkNode<T> node = endNode.lastNode;
node.lastNode.nextNode = endNode;
endNode.lastNode = node.lastNode;
count--;
}
//清空有效节点
public void Clear()
{
headtNode.nextNode = endNode;
endNode.lastNode = headtNode;
}
}
测试:
public class Test : MonoBehaviour
{
void Start()
{
DoubleLink<string> doubleLink = new DoubleLink<string>();
doubleLink.AddAfterHead("1");
doubleLink.AddAfterHead("0");
doubleLink.AddBeforeEnd("2");
doubleLink.AddBeforeEnd("3");
LinkNode<string> node = doubleLink.headtNode;
while (node != null)
{
Debug.Log(node.value);
node = node.nextNode;
}
//打印结果:"Null;0;1;2;3;Null;"
doubleLink.RemoveAfterHead();
node = doubleLink.headtNode;
while (node != null)
{
Debug.Log(node.value);
node = node.nextNode;
}
//打印结果:"Null;1;2;3;Null;"
doubleLink.RemoveBeforeEnd();
node = doubleLink.headtNode;
while (node != null)
{
Debug.Log(node.value);
node = node.nextNode;
}
//打印结果:"Null;1;2;Null;"
doubleLink.Clear();
node = doubleLink.headtNode;
while (node != null)
{
Debug.Log(node.value);
node = node.nextNode;
}
//打印结果:"Null;Null;"
}
}