数据结构单链表

本文深入探讨了链表的概念,包括链表的结构、单链表的实现、链表的基本操作及其应用实例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

    链表是用一组任意的存储单元来存储线性表中的数据元素(这组存储单元可以是连续的,也可以是不连续的)。那么,怎么表示两个数据元素逻辑上的相邻关系呢?即如何表示数据元素之间的线性关系呢?为此,在存储数据元素时,除了存储数据元素本身的信息外,还要存储与它相邻的数据元素的存储地址信息。这两部分信息组成该数据元素的存储映像(Image),称为结点(Node)。把存储据元素本身信息的域叫结点的数据域(Data Domain),把存储与它相邻的数据元素的存储地址信息的域叫结点的引用域(Reference Domain)。因此,线性表通过每个结点的引用域形成了一根“链条”,这就是“链表”名称的由来。
如果结点的引用域只存储该结点直接后继结点的存储地址,则该链表叫单链表(Singly Linked List)。把该引用域叫next。单链表结点的结构如图2.5所示,图中data表示结点的数据域。

2010052108520494.jpg

把单链表结点看作是一个类,类名为Node<T>。单链表结点类的实现如下所示。

 

 

ContractedBlock.gifExpandedBlockStart.gif代码
public class Node<T>
{
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 
 2010052108545262.jpg

   通常,我们把链表画成用箭头相连接的结点的序列,结点间的箭头表示引用域中存储的地址。为了处理上的简洁与方便,在本书中把引用域中存储的地址叫引用,如图示

      2010052108580371.jpg

    由图可知,单链表由头引用H唯一确定。头引用指向单链表的第一个结点,也就是把单链表第一个结点的地址放在H中,所以,H是一个Node类型的变量。头引用为null表示一个空表。
把单链表看作是一个类,类名叫LinkList<T>。LinkList<T>类也实现了接口IListDS<T>。LinkList<T>类有一个字段head,表示单链表的头引用,所以head的类型为Node<T>。由于链表的存储空间不是连续的,所以没有最大空间的限制,在链表中插入结点时不需要判断链表是否已满。因此,在LinkList<T>类中不需要实现判断链表是否已满的成员方法。
单链表类LinkList<T>的实现说明如下所示。

 

ContractedBlock.gifExpandedBlockStart.gif代码
public class LinkList<T>:IList<T>
{
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
++;
}


}

 

 

  

 

转载于:https://www.cnblogs.com/ScriptZhang/archive/2010/05/21/1740598.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值