何为线性表
线性表(List):零个或多个数据元素的有限序列。
线性表的实现方式有下面几种
顺序表
单链表 ( 双向链表 循环链表)
操作:
interface IListDS<T>
{
int GetLength(); //数据元素个数
void Clear(); //清空
bool IsEmpty(); //线性表是否为空
void Add(T item); //添加
void Insert(T item, int index);//插入
T Delete(int index); //删除
T this[int index] { get; } //查找(索引器)
T GetEle(int index); //查找 返回第index个位置元素
int Locate(T value); //查找 查找与给定值相等的元素
}
顺序存储
线性表的顺序存储结构,指的是用一段 地址连续的存储单元 依次存储线性表的数据元素。
存储结构:一维数组
三个属性:
1.存储空间的起始位置:数组data 它的存储位置就是存储空间的存储位置
2.线性表的最大存储容量:数组长度size
3.线性表的当前长度:count
/// 顺序表实现方式
class SeqList<T>:IListDS<T>
{
private T[] data; //1.用来存储数据 data
private int count = 0; //3.线性表当前长度count
public SeqList(int size) //2.最大容量size
{
data = new T[size];
count = 0;
}
//初始化操作
public SeqList():this(10)//默认构造函数 容量是10
{
}
//取得数据的个数
public int GetLength()
{
return count;
}
//清空
public void Clear()
{
count = 0;
}
//是否为空
public bool IsEmpty()
{
return count == 0;
}
//添加
public void Add(T item)
{
if (count == data.Length) //当前数组已经存满
{
Console.WriteLine("当前顺序表已经存满,不允许再存入");
}
else
{
data[count] = item;
count++;
}
}
//插入
public void Insert(T item, int index)
{
for (int i = count-1; i >=index; i--)
{
data[i + 1] = data[i];
}
data[index] = item;
count++;
}
//删除
public T Delete(int index)
{
T temp = data[index];
for (int i = index+1; i < count; i++)
{
data[i - 1] = data[i];// 把数据向前移动
}
count--;
return temp;
}
//查找(索引器)
public T this[int index]
{
get { return GetEle(index); }
}
//查找
public T GetEle(int index)
{
if (index >= 0 && index <= count - 1) //索引存在
{
return data[index];
}
else
{
Console.WriteLine("索引不存在");
return default(T);
}
}
//查找
public int Locate(T value)
{
for (int i = 0; i < count; i++)
{
if (data[i].Equals(value))
{
return i;
}
}
return -1;
}
}
分析:适合 元素个数变化不大、常存、取数据的应用
1.(查找)存、读 ,不管在那个位置,时间复杂度都为O(1);
2.插入、删除,时间复杂度O(n);插入或删除尾部数据元素时为O(1)。
优点:无须为表示表中元素之间的逻辑关系而增加额外的存储空间;可以快速的存取表中任一位置的与元素。
缺点:插入和删除操作需要移动大量元素;当线性表长度变化较大时,难以确定存储空间的容量;造成存储空间的碎片。
链式存储
单链表 采用链式存储结构,用一组任意的存储单元存放线性表的元素
数据域:存储数据元素信息的域 指针域:存储直接后继位置的域
结点:数据域和指针域组成数据元素ai的存储映像。
头指针与头结点:头指针即为头结点的指针域
存储结构:结点
1.数据data
2.指针next
class Node<T>
{
private T data; //1.数据data
private Node<T> next; //2.指针next 用来指向下一个元素
public Node()
{
data = default(T);
next = null;
}
public Node(T value)
{
data = value;
next = null;
}
public Node(T value, Node<T> next)
{
this.data = value;
this.next = next;
}
public Node(Node<T> next)
{
this.next = next;
}
public T Data
{
get { return data; }
set { data = value; }
}
public Node<T> Next
{
get { return next; }
set { next = value; }
}
}
链表实现
class LinkList<T>:IListDS<T>
{
private Node<T> head;//存储一个头结点
public LinkList() //初始化
{
head = null;
}
//取得数据个数
public int GetLength()
{
if (head == null) return 0;
Node<T> temp = head;
int count = 1;
while (true)
{
if (temp.Next != null)
{
count++;
temp = temp.Next;
}
else
{
break;
}
}
return count;
}
//清空
public void Clear()
{
head = null;
}
//是否为空
public bool IsEmpty()
{
return head == null;
}
//添加
public void Add(T item)
{
Node<T> newNode = new Node<T>(item);//根据新的数据创建一个新的节点
//如果头结点为空,那么这个新的节点就是头节点
if (head == null)
{
head = newNode;
}
else
{//把新来的结点放到 链表的尾部
//要访问到链表的尾结点
Node<T> temp = head;
while (true)
{
if (temp.Next != null)
{
temp = temp.Next;
}
else
{
break;
}
}
temp.Next = newNode;//把新来的结点放到 链表的尾部
}
}
//插入
public void Insert(T item, int index)
{
Node<T> newNode = new Node<T>(item);
if (index == 0) //插入到头节点
{
newNode.Next = head;
head = newNode;
}
else
{
Node<T> temp = head;
for (int i = 1; i <=index-1; i++)
{
//让temp向后移动一个位置
temp = temp.Next;
}
Node<T> preNode = temp;
Node<T> currentNode = temp.Next;
preNode.Next = newNode;
newNode.Next = currentNode;
}
}
//删除
public T Delete(int index)
{
T data = default(T);
if (index == 0) //删除头结点
{
data = head.Data;
head = head.Next;
}
else
{
Node<T> temp = head;
for (int i = 1; i <= index - 1; i++) {
//让temp向后移动一个位置
temp = temp.Next;
}
Node<T> preNode = temp;
Node<T> currentNode = temp.Next;
data = currentNode.Data;
Node<T> nextNode = temp.Next.Next;
preNode.Next = nextNode;
}
return data;
}
//查找(索引器)
public T this[int index]
{
get
{
Node<T> temp = head;
for (int i = 1; i <= index; i++) {
//让temp向后移动一个位置
temp = temp.Next;
}
return temp.Data;
}
}
//查找
public T GetEle(int index)
{
return this[index];
}
//查找
public int Locate(T value)
{
Node<T> temp = head;
if (temp == null)
{
return -1;
}
else
{
int index = 0;
while (true)
{
if (temp.Data.Equals(value))
{
return index;
}
else
{
if (temp.Next != null)
{
temp = temp.Next;
}
else
{
break;
}
}
}
return -1;
}
}
}
分析:元素个数变化大、不知道有多大 频繁插入、删除数据
1.(查找):O(n)
2.插入、删除:从整个算法O(n)。但是从第i位置插入多个结点,只需第一次找到第i位置的指针,此时O(n),接下来只是简单的通过赋值移动指针,此时O(1)
与顺序表比较
存储分配方式 时间性能 空间性能