线性表是最简单最基本的一种数据结构,线性表中的数据元素都存在一对一的关系,属于线性结构,是有顺序有先后关系的,除了第一个元素外,其他数据元素前只有一个数据元素(前驱),除了最后一个元素外,其他数据元素后只有一个数据元素(后驱)
用一段地址连续的存储单元依次存储线性表中的数据元素
线性表的顺序存储结构在读、存数据时,时间复杂度都是O(1),我们把读、存数据时时间复杂度为O(1)的存储结构称为随机存储结构
在插入、删除数据时,时间复杂度是O(n),数组就是线性表的顺序存储结构的体现,这也是为什么数组比较适合元素个数不太变化,更多的是存取数据的应用
引言:对于线性表的顺序存储结构,当元素个数不太变化时很适用,但是当我们插入、删除数据时,有可能会移动大量的数据,从而耗费时间,根本原因在于顺序存储结构中数据与数据之间的存储位置是连续的,当我们插入、删除数据时,也要让线性表中的数据仍然保持内存的连续,既然这样,我们可以不考虑内存的连续,只是让每个元素知道它下一个元素的地址就可以,这就是线性表的链式存储结构(链表)
为了表示ai与ai+1之间的关系,对于ai来说,除了存储本身的信息外,还需要存储一个指向它直接后继的信息(直接后继的地址),我们把存储本身数据信息的域称为数据域,把存储直接后继位置的域称为指针域,数据域与指针域组成了ai的存储映像,称为结点,n个结点组成为一个链表,也就是线性表的链式存储结构(链表)。又因为此链表中的每个结点只包含一个指针域(只能指向直接后驱),所以称为单链表
我们把线性表的链式存储结构中指向第一个结点的指针称为头指针,链表的存储从头指针开始进行,之后的每一个结点都是上一个的指针指向的地址,规定最后一个的结点的指针域为NULL,有时候为了方便操作,会在第一个结点前附设一个结点,称为头结点,头结点的数据域可以不存储任何信息(也可以存储线性表的公共数据),头结点的指针域(也就是头指针)指向第一个结点的地址,就算线性单链表为空,头指针也不能为空,但是头结点是附设的可以没有
线性表的链式存储结构对于插入、删除数据越频繁的操作优势越是明显
——静态链表
引言:对于C、C++来说,它具有指针,可以方便地操作内存中的地址和数据,而对于C#、Java等面向对象的语言,虽然没有指针但是可以利用引用间接地实现指针的作用,但是对于早期的一些编程语言,例如Basic、Fortran等,由于没有指针也不是面向对象语言,所以前人就想出了用数组代替指针,我们把这种描述方式称为游标实现法,把这种用数组描述的链表称为静态链表
首先让数组中的每个元素都是由两个数据域组成,data和cur,data存储数据元素,cur存储下一个元素在数组中的下标(与单链表中的next指针作用相同),把未被使用的数组元素称为备用链表,另外对数组中的第一个和最后一个元素进行特殊处理,都不存储数据,第一个元素的cur存储第一个备用链表的下标,最后一个元素的cur存储第一个有数值的元素的下标(与头结点作用相同),当某一个元素的cur为0时,则此元素是静态链表中最后一个有数值的元素
——循环链表
引言:对于单链表,我们无法从中间某个结点开始遍历到整个链表的结点,所以引出了循环链表
将单链表中的最后一个结点由空指针改为指向头结点的指针,使整个单链表形成了一个环,这样头尾相连的单链表称为循环链表
循环链表与单链表最主要的差别就在于循环的判断条件上,单链表是判断结点的指针指向是否为空,而循环链表是判断结点的指针指向是否为头结点
——双向链表
引言:对于单链表,我们无法从某个结点访问到前驱的结点,所以引出了双向链表
将单链表的每个结点中,再设置一个指向其直接前驱的指针域,相当于每个结点有两个指针域,一个指向直接前驱,一个指向直接后驱,这样的链表称为双向链表
双向链表与单链表最主要的差别就在于插入、删除元素上,需要更改两个指针的指向
using System;
//顺序表类
public class LinearList
{
//存储顺序表中元素的数组
private T[] array;
//顺序表中元素的个数
private int count;
public int Count
{
get
{
return count;
}
}
//构造器初始化
public LinearList()
{
array = new T[0];
}
public LinearList(int size)
{
array = new T[size];
}
//判断顺序表是否已满
private bool IsFull()
{
return count >= array.Length;
}
//判断索引是否正确
private bool IndexIsVaild(int index)
{
return index >= 0 && index <= array.Length - 1;
}
//得到顺序表长度
public int GetLength()
{
return count;
}
//清空顺序表
public void Clear()
{
for (int i = 0; i < count; i++)
{
array[i] = default(T);
}
count = 0;
}
//添加元素
public void AddItem(T item)
{
if (!IsFull())
{
array[count] = item;
count++;
}
else
{
throw new Exception("表已满");
}
}
//得到元素(不通过索引器)
public T GetItem(int index)
{
if (IndexIsVaild(index))
{
return array[index];
}
else
{
throw new Exception("索引超出范围");
}
}
//得到元素(通过索引器)
public T this[int index]
{
get
{
if (IndexIsVaild(index))
{
return array[index];
}
else
{
throw new Exception("索引超出范围");
}
}
set
{
if (!IsFull())
{
array[index] = value;
}
else
{
throw new Exception("顺序表当前已满");
}
}
}
//判断顺序表是否为空
public bool IsEmpty()
{
return count == 0;
}
//插入元素
public void Insert(int index, T item)
{
if (!IsFull() == false)
{
if (IndexIsVaild(index))
{
for (int i = count - 1; i >= index; i--)
{
array[i + 1] = array[i];
}
array[index] = item;
count++;
}
else
{
throw new Exception("索引超出范围");
}
}
else
{
throw new Exception("顺序表当前已满");
}
}
//移除元素(通过指定位置)
public void RemoveAt(int index)
{
if (IndexIsVaild(index))
{
for (int i = index + 1; i < count; i++)
{
array[index - 1] = array[index];
}
count--;
}
else
{
throw new Exception("索引超出范围");
}
}
//移除元素(通过指定元素)
public void Remove(T item)
{
int index = 0;
for (int i = 0; i < count; i++)
{
if (array[i].Equals(item))
{
index = i;
}
}
RemoveAt(index);
}
//获取元素位置
public int IndexOf(T item)
{
for (int i = 0; i < count; i++)
{
if (array[i].Equals(item))
{
return i;
}
}
return -1;
}
}
class Program
{
//*****进行测试*****
static void Main(string[] args)
{
LinearList myList = new LinearList(5);
myList.AddItem(1);
myList[1] = 2;
myList.Insert(1, 3);
myList.Remove(1);
myList.RemoveAt(1);
}
}
using System;
//结点类
public class Node
{
//存储数据(数据域)
public T Data { get; set; }
//存储下一个结点的地址(指针域)——引用
public Node Next { get; set; }
//构造器初始化
public Node()
{
this.Data = default(T);
Next = null;
}
public Node(T value)
{
this.Data = value;
Next = null;
}
public Node(T value, Node next)
{
this.Data = value;
this.Next = next;
}
public Node(Node next)
{
this.Next = next;
}
}
//链表类
public class LinearList
{
//头结点
private Node head;
//链表长度
private int length;
public int Length
{
get
{
return length;
}
}
//构造器初始化
public LinearList()
{
head = null;
}
//得到链表长度
public int GetLength()
{
return length;
}
//判断索引是否正确
private bool IndexIsVaild(int index)
{
return index >= 0 && index <= length - 1;
}
//添加元素
public void AddItem(T item)
{
Node newNode = new Node(item);
if (head == null)
{
head = newNode;
}
else
{
Node temp = head;
while (true)
{
if (temp.Next != null)
{
temp = temp.Next;
}
else
{
break;
}
}
temp.Next = newNode;
}
length++;
}
//插入元素
public void Insert(int index, T item)
{
Node newNode = new Node(item);
if (index == 0)
{
newNode.Next = head;
head = newNode;
length++;
}
else
{
if (IndexIsVaild(index))
{
Node temp = head;
for (int i = 1; i <= index - 1; i++)
{
temp = temp.Next;
}
Node preNode = temp;
Node nextNode = temp.Next;
preNode.Next = newNode;
newNode.Next = nextNode;
length++;
}
else
{
throw new Exception("索引超出范围");
}
}
}
//删除元素
public void Remove(int index)
{
if (IndexIsVaild(index))
{
if (index == 0)
{
head = head.Next;
}
else
{
Node temp = head;
for (int i = 1; i <= index - 1; i++)
{
temp = temp.Next;
}
Node preNode = temp;
Node nextNode = temp.Next.Next;
preNode.Next = nextNode;
}
length--;
}
else
{
throw new Exception("索引超出范围");
}
}
//清空链表
public void CLear()
{
head = null;
}
//获取元素(通过索引器)
public T this[int index]
{
get
{
if (IndexIsVaild(index))
{
Node temp = head;
for (int i = 1; i <= index; i++)
{
temp = temp.Next;
}
return temp.Data;
}
else
{
throw new Exception("索引超出范围");
}
}
set
{
if (IndexIsVaild(index))
{
Node newNode = new Node(value);
Node temp = head;
for (int i = 1; i <= index - 1; i++)
{
temp = temp.Next;
}
Node preNode = temp;
Node nextNode = temp.Next.Next;
preNode.Next = newNode;
newNode.Next = nextNode;
}
else
{
throw new Exception("索引超出范围");
}
}
}
//获取元素(不通过索引器)
public T GetItem(int index)
{
if (IndexIsVaild(index))
{
Node temp = head;
for (int i = 1; i < index; i++)
{
temp = temp.Next;
}
return temp.Data;
}
else
{
throw new Exception("索引超出范围");
}
}
//获取元素位置
public int IndexOf(T item)
{
int index = 0;
Node temp = head;
while (true)
{
if (temp.Data.Equals(item))
{
return index;
}
else
{
if (temp.Next != null)
{
temp = temp.Next;
index++;
}
else
{
break;
}
}
}
return -1;
}
//判断链表是否为空
public bool IsEmpty()
{
return length == 0 || head == null;
}
}
class Program
{
//*****进行测试*****
public static void Main(string[] args)
{
LinearList myList = new LinearList();
myList.AddItem(1);
myList.AddItem(2);
myList[1] = 3;
myList.Insert(1, 4);
myList.Remove(2);
}
}