- 线性表的定义:线性表是一个具有n(n>=0)个数据元素的线性关系有限序列。元素的个数为线性表的长度,当n=0时,线性表为空表,用一对空括号表示;当n!=0时,线性表可以表示为(a1,a2,a3,…an),a1为表头元素,an为表尾元素,an-1是an的直接前驱,an+1是an的直接后继。
- 线性表的数据元素:可以为一个数,也可以为一个符号或者复杂数据类型,但同一个线性表中的元素必须具有相同的特性。
- 例如:线性表1:字母表(a,b,c…z)线性表2:数字表 (2,5,9,1,0)线性表2:线性表中数据元素为复杂类型的表 新生报道表
- 线性表的逻辑结构:线性表的逻辑结构为线性结构,元素之间是一对一的关系。
- 数组 & 链表 之前的绪论部分我们已经谈到链式存储结构的定义,即不要求逻辑上相邻的元素在物理层面也相邻,顾名思义就是利用链表存储数据,它用附加指针表示节点间的逻辑关系。
数组优点:
- 随机访问,通过索引访问数组数据,由于是连续的内存空间,所以支持随机访问,通过下标随机访问的时间复杂度是 O (1)。
- 查找快,可以通过数组的所以快速定位到要查找的数据
- 支持动态扩容,当我们开始预定义数组的长度是 10,当数组存储了 10 个数据后,我们继续添加第 11 个数据的时候,我们就需要重新分配一块更大的空间,将原来的数据复制过去,然后再将新的数据插入
数组缺点:
- 插入、删除数据慢,因为数组连续的内存空间,所以在插入一个数据的时候会使插入位置后面的每个数据都向后位移一个位置,所以比较低效,删除同理,会使删除位置之后的每个数据向前位移一个。
- 操作不当会引起数组的访问越界问题,比如我定义的数组长度是 10,索引长度从 0~9,但是当我访问位置 10 的时候,超过数组长度,所以会发生越界问题
- 查询某个元素是否存在时需要遍历整个数组,耗费 O (n) 的时间。
- 删除和添加某个元素时,同样需要耗费 O (n) 的时间
单链表优点:
- 插入和删除快,和数组相比,链表的插入和删除不需要其他的节点的位移,我们只需要修改节点之间的 next 指针指向,就可以完成插入和删除,时间复杂度已经是 O (1)
- 链表能灵活地分配内存空间。
单链表缺点:
- 查询相比数组低效,因为链表的内存地址不是连续的,所以不能像数组一样通过索引随机访问,所以链表在查找某个节点时候只能通过从头遍历链表节点来查找。
- 查询第 n 个元素需要 O (n) 时间
namespace Class
{
interface IList_iter //接口名称
{
//接口
int GetLength(); //获取长度
void Clear(); //清空操作
bool IsEmpty(); //判断是否为Null
void Adds(T item); //添加操作
void Insert(T item, int Index); //插入操作
T Delete(int Index); //删除操作
T GetEle(int Index); // 索引器
}
class SeqList : IList
{
//存储数据
private T[] Date;
private int Count = 0; //来表示存了多少个数据
public SeqList(int Size) //构造函数
{
Date = new T[Size];
Count = 0;
}
public SeqList() : this(10) //默认构造函数容量为10
{
}
public void Adds(T item)
{
if (Count == Date.Length)
{
Console.WriteLine("当前数组已经存满了");
}else
{
Date[Count] = item;
Count++;
}
}
public void Clear()
{
throw new NotImplementedException();
}
public T Delete(int Index)
{
T Temp = Date[Index];
for (int i = Index+1; i < Count; i++)
{
Date[i - 1] = Date[i];
//将数据向前移动
}
Count--;
return Temp;
}
public T GetEle(int Index)
{
//取的操作
if (Count>=0&&Index<=(Count-1)))
{
//说明索引是存在的
return Date[Index];
}
else
{
return default(T);//自动获取数值的默认值
}
}
public int GetLength()
{
return Count;
}
public void Insert(T item, int Index)
{
//
for (int i = Count-1; i > Date.Length ; i--)
{
Date[i + 1] = Date[i];
}
Date[Index] = item;
Count++;
}
public bool IsEmpty()
{
if (Count-1>=0)
{
return true;
}
else
{
return false;
}
}
}
}
单向链表
双向链表 双向链表中存在两个指针域,一个指向直接后继,一个指向直接前驱。
循环链表
循环链表时另一种链式存储结构,它的特点是最后一个节点的指针指向头节点,整个链表形成一个环。循环链表可有单链的循环链表,也可以有多重链的循环链表。
循环双链表
循环双链表不仅尾结点指向头结点,且头结点的prior指向尾结点,判断为空时,只要看尾结点下一个是否指向头结点
静态链表
是用数组来表示链表,用数组元素的下标来模拟链表的指针.
由于是利用数组来定义的链表,属于静态储存分配, 因而叫做静态链表.
部分算法题目 --力扣