链表是用一组任意的存储单元来存储线性表中的数据元素(这组存储单元可以是连续的,也可以是不连续的)。那么,怎么表示两个数据元素逻辑上的相邻关系呢?即如何表示数据元素之间的线性关系呢?为此,在存储数据元素时,除了存储数据元素本身的信息外,还要存储与它相邻的数据元素的存储地址信息。这两部分信息组成该数据元素的存储映像(Image),称为结点(Node)。把存储据元素本身信息的域叫结点的数据域(Data Domain),把存储与它相邻的数据元素的存储地址信息的域叫结点的引用域(Reference Domain)。因此,线性表通过每个结点的引用域形成了一根“链条”,这就是“链表”名称的由来。
如果结点的引用域只存储该结点直接后继结点的存储地址,则该链表叫单链表(Singly Linked List)。把该引用域叫next。单链表结点的结构如图2.5所示,图中data表示结点的数据域。
把单链表结点看作是一个类,类名为Node<T>。单链表结点类的实现如下所示。
![ContractedBlock.gif](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![ExpandedBlockStart.gif](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
{
private T data; // 数据域
private Node < T > next; // 引用域
// 构造器
public Node(T val, Node < T > p)
{
data = val;
next = p;
}
// 构造器
public Node(Node < T > p)
{
next = p;
}
// 构造器
public Node(T val)
{
data = val;
next = null ;
}
// 构造器
public Node()
{
data = default (T);
next = null ;
}
// 数据域属性
public T Data
{
get { return data; }
set { data = value; }
}
// 引用域属性
public Node < T > Next
{
get { return next; }
set { next = value; }
}
}
是线性表(a1,a2,a3,a4,a5,a6)对应的链式存储结构示意图。
存储地址 data next
头引用H
通常,我们把链表画成用箭头相连接的结点的序列,结点间的箭头表示引用域中存储的地址。为了处理上的简洁与方便,在本书中把引用域中存储的地址叫引用,如图示
由图可知,单链表由头引用H唯一确定。头引用指向单链表的第一个结点,也就是把单链表第一个结点的地址放在H中,所以,H是一个Node类型的变量。头引用为null表示一个空表。
把单链表看作是一个类,类名叫LinkList<T>。LinkList<T>类也实现了接口IListDS<T>。LinkList<T>类有一个字段head,表示单链表的头引用,所以head的类型为Node<T>。由于链表的存储空间不是连续的,所以没有最大空间的限制,在链表中插入结点时不需要判断链表是否已满。因此,在LinkList<T>类中不需要实现判断链表是否已满的成员方法。
单链表类LinkList<T>的实现说明如下所示。
![ContractedBlock.gif](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![ExpandedBlockStart.gif](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
{
private Node < T > head; // 单链表的头引用
// 头引用属性
public Node < T > Head
{
get
{
return head;
}
set
{
head = value;
}
}
// 构造器
public LinkList()
{
head = null ;
}
// 链表的基本操作
// 求单链表的长度
public int GetLenght()
{
Node < T > p = head;
int len = 0 ;
while (p != null )
{
++ len;
p = p.Next;
}
return len;
}
// 清空单链表
public void Clear()
{
head = null ;
}
// 判断单链表是否为空
public bool IsEmpty()
{
if (head == null )
{
return true ;
}
else
{
return false ;
}
}
// 在单链表的末尾添加新元素
public void Append(T item)
{
Node < T > q = new Node < T > (item);
Node < T > p = new Node < T > ();
if (head == null )
{
head = q;
return ;
}
p = head;
while (p.Next != null )
{
p = p.Next;
}
p.Next = q;
}
// 在单链表的第i个结点的位置前插入一个值为item的元素
public void Insert(T item, int i)
{
if (IsEmpty() || i < 1 )
{
Console.WriteLine( " List is empty or Position is error " );
return ;
}
if (i == 1 )
{
Node < T > q = new Node < T > (item);
q.Next = head;
head = q;
return ;
}
Node < T > p = head;
Node < T > r = new Node < T > ();
int j = 1 ;
while (p.Next != null && j < i)
{
r = p;
p = p.Next;
++ j;
}
if (j == i)
{
Node < T > q = new Node < T > (item);
q.Next = p;
r.Next = q;
}
}
// 在单链表的第i个结点的位置后插入一个值为item的元素
public void InsertPost(T item, int i)
{
if (IsEmpty() || i < 1 )
{
Console.WriteLine( " List is empty or Position is error " );
return ;
}
if (i == 1 )
{
Node < T > q = new Node < T > (item);
q.Next = head.Next;
head.Next = q;
return ;
}
Node < T > p = head;
int j = 1 ;
while (p != null && j < i)
{
p = p.Next;
++ j;
}
if (j == i)
{
Node < T > q = new Node < T > (item);
q.Next = p.Next;
p.Next = q;
}
}
// 删除单链表的第i个结点
public T Delete( int i)
{
if (IsEmpty() || i < 0 )
{
Console.WriteLine( " List is empty or Position is error " );
return default (T);
}
Node < T > q = new Node < T > ();
if (i == 1 )
{
q = head;
head = head.Next;
return q.Data;
}
Node < T > p = head;
int j = 1 ;
while (p.Next != null && j < i)
{
++ j;
q = p;
p = p.Next;
}
if (j == i)
{
q.Next = p.Next;
return p.Data;
}
else
{
Console.WriteLine( " The ith node is not exist " );
return default (T);
}
}
// 获得单链表的第i个数据元素
public T GetElem( int i)
{
if (IsEmpty())
{
Console.WriteLine( " List is empty " );
return default (T);
}
Node < T > p = new Node < T > ();
p = head;
int j = 1 ;
while (p.Next != null && j < i)
{
++ j;
p = p.Next;
}
if (j == i)
{
return p.Data;
}
else
{
Console.WriteLine( " The ith node is not exist " );
return default (T);
}
}
// 在单链表中查找值为value的结点
public int Locate(T value)
{
if (IsEmpty())
{
Console.WriteLine( " List is Empty " );
return - 1 ;
}
Node < T > p = new Node < T > ();
p = head;
int i = 1 ;
while ( ! p.Data.Equals(value) && p.Next != null )
{
p = p.Next;
++ i;
}
return i;
}
// 在尾部插入结点建立单链表的算法
public LinkList < int > CreatLListHead()
{
int d;
LinkList < int > L = new LinkList < int > ();
d = Int32.Parse(Console.ReadLine());
while (d != - 1 )
{
Node < int > p = new Node < int > ();
p.Next = L.Head;
L.Head = p;
d = Int32.Parse(Console.ReadLine());
}
return L;
}
// 将两个表合成一表的算法
// public LinkList<int> Merge(LinkList<int> Ha, LinkList<int> Hb)
// {
// LinkList<int> Hc = new LinkList<int>();
// }
// 复制单链表的算法
public LinkList < int > LinkClone(LinkList < int > la)
{
LinkList < int > lb = new LinkList < int > ();
Node < T > p = new Node < T > ();
p = head;
int j = 1 ;
while (p.Next != null && j < 100 )
{
lb.Append(la.GetElem(j));
j ++ ;
}
return lb;
}
// 输入全部的节点
public void Display()
{
Node < T > p = new Node < T > ();
p = head;
int j = 0 ;
while (p.Next != null && j < 100 )
{
Console.WriteLine(p.Data);
p = p.Next;
j ++ ;
}
}