知识结构:
线性表(Linear List)是由 n ( n ≥ 0 ) n (n≥0) n(n≥0)个相同类型的数据元素 a 0 , a 1 , ⋯ , a n − 1 a_0,a_1,⋯,a_{n-1} a0,a1,⋯,an−1组成的序列。即表中除首尾元素外,其它元素有且仅有一个直接前驱和直接后继。首元素仅有一个直接后继,尾元素仅有一个直接前驱,记为: ( a 0 , a 1 , ⋯ , a n − 1 ) (a_0,a_1,⋯,a_{n-1}) (a0,a1,⋯,an−1)。
表中数据元素的个数称为表的长度。
例1:字母表
( a , b , c , d , … , z ) (a,b,c,d,\dots,z) (a,b,c,d,…,z)
例2:学生成绩表
using System;
namespace LinearStruct
{
///
/// 线性表的抽象数据类型
///
/// 线性表中元素的类型
public interface ILinearList<T> where T : IComparable<T>
{
///
/// 获取线性表中实际包含元素的个数
///
int Length {
get; }
///
/// 获取或设置指定索引处的元素
///
/// 要获取或设置的元素从零开始的索引
/// 指定索引处的元素
T this[int index] {
get; set; }
///
/// 判断线性表中是否包含元素
///
/// 如果包含元素返回false,否则返回true.
bool IsEmpty();
///
/// 将元素插入到指定索引处
///
/// 从零开始的索引,应在该位置插入data.
/// 要插入的元素
void Insert(int index, T data);
///
/// 移除线性表指定索引处的元素
///
/// 要移除元素从0开始的索引
void Remove(int index);
///
/// 在线性表中寻找元素data.
///
/// 要寻找的元素
/// 如果存在返回该元素在线性表中的位置,否则返回-1.
int Search(T data);
///
/// 从线性表中移除所有元素
///
void Clear();
}
}
定义:利用顺序存储结构(即利用数组)实现的线性表,称为顺序表。
特点:逻辑结构与存储结构相同;具有随机存取的特点。
实现:
using System;
namespace LinearStruct
{
///
/// 用顺序存储结构实现的线性表
///
/// 顺序表中元素的类型
public class SeqList<T> : ILinearList<T> where T : IComparable<T>
{
///
/// 数据集合
///
protected readonly T[] Dataset;
///
/// 获取SeqList中实际包含元素的个数
///
public int Length {
get; private set; }
///
/// 获取SeqList中最多包含元素的个数
///
public int MaxSize {
get; }
///
/// 初始化SeqList类的新实例
///
/// SeqList中最多包含元素的个数
public SeqList(int max)
{
if (max <= 0)
throw new ArgumentOutOfRangeException();
MaxSize = max;
Dataset = new T[MaxSize];
Length = 0;
}
///
/// 获取或设置指定索引处的元素
///
/// 要获得或设置的元素从零开始的索引
/// 指定索引处的元素
public T this[int index]
{
get
{
if (index < 0 || index > Length - 1)
throw new IndexOutOfRangeException();
return Dataset[index];
}
set
{
if (index < 0 || index > Length - 1)
throw new IndexOutOfRangeException();
Dataset[index] = value;
}
}
///
/// 判断SeqList中是否包含元素
///
/// 如果包含元素返回false,否则返回true.
public bool IsEmpty()
{
return Length == 0;
}
///
/// 将元素插入到指定索引处
///
/// 从零开始的索引,应在该位置插入data.
/// 要插入的元素
public void Insert(int index, T data)
{
if (index < 0 || index > Length)
throw new IndexOutOfRangeException();
if (Length == MaxSize)
throw new Exception("达到最大值");
for (int i = Length; i > index; i--)
{
Dataset[i] = Dataset[i - 1];
}
Dataset[index] = data;
Length++;
}
///
/// 移除SeqList指定索引处的元素
///
/// 要移除元素从0开始的索引
public void Remove(int index)
{
if (index < 0 || index > Length - 1)
throw new IndexOutOfRangeException();
for (int i = index; i < Length - 1; i++)
{
Dataset[i] = Dataset[i + 1];
}
Length--;
}
///
/// 在SeqList中寻找元素data.
///
/// 要寻找的元素
/// 如果存在返回该元素在线性表中的位置,否则返回-1.
public int Search(T data)
{
int i;
for (i = 0; i < Length; i++)
{
if (Dataset[i].CompareTo(data) == 0)
break;
}
return i == Length ? -1 : i;
}
///
/// 从SeqList中移除所有元素
///
public void Clear()
{
Length = 0;
}
}
}
应用:
using System;
using LinearStruct;
namespace ExampleList
{
class Program
{
static void Main(string[] args)
{
ListTest(new SeqList<string>(500));
// 2
// a1
// a3
}
private static void ListTest(ILinearList<string> lst)
{
lst.Insert(0, "a1");
lst.Insert(1, "a2");
lst.Insert(2, "a3");
lst.Remove(1);
Console.WriteLine(lst.Length);
for (int i = 0; i < lst.Length; i++)
{
Console.WriteLine(lst[i]);
}
}
}
}
利用指针方式实现的线性表称为链表(单链表、循环链表、双向链表)。它不要求逻辑上相邻的数据元素在物理位置上也相邻,即:逻辑结构与物理结构可以相同也可以不相同。
例3:将线性表 ( a 3 , a 4 , a 5 ) (a_3,a_4,a_5) (a3,a4,a5)以链表的形式存储。
定义:每个结点只含有一个链域(指针域)的链表。即:利用单链域的方式存储线性表的逻辑结构。
结构:
实现:
对结点的封装:
using System;
namespace LinearStruct
{
///
/// 单链表结点
///
/// 结点中数据元素的类型
public class SNode<T> where T : IComparable<T>
{
///
/// 获取或设置该结点的数据元素
///
public T Data {
get; set; }
///
/// 获取或设置该结点的后继结点
///
public SNode<T> Next {
get; set; }
///
/// 初始化SNode类的新实例
///
/// 该结点的数据元素
/// 该结点的后继结点
public SNode(T data, SNode<T> next = null)
{
Data = data;
Next = next;
}
}
}
对单链表的封装:
using System;
namespace LinearStruct
{
///
/// 用链式存储结构实现的线性表--单链表
///
/// 单链表中元素的类型
public class SLinkList<T> : ILinearList<T> where T : IComparable<T>
{
///
/// 存储头结点
///
protected SNode<T> PHead {
get; set; }
///
/// 获取SLinkList中实际包含元素的个数
///
public int Length {
get; private set; }
///
/// 初始化SLinkList类的新实例
///
public SLinkList()
{
Length = 0;
PHead = null;
}
///
/// 将元素插入到单链表的首部
///
/// 要插入的元素
public void InsertAtFirst(T data)
{
PHead = new SNode<T>(data, PHead);
Length++;
}
///
/// 获得指定索引处的结点
///
/// 元素从零开始的索引
/// 指定索引处的结点
private SNode<T> Locate(int index)
{
if (index < 0 || index > Length - 1)
throw new IndexOutOfRangeException();
SNode<T> temp = PHead;
for (int i = 0; i < index; i++)
{
temp = temp.Next;
}
return temp;
}
///
/// 将元素插入到单链表的尾部
///
/// 要插入的元素
public void InsertAtRear(T data)
{
if (PHead == null)
{
PHead = new SNode<T>(data);
}
else
{
Locate(Length - 1).Next = new SNode<T>(data);
}
Length++;
}
///
/// 获取或设置指定索引处的元素
///
/// 要获得或设置的元素从零开始的索引
/// 指定索引处的元素
public T this[int index]
{
get
{
if (index < 0 || index > Length - 1)
throw new IndexOutOfRangeException();
return Locate(index).Data;
}
set
{
if (index < 0 || index > Length - 1)
throw new IndexOutOfRangeException();
Locate(index).Data = value;
}
}
///
/// 判断SLinkList中是否包含元素
///
/// 如果包含元素返回false,否则返回true.
public bool IsEmpty()
{
return Length == 0;
}
///
/// 将元素插入到指定索引处
///
/// 从零开始的索引,应在该位置插入data.
/// 要插入的元素
public void Insert(int index, T data)
{
if (index < 0 || index > Length)
throw new IndexOutOfRangeException();
if (index == 0)
{
InsertAtFirst(data);
}
else if (index == Length)
{
InsertAtRear(data);
}
else
{
SNode<T> temp = Locate(index - 1);
temp.Next = new SNode<T>(data, temp.Next);
Length++;
}
}
///
/// 移除SLinkList指定索引处的元素
///
/// 要移除元素从0开始的索引
public void Remove(int index)
{
if (index < 0 || index > Length - 1)
throw new IndexOutOfRangeException();
if (index == 0)
{
PHead = PHead.Next;
}
else
{
SNode<T> temp = Locate(index - 1);
temp.Next = temp.Next.Next;
}
Length--;
}
///
/// 在SLinkList中寻找元素data.
///
/// 要寻找的元素
/// 如果存在返回该元素在线性表中的位置,否则返回-1.
public int Search(T data)
{
int i;
SNode<T> temp = PHead;
for (i = 0; i < Length; i++)
{
if (temp.Data.CompareTo(data) == 0)
break;
temp = temp.Next;
}
return i == Length ? -1 : i;
}
///
/// 从SLinkList中移除所有元素
///
public void Clear()
{
PHead = null;
Length = 0;
}
}
}
应用:
using System;
using LinearStruct;
namespace ExampleList
{
class Program
{
static void Main(string[] args)
{
ListTest(new SLinkList<string>());
// 2
// a1
// a3
}
private static void ListTest(ILinearList<string> lst)
{
lst.Insert(0, "a1");
lst.Insert(1, "a2");
lst.Insert(2, "a3");
lst.Remove(1);
Console.WriteLine(lst.Length);
for (int i = 0; i < lst.Length; i++)
{
Console.WriteLine(lst[i]);
}
}
}
}
定义:是一种首尾相连的单链表。即:在单链表中,将尾结点的指针域null
改为指向PHead
,就得到单链形式的循环链表。
表现形式:
通常情况下,使用尾指针表示循环链表。
实现:
对循环链表的封装:
using System;
namespace LinearStruct
{
///
/// 用链式存储结构实现的线性表--循环链表
///
/// 循环链表中元素的类型
public class CLinkList<T> : ILinearList<T> where T : IComparable<T>
{
///
/// 存储尾部结点
///
protected SNode<T> PRear {
get; set; }
///
/// 获取CLinkList中实际包含元素的个数
///
public int Length {
get; private set; }
///
/// 获取或设置指定索引处的元素
///
/// 要获得或设置的元素从零开始的索引
/// 指定索引处的元素
public T this[int index]
{
get
{
if (index < 0 || index > Length - 1)
throw new IndexOutOfRangeException();
return Locate(index).Data;
}
set
{
if (index < 0 || index > Length - 1)
throw new IndexOutOfRangeException();
Locate(index).Data = value;
}
}
///
/// 初始化CLinkList类的新实例
///
public CLinkList()
{
Length = 0;
PRear = null;
}
///
/// 判断CLinkList中是否包含元素
///
/// 如果包含元素返回false,否则返回true.
public bool IsEmpty()
{
return Length == 0;
}
///
/// 将元素插入到循环链表的尾部
///
/// 要插入的元素
public void InsertAtRear(T data)
{
if (IsEmpty())
{
PRear = new SNode<T>(data);
PRear.Next = PRear;
}
else
{
SNode<T> temp = new SNode<T>(data, PRear.Next);
PRear.Next = temp;
PRear = temp;
}
Length++;
}
///
/// 将元素插入到循环链表的首部
///
/// 要插入的元素
public void InsertAtFirst(T data)
{
if (IsEmpty())
{
PRear = new SNode<T>(data);
PRear.Next = PRear;
}
else
{
SNode<T> temp = new SNode<T>(data, PRear.Next);
PRear.Next = temp;
}
Length++;
}
///
/// 获得指定索引处的结点
///
/// 元素从零开始的索引
/// 指定索引处的结点
private SNode<T> Locate(int index)
{
if (index < 0 || index > Length - 1)
throw new IndexOutOfRangeException();
SNode<T> temp = PRear.Next;
for (int i = 0; i < index; i++)
{
temp = temp.Next;
}
return temp;
}
///
/// 将元素插入到指定索引处
///
/// 从零开始的索引,应在该位置插入data.
/// 要插入的元素
public void Insert(int index, T data)
{
if (index < 0 || index > Length)
throw new IndexOutOfRangeException();
if (index == 0)
{
InsertAtFirst(data);
}
else if (index == Length)
{
InsertAtRear(data);
}
else
{
SNode<T> temp = Locate(index - 1);
temp.Next = new SNode<T>(data, temp.Next);
Length++;
}
}
///
/// 移除CLinkList指定索引处的元素
///
/// 要移除元素从0开始的索引
public void Remove(int index)
{
if (index < 0 || index > Length - 1)
throw new IndexOutOfRangeException();
if (PRear == PRear.Next)
{
PRear = null;
}
else
{
if (index == Length - 1)
{
SNode<T> temp = Locate(Length - 2);
temp.Next = PRear.Next;
PRear = temp;
}
else if (index == 0)
{
PRear.Next = PRear.Next.Next;
}
else
{
SNode<T> temp = Locate(index - 1);
temp.Next = temp.Next.Next;
}
}
Length--;
}
///
/// 在CLinkList中寻找元素data.
///
/// 要寻找的元素
/// 如果存在返回该元素在线性表中的位置,否则返回-1.
public int Search(T data)
{
int i;
SNode<T> temp = PRear;
for (i = 0; i < Length; i++)
{
if (temp.Next.Data.CompareTo(data) == 0)
break;
temp = temp.Next;
}
return (i == Length) ? -1 : i;
}
///
/// 从CLinkList中移除所有元素
///
public void Clear()
{
Length = 0;
PRear = null;
}
}
}
应用:
using System;
using LinearStruct;
namespace ExampleList
{
class Program
{
static void Main(string[] args)
{
ListTest(new CLinkList<string>());
// 2
// a1
// a3
}
private static void ListTest(ILinearList<string> lst)
{
lst.Insert(0, "a1");
lst.Insert(1, "a2");
lst.Insert(2, "a3");
lst.Remove(1);
Console.WriteLine(lst.Length);
for (int i = 0; i < lst.Length; i++)
{
Console.WriteLine(lst[i]);
}
}
}
}
定义:每个结点含有两个链域(指针域)的链表。即:利用双链域的方式存储线性表的逻辑结构。
结构:
实现:
对结点的封装:
using System;
namespace LinearStruct
{
///
/// 双向链表结点
///
/// 结点中数据元素的类型
public class DNode<T> where T : IComparable<T>
{
///
/// 获取或设置该结点的前趋结点
///
public DNode<T> Prior {
get; set; }
///
/// 获取或设置该结点的后继结点
///
public DNode<T> Next {
get; set; }
///
/// 获取或设置该结点的数据元素
///
public T Data {
get; set; }
///
/// 初始化DNode类的新实例
///
/// 该结点的数据元素
/// 该结点的前趋结点
/// 该结点的后继结点
public DNode(T data, DNode<T> prior = null, DNode<T> next = null)
{
Prior = prior;
Data = data;
Next = next;
}
}
}
对双向链表的封装:
using System;
namespace LinearStruct
{
///
/// 用链式存储结构实现的线性表--双链表
///
/// 结点中数据元素的类型
public class DLinkList<T> : ILinearList<T> where T : IComparable<T>
{
///
/// 存储头结点
///
protected DNode<T> PHead {
get; set; }
///
/// 存储尾结点
///
protected DNode<T> PRear {
get; set; }
///
/// 获取DLinkList中实际包含元素的个数
///
public int Length {
get; private set; }
///
/// 初始化DLinkList类的新实例
///
public DLinkList()
{
PHead = null;
PRear = null;
Length = 0;
}
///
/// 将元素插入到双链表的首部
///
/// 要插入的元素
public void InsertAtFirst(T data)
{
if (IsEmpty())
{
DNode<T> temp = new DNode<T>(data);
PHead = temp;
PRear = temp;
}
else
{
DNode<T> temp = new DNode<T>(data, null, PHead);
PHead.Prior = temp;
PHead = temp;
}
Length++;
}
///
/// 将元素插入到双链表的尾部
///
/// 要插入的元素
public void InsertAtRear(T data)
{
if (IsEmpty())
{
DNode<T> temp = new DNode<T>(data);
PHead = temp;
PRear = temp;
}
else
{
DNode<T> temp = new DNode<T>(data, PRear, null);
PRear.Next = temp;
PRear = temp;
}
Length++;
}
///
/// 获得指定索引处的结点
///
/// 元素从零开始的索引
/// 指定索引处的结点
private DNode<T> Locate(int index)
{
if (index < 0 || index > Length - 1)
throw new IndexOutOfRangeException();
DNode<T> temp = PHead;
for (int i = 0; i < index; i++)
{
temp = temp.Next;
}
return temp;
}
///
/// 将元素插入到指定索引处
///
/// 从零开始的索引,应在该位置插入data.
/// 要插入的元素
public void Insert(int index, T data)
{
if (index < 0 || index > Length)
throw new IndexOutOfRangeException();
if (index == 0)
{
InsertAtFirst(data);
}
else if (index == Length)
{
InsertAtRear(data);
}
else
{
DNode<T> temp1 = Locate(index);
DNode<T> temp2 = new DNode<T>(data, temp1.Prior, temp1);
temp2.Prior.Next = temp2;
temp2.Next.Prior = temp2;
Length++;
}
}
///
/// 移除DLinkList指定索引处的元素
///
/// 要移除元素从0开始的索引
public void Remove(int index)
{
if (index < 0 || index > Length - 1)
throw new IndexOutOfRangeException();
if (Length == 1)
{
PHead = null;
PRear = null;
}
else
{
if (index == 0)
{
PHead = PHead.Next;
PHead.Prior = null;
}
else if (index == Length - 1)
{
PRear = PRear.Prior;
PRear.Next = null;
}
else
{
DNode<T> temp = Locate(index);
temp.Prior.Next = temp.Next;
temp.Next.Prior = temp.Prior;
}
}
Length--;
}
///
/// 判断DLinkList中是否包含元素
///
/// 如果包含元素返回false,否则返回true.
public bool IsEmpty()
{
return Length == 0;
}
///
/// 从DLinkList中移除所有元素
///
public void Clear()
{
Length = 0;
PHead = null;
PRear = null;
}
///
/// 在DLinkList中寻找元素data.
///
/// 要寻找的元素
/// 如果存在返回该元素在线性表中的位置,否则返回-1.
public int Search(T data)
{
int i;
DNode<T> temp = PHead;
for (i = 0; i < Length; i++)
{
if (temp.Data.CompareTo(data) == 0)
break;
temp = temp.Next;
}
return i == Length ? -1 : i;
}
///
/// 获取或设置指定索引处的元素
///
/// 要获得或设置的元素从零开始的索引
/// 指定索引处的元素
public T this[int index]
{
get
{
if (index < 0 || index > Length - 1)
throw new IndexOutOfRangeException();
return Locate(index).Data;
}
set
{
if (index < 0 || index > Length - 1)
throw new IndexOutOfRangeException();
Locate(index).Data = value;
}
}
}
}
应用:
using System;
using LinearStruct;
namespace ExampleList
{
class Program
{
static void Main(string[] args)
{
ListTest(new DLinkList<string>());
// 2
// a1
// a3
}
private static void ListTest(ILinearList<string> lst)
{
lst.Insert(0, "a1");
lst.Insert(1, "a2");
lst.Insert(2, "a3");
lst.Remove(1);
Console.WriteLine(lst.Length);
for (int i = 0; i < lst.Length; i++)
{
Console.WriteLine(lst[i]);
}
}
}
}
后台回复「搜搜搜」,随机获取电子资源!
欢迎关注,请扫描二维码: