线性表
- 线性表的定义:
Linear List
是由n个相同类型的数据元素a0,a1,...a(n-1)
组成的序列,即表中除首尾元素外,其他元素有且仅有一个直接前驱和直接后继。首元素仅有一个直接后继,尾元素仅有一个直接前驱 - 表中数据元素的个数称为表的长度
线性表的操作
- 随机存取:获取或设置指定索引处的数据元素值(支持索引器)
- 插入操作:将数据元素值插入到指定索引处
- 移除操作:移除线性表指定索引处的数据元素
- 查找操作:寻找具有特征值域的结点并返回其下标
- 得到表长:获取线性表中实际包含数据元素的个数
- 是否为空:判断线性表中是否包含数据元素
- 清空操作:移除线性表中的所有数据元素
using System;
using System.Collections.Generic;
using System.Text;
namespace DataStruct2020.demo
{
public interface ILinearList<T>
{
int Length { get; }
T this[int index] { get; set; }
void Clear();
void Insert(int index, T data);
bool IsEmpty();
void Remove(int index);
int Search(T data);
}
}
- 泛型约束:
public interface ILinearList<T> where T : IComparable<T>
线性表的存储与实现
顺序存储Sequence List
- 顺序存储:顺序表,逻辑结构与物理结构相同
顺序表: - 定义:利用顺序存储结构(即利用数组)实现的线性表
- 特点:逻辑结构与存储结构相同,具有随机存取的特点,但需要一块连续的存储空间
//接口比较简单,略
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace DataStruct2020.demo
{
public class SeqList<T> : ILinearList<T> where T : IComparable<T>
{
private T[] _dataset;
private int _maxSize;
private int _length;
public int Length
{
get
{
return _length;
}
}
public int MaxSize
{
get
{
return _maxSize;
}
}
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 ArgumentOutOfRangeException();
return _dataset[index];
}
set
{
if (index < 0 || index > _length - 1)
throw new ArgumentOutOfRangeException();
_dataset[index] = value;
}
}
public void Clear()
{
_length = 0;
}
public void Insert(int index, T data)
{
if (index < 0 || index > _length)
throw new ArgumentOutOfRangeException();
if (_length == MaxSize)
throw new Exception("数组存放已满");
for (int i = _length; i > index; i--)
{
_dataset[i] = _dataset[i - 1];
}
_dataset[index] = data;
_length++;
}
public bool IsEmpty()
{
return _length == 0;
}
public void Remove(int index)
{
if (index < 0 || index > _length - 1)
throw new ArgumentOutOfRangeException();
for (int i = index; i < _length - 1; i++)
{
_dataset[i] = _dataset[i + 1];
}
_length--;
}
public int Search(T data)
{
if (data == null)
throw new ArgumentNullException();
int i;
for (i = 0; i < _length; i++)
{
if (_dataset[i].CompareTo(data) == 0)
break;
}
return i == _length ? -1 : i;
}
}
}
using System;
using DataStruct2020.demo;
namespace DataStruct2020
{
class Program
{
static void Main(string[] args)
{
ILinearList<int> lst = new SeqList<int>(200);
lst.Insert(0, 100);
lst.Insert(1, 200);
lst.Insert(2, 300);
lst.Remove(1);
for (int i = 0; i < lst.Length; i++)
{
Console.WriteLine(lst[i]);
}
}
}
}
//
100
300
- 自定义的泛型也要实现
Comparable
接口
{
public class Student :IComparable<Student>
{
private string _name;
private int _age;
private long _id;
public Student(string name, int age,long id)
{
_name = name;
_age = age;
_id = id;
}
public int CompareTo([AllowNull] Student other)
{
if (other._id == _id)
return 0;
return -1;
}
public override string ToString()
{
return string.Format("Name :{0},Age:{1}" ,_name,_age);
}
}
链式存储
- 链式存储:利用该存储方是实现的线性表称为链表(单链表、循环链表、双链表)。他不要求逻辑上相邻的数据元素在物理位置上也相邻,即:逻辑结构与物理结构可以相同也可以不同
- 除了存储本身的数据外,还要存储下一个结点的地址(可以不用占据大量的存储空间)
- 单链表:每个结点只含有一个指针域的链表。即:利用单链域的方式存储线性表的逻辑结构
//结点类
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace DataStruct2020.demo
{
public class SNode<T>where T : IComparable<T>
{
public T Data { get; set; }
public SNode<T> Next { get; set; }
public SNode(T data)
{
Data = data;
Next = null;
}
public SNode(T data, SNode<T> next)
{
Data = data;
Next = next;
}
public int CompareTo(T other)
{
throw new NotImplementedException();
}
}
}
//单链表的链式存储
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace DataStruct2020.demo
{
public class SLinkList<T> : ILinearList<T> where T : IComparable<T>
{
private SNode<T> _pHead;
private int _length;
public SNode<T> PHead
{
get { return _pHead; }
}
public T this[int index]
{
get
{
if (index < 0 || index > _length - 1)
throw new ArgumentOutOfRangeException();
return Locate(index).Data;
}
set
{
if (index < 0 || index > _length - 1)
throw new ArgumentOutOfRangeException();
Locate(index).Data = value;
}
}
public int Length
{
get
{
return _length;
}
}
public SLinkList()
{
_pHead = null;
_length = 0;
}
public void InsertAtFirst(T data)
{
_pHead = new SNode<T>(data, _pHead);
_length++;
//两种方式一样的代码:链表为空,链表非空
//if (_length == 0)
//{
// _pHead = new SNode<T>(data, null);
//}
//else
//{
// _pHead = new SNode<T>(data, _pHead);
//}
}
public SNode<T> Locate(int index)
{
if (index < 0 || index > Length - 1)
throw new ArgumentOutOfRangeException();
int i = 0;
SNode<T> temp = _pHead;
for (; i < index; i++)
{
temp = temp.Next;
}
return temp;
}
public void InsertAtRear(T data)
{
if (_length == 0)
{
_pHead = new SNode<T>(data);
}
else
{
Locate(_length - 1).Next = new SNode<T>(data);
}
_length++;
}
public void Insert(int index, T data)
{
if (index < 0 || index > _length)
throw new ArgumentOutOfRangeException();
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);
//Locate(index - 1).Next = new SNode<T>(data, Locate(index));
_length++;
}
}
public void Clear()
{
_pHead = null;
_length = 0;
}
public bool IsEmpty()
{
return _length == 0;
}
public void Remove(int index)
{
if (index < 0 || index > _length - 1)
throw new ArgumentOutOfRangeException();
else if (index == 0)
{
_pHead = _pHead.Next;
_length--;
}
else
{
SNode<T> temp = Locate(index - 1);
temp.Next = temp.Next.Next;
_length--;
}
}
public int Search(T data)
{
SNode<T> temp = _pHead;
int i = 0;
for (; i < _length; i++)
{
if (temp.Data.CompareTo(data) == 0)
break;
temp = temp.Next;
}
return i == _length ? -1 : i;
}
}
}
- 循环链表:是一种首尾相连的单链表。即:在单链表中,将尾结点的指针域
null
改为指向pHead
,就得到单链形式的循环链表
//循环链表
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace DataStruct2020.demo
{
public class CLinkList<T> : ILinearList<T> where T : IComparable<T>
{
//private SNode<T> _pHead;
private SNode<T> _pRear;
private int _length;
public CLinkList()
{
_length = 0;
_pRear = null;
}
public void InsertAtRear(T data)
{
if (_length == 0)
{
_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 InsertAtHead(T data)
{
if (_length == 0)
{
_pRear = new SNode<T>(data);
_pRear.Next = _pRear;
}
else
{
SNode<T> temp = new SNode<T>(data,_pRear.Next);
_pRear.Next = temp;
}
_length++;
}
public SNode<T> Locate(int index)
{
if (index < 0 || index > _length - 1)
throw new ArgumentOutOfRangeException();
SNode<T> temp = _pRear.Next;
for (int i = 0; i < index; i++)
{
temp = temp.Next;
}
return temp;
}
public void Insert(int index,T data)
{
if (index < 0 || index > _length)
throw new ArgumentOutOfRangeException();
if (index == 0)
InsertAtHead(data);
else if (index == Length)
InsertAtRear(data);
else
{
SNode<T> temp = Locate(index - 1);
temp.Next = new SNode<T>(data,temp.Next);
_length++;
}
}
public T this[int index]
{
get
{
if (index < 0 || index > _length - 1)
throw new ArgumentOutOfRangeException();
return Locate(index).Data;
}
set
{
if (index < 0 || index > _length - 1)
throw new ArgumentOutOfRangeException();
Locate(index).Data = value;
}
}
public int Length
{
get { return _length; }
}
public void Clear()
{
_length = 0;
_pRear = null;
}
public bool IsEmpty()
{
return _length == 0;
}
public void Remove(int index)
{
if (index < 0 || index > _length - 1)
throw new ArgumentOutOfRangeException();
if (index == 0)
_pRear.Next = _pRear.Next.Next;
else if (index == _length - 1)
{
SNode<T> temp = Locate(index - 1);
temp.Next = _pRear.Next;
_pRear = temp;
}
else if (_length == 1)
{
_pRear = null;
}
else
{
SNode<T> temp = Locate(index - 1);
temp.Next = temp.Next.Next;
}
_length--;
}
public int Search(T data)
{
SNode<T> temp = _pRear;//不能使temp是头结点因为_pRear可能为空
int i;
for (i = 0; i < _length; i++)
{
if (temp.Next.Data.CompareTo(data) == 0)
break;
temp = temp.Next;
}
return i == _length ? -1 : i;
}
}
}
//客户端
ILinearList<Student> lst;
lst = new CLinkList<Student>();
lst.Insert(0, new Student("test 01", 10, 10086));
lst.Insert(1, new Student("test 02", 10, 95588));
lst.Insert(2, new Student("test 03", 10, 12345));
lst.Remove(2);
for (int i = 0; i < lst.Length; i++)
{
Console.WriteLine(lst[i]);
}
int j = lst.Search(new Student("test 01", 10, 10086));
Console.WriteLine(j);
//
Name :test 01,Age:10
Name :test 02,Age:10
0
- 双链表:每个结点含有两个指针域的链表。即:利用双链域的方式存储线性表的逻辑结构
//定义结点
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace DataStruct2020.demo
{
public class DNode<T>where T : IComparable<T>
{
private T _data;
private DNode<T> _prior;
private DNode<T> _next;
public T Data
{
get { return _data; }
set { _data = value; }
}
public DNode<T> Prior
{
get { return _prior; }
set { _prior = value; }
}
public DNode<T> Next
{
get { return _next; }
set { _next = value; }
}
/*
public DNode(T data)
{
_data = data;
_prior = null;
_next = null;
}
*/
public DNode(T data, DNode<T> prior = null, DNode<T> next = null)
{
_prior = prior;
_data = data;
_next = next;
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace DataStruct2020.demo
{
public class DLinkList<T> : ILinearList<T> where T : IComparable<T>
{
private DNode<T> _pHead;
private DNode<T> _pRear;
private int _length;
public int Length
{
get { return _length;}
}
public DLinkList()
{
_pHead = null;
_pRear = null;
_length = 0;
}
public void InsertAtFirst(T data)
{
if (_length == 0)
{
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 (_length == 0)
{
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 ArgumentOutOfRangeException();
DNode<T> temp = _pHead;
for(int i = 0; i < index; i++)
{
temp = temp.Next;
}
return temp;
}
public void Insert(int index, T data)
{
if (index < 0 || index > _length)
throw new ArgumentOutOfRangeException();
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++;
}
}
public T this[int index]
{
get
{
if (index < 0 || index > _length - 1)
throw new ArgumentOutOfRangeException();
return Locate(index).Data;
}
set
{
if (index < 0 || index > _length - 1)
throw new ArgumentOutOfRangeException();
Locate(index).Data = value;
}
}
public void Clear()
{
_length = 0;
_pHead = null;
_pRear = null;
}
public bool IsEmpty()
{
return _length == 0;
}
public void Remove(int index)
{
if (index < 0 || index > _length - 1)
throw new ArgumentOutOfRangeException();
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--;
}
public int Search(T data)
{
DNode<T> temp = _pHead;
int i;
for(i = 0;i < _length; i++)
{
if (temp.Data.CompareTo(data) == 0)
break;
temp = temp.Next;
}
return i == _length ? -1 : i;
}
}
}