前情提示:
上一篇总结了数据结构的基本概念,以及在C#下的一些基本实现Code。从这篇之后难度加大,代码量也增大了。分卷了。这一篇主要讲述双向链表和双向循环链表。
双向链表:
双向链表也叫双链表,是链表的一种,它的每个数据结点中都有两个指针,分别指向直接后继和直接前驱。所以,从双向链表中的任意一个结点开始,都可以很方便地访问它的前驱结点和后继结点。一般我们都构造双向循环链表。
双向循环链表:
双向循环链表是另一种形式的链式存贮结构。它的特点是表中最后一个结点的指针域指向头结点,整个链表形成一个环。
节点类(DoubleLinkedListNode.cs)
public class DoubleLinkedListNode<T>
{
//前驱
private DoubleLinkedListNode<T> _nextDoubleLinkedListNode;
private DoubleLinkedListNode<T> _prevDoubleLinkedListNode;
//数据
private T dataValue;
/// <summary>
/// 无参构造函数 该节点只有默认值,前驱和后继都 ——>null
/// </summary>
public DoubleLinkedListNode()
{
this.dataValue = default(T);
this._nextDoubleLinkedListNode = null;
this._prevDoubleLinkedListNode = null;
}
/// <summary>
/// 构造方法:实例化该节点只有传入的data域,前驱和后继都指向null
/// </summary>
/// <param name="value"></param>
public DoubleLinkedListNode(T value)
{
this._prevDoubleLinkedListNode = null;
this.dataValue = value;
this._nextDoubleLinkedListNode = null;
}
/// <summary>
/// 构造函数:实例化一个正常的Node 数据域 前驱后继都有值
/// </summary>
/// <param name="value"></param>
/// <param name="prev"></param>
/// <param name="next"></param>
public DoubleLinkedListNode(T value, DoubleLinkedListNode<T> prev, DoubleLinkedListNode<T> next)
{
this._prevDoubleLinkedListNode = prev;
this.dataValue = value;
this._nextDoubleLinkedListNode = next;
}
public DoubleLinkedListNode<T> PrevDoubleLinkedListNode
{
get { return this._prevDoubleLinkedListNode; }
set { this._prevDoubleLinkedListNode = value; }
}
public T DataValue
{
get { return this.dataValue; }
set { this.dataValue = value; }
}
public DoubleLinkedListNode<T> NextDoubleLinkedListNode
{
get { return this._nextDoubleLinkedListNode; }
set { this._nextDoubleLinkedListNode = value; }
}
/// <summary>
/// Show 方法,调试用
/// </summary>
/// <returns></returns>
public override string ToString()
{
T p = this._prevDoubleLinkedListNode == null ? default(T) : this._prevDoubleLinkedListNode.dataValue;
T n = this._nextDoubleLinkedListNode == null ? default(T) : this._nextDoubleLinkedListNode.dataValue;
string s = string.Format("Data:{0},Prev:{1},Next:{2}", this.dataValue, p, n);
return s;
}
}
接口(ILinkList.cs)
internal interface ILinkedList<T>
{
/// <summary>
/// 头元素
/// </summary>
DoubleLinkedListNode<T> HeadDoubleLinkedListNode { get; }
/// <summary>
/// 尾元素
/// </summary>
DoubleLinkedListNode<T> EndDoubleLinkedListNode { get; }
/// <summary>
/// 在 LinkedList<(Of <(T>)>) 中指定的现有节点后添加指定的新节点。
/// </summary>
/// <param name="node"></param>
/// <param name="newNode"></param>
void AddAfter(DoubleLinkedListNode<T> node, DoubleLinkedListNode<T> newNode);
/// <summary>
/// 在 LinkedList<(Of <(T>)>) 中的现有节点后添加新的节点或值。
/// </summary>
/// <param name="node"></param>
/// <param name="t"></param>
void AddAfter(DoubleLinkedListNode<T> node, T t);
/// <summary>
/// 在 LinkedList<(Of <(T>)>) 中指定的现有节点前添加指定的新节点。
/// </summary>
/// <param name="node"></param>
/// <param name="newNode"></param>
void AddBefore(DoubleLinkedListNode<T> node, DoubleLinkedListNode<T> newNode);
/// <summary>
/// 在 LinkedList<(Of <(T>)>) 中指定的现有节点前添加包含指定值的新节点。
/// </summary>
/// <param name="node"></param>
/// <param name="t"></param>
void AddBefore(DoubleLinkedListNode<T> node, T t);
/// <summary>
/// 在 LinkedList<(Of <(T>)>) 的开头处添加包含指定值的新节点。
/// </summary>
/// <param name="value"></param>
/// <returns></returns>
DoubleLinkedListNode<T> AddFirst(T value);
/// <summary>
/// 在 LinkedList<(Of <(T>)>) 的开头处添加指定的新节点
/// </summary>
/// <param name="node"></param>
void AddFirst(DoubleLinkedListNode<T> node);
/// <summary>
/// 在 LinkedList<(Of <(T>)>) 的结尾处添加包含指定值的新节点。
/// </summary>
/// <param name="value"></param>
/// <returns></returns>
DoubleLinkedListNode<T> AddLast(T value);
/// <summary>
/// 在 LinkedList<(Of <(T>)>) 的结尾处添加指定的新节点
/// </summary>
/// <param name="node"></param>
void AddLast(DoubleLinkedListNode<T> node);
/// <summary>
/// 从 LinkedList<(Of <(T>)>) 中移除指定的节点。
/// </summary>
/// <param name="node"></param>
bool Remove(DoubleLinkedListNode<T> node);
/// <summary>
/// 从 LinkedList<(Of <(T>)>) 中按索引删除节点。
/// </summary>
/// <param name="node"></param>
bool Remove(int index);
/// <summary>
/// 移除头结点
/// </summary>
void RemoveHeadNode();
/// <summary>
/// 移除尾节点
/// </summary>
void RemoveEndNode();
/// <summary>
/// 从 LinkedList<(Of <(T>)>) 中查找第一个匹配项
/// </summary>
/// <param name="value"></param>
/// <returns></returns>
DoubleLinkedListNode<T> Find(T value);
/// <summary>
/// 从 LinkedList<(Of <(T>)>) 中查找最后一个匹配项
/// </summary>
/// <param name="value"></param>
/// <returns></returns>
DoubleLinkedListNode<T> FindLast(T value);
/// <summary>
/// 查询元素的索引
/// </summary>
/// <param name="item"></param>
/// <returns></returns>
int IndexOf(T item);
/// <summary>
/// 能过索引得到元素的元素
/// </summary>
/// <param name="index"></param>
/// <returns></returns>
T GetElementByIndex(int index);
/// <summary>
/// 通过索引得到节点对象
/// </summary>
/// <param name="index"></param>
/// <returns></returns>
DoubleLinkedListNode<T> GetNodeByIndex(int index);
}
双向链表类(DoubleLinkList.cs)
public class DoubleLinkedList<T> : ILinkedList<T>
{
//前驱
//后置
private DoubleLinkedListNode<T> _endDoubleLinkedListNode;
private DoubleLinkedListNode<T> _headDoubleLinkedListNode;
//长度
private int size;
/// <summary>
/// 判断链表是否是空的
/// </summary>
public bool IsEmpty
{
get { return this._headDoubleLinkedListNode == null; }
}
/// <summary>
/// 链表中元素的个数
/// </summary>
public int Count
{
get
{
int i = 0;
DoubleLinkedListNode<T> node = this._headDoubleLinkedListNode;
while (node != null)
{
++ i;
node = node.NextDoubleLinkedListNode;
}
return i;
//return this.size;
}
}
/// <summary>
/// 根据索引获取链表中的节点
/// </summary>
/// <param name="index">整型索引</param>
/// <returns>节点</returns>
public DoubleLinkedListNode<T> this[int index]
{
get
{
//链表头节点是空的
if (this._headDoubleLinkedListNode == null)
{
throw new Exception("链表是空的。");
}
//索引过小
if (index < 0)
{
throw new IndexOutOfRangeException();
}
//索引过大
if (index >= this.Count)
{
throw new IndexOutOfRangeException();
}
//取得头节点
var current = new DoubleLinkedListNode<T>();
//current = head;
//int i = 0;
遍历链表
//while (true)