链表
链表是一种递归的数据结构,他或者为空,或者是指向另一个结点的引用,该结点含有一个泛型元素和一个指向另一条链表的引用。
链表不要求逻辑上相邻的数据元素在物理存储位置上也相邻,链表插入和删除时不需要移动数据元素,同时也失去了顺序表可随即存储的优点。
链表储存数据元素时,除了存储数据元素本身的信息外还要存储它相邻的存储地址信息。这两部分信息组成该数据元素的存储映像Image,称为结点Node。把存储数据元素本身信息的域叫结点的数据域Data Domain,把存储与他相邻的数据元素的存储地址信息的域叫结点的引用域Reference Domain,线性表通过每个结点的引用域形成一个链条,即链表。
单链表
如果结点的引用域只存储该结点直接后继结点的存储地址,则该链表叫单链表Singly Linked List。把该引用域叫next。
头引用
单链表由头引用H唯一确定,头引用指向单链表的第一个结点,也就是把单链表第一个结点的地址放head中,所以head是一个Node类型的变量。
头结点
单链表的头引用head永远是一个引用,有头结点时他就是头结点的引用,没有头结点时他就是首元结点的引用。
有无头结点的区别就是:在遍历表时,无头结点往往是以p=head开始遍历p.next,即从首元结点开始,二有头结点的表往往是以p=head.next开始遍历p.next,将头结点略过后再从首元结点开始。
单链表的数据结构
单链表结点类和单链表类的完整实现在最后贴出
①无头结点
首先以单链表的前插操作中插在首元结点前为例,解释单链表无头结点的操作逻辑
1.新建一个单链表L,并添加若干元素,即执行Append()方法,头引用head在Append()方法中被设置为第一个元素(元结点)的引用,表L的数据结构如下图所示
2.声明一个值为item的Node类型变量Q,将Q插入表L的i=1处,即将Q插在A前面
Node<T> Q = new Node<T>(item);
Q.Next = head;
head = Q;
设置Q的引用域为head,因为head是A的引用,等同将Q的引用域设置为A。再使head=Q,即设置head为Q的引用
最后的表L的数据结构如下图所示
②有头结点
以单链表的反转操作为例,解释单链表有头结点的操作逻辑
声明一个新的单链表L,并附加若干元素。
声明新的结点q和p,并设置p为头引用head的next指向的结点的引用,即p为B的引用,再设置head的引用域为null
while (p != null)
{
q = p;
p = p.Next;
q.Next = head.Next;
head.Next = q;
}
循环执行以上代码:
第一次循环中
1.设置q为p的引用,p为B的引用,即设置q为B的引用
2.设置p为p.Next,即遍历表元,使p为C的引用
3.设置q的next为head的next,即q(也就是B)的next为null
4.设置head的next为q,即head(也是A)的next为q(也就是B)
第二次循环中
1.设置q为p的引用,p为C的引用,即设置q为C的引用
2.设置p为p.Next,即遍历表元,p循环完毕,为null
3.设置q的next为head的next,即q(也就是C)的next为B
4.设置head的next为q,即head(也是A)的next为q(也就是C)
单链表结点类的实现
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;
}
}
}
单链表类的实现
public class LinkList<T> : IListDS<T>
{
private Node<T> head;//单链表的头引用
//头引用属性
public Node<T> Head
{
get
{
return head;
}
set
{
head = value;
}
}
//构造器
public LinkList()
{
head = null;
}
//附加操作
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;
}
//清空表
public void Clear()
{
head = null;
}
//删除操作
public T Delete(int i)
{
if(IsEmpty() || i < 1)
{
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("Node is not exist");
return default(T);
}
}
//取表元
public T GetElm(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("Node is not exist");
return default(T);
}
}
//获取长度
public int GetLength()
{
Node<T> p = head;
int len = 0;
while (p != null)
{
++len;
p = p.Next;
}
return len;
}
//前插操作
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;
}
}
//后插操作
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.Next != null && j < 1)
{
p = p.Next;
++j;
}
if (j == i)
{
Node<T> q = new Node<T>(item);
q.Next = p.Next;
p.Next = q;
}
else
{
Console.WriteLine("Position is error!");
}
return;
}
//判断表为空
public bool IsEmpty()
{
if (head == null)
{
return true;
}
else
{
return false;
}
}
//按值查找
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.Next != null&&!p.Data.Equals(value))
{
p = p.Next;
++i;
}
return i;
}
//表元反转
public void Reverse()
{
Node<T> p = head.Next;
Node<T> q = new Node<T>();
head.Next = null;
while (p != null)
{
q = p;
p = p.Next;
q.Next = head.Next;
head.Next = q;
}
}
}