数据结构 线性表
什么是线性表:线性表(List)是由 n(n≥ 0)个相同类型的数据元素构成的有限序列
线性表中的数据元素之间存在着前后次序的位置关系,将ai-1称为ai的直接前
驱,将ai 称为ai+1 的直接后继。除a1 外,其余元素只有一个直接前驱,因为a1 是第
一个元素,所以它没有前驱。除an外,其余元素只有一个直接后继,因为an 是最
后一个元素,所以它没有后继。
线性表的形式化定义为:线性表(List)简记为L,是一个二元组,
L = (D, R)
其中:D 是数据元素的有限集合。
R 是数据元素之间关系的有限集合。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 ///定义接口 2 public interface IListDS<T> 3 { 4 int GetLength(); //求长度 5 void Clear(); //清空操作 6 bool IsEmpty(); //判断线性表是否为空 7 void Append(T item); //附加操作 8 void Insert(T item, int i); //插入操作 9 T Delete(int i); //删除操作 10 T GetElem(int i); //取表元 11 int Locate(T value); //按值查找 12 }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 实现接口 2 public class SeqList<T>:IListDS<T> 3 { 4 private int maxSize;//顺序表的容量 5 6 public int MaxSize 7 { 8 get { return maxSize; } 9 set { maxSize = value; } 10 } 11 private int last;//最后一个元素的位置 0开始 12 13 public int Last 14 { 15 get { return last; } 16 } 17 private T[] date;//数组,用于存储顺序表中的数据元素 18 public SeqList(int size) 19 { 20 maxSize = size; 21 date = new T[size]; 22 last = -1; 23 } 24 25 #region IListDS<T> 成员 26 27 28 public int GetLength() 29 { 30 return last + 1; 31 } 32 33 public void Clear() 34 { 35 last = -1; 36 } 37 38 public bool IsEmpty() 39 { 40 if (last == -1) return true; 41 else return false; 42 } 43 44 public void Append(T item) 45 { 46 date[++last] = item; 47 } 48 49 public void Insert(T item, int i) 50 { 51 if (i < 1 || i > last + 2) 52 { 53 return; 54 } 55 else if (i == last + 2) 56 { 57 date[++last] = item; 58 } 59 else 60 { 61 for (int j = last; j <= i - 1; j--) 62 { 63 date[j + 1] = date[j]; 64 } 65 date[i - 1] = item; 66 } 67 ++last; 68 } 69 70 public T Delete(int i) 71 { 72 T tmp = default(T); 73 if (i < 1 || i > last + 2) 74 { 75 return; 76 } 77 if (i == last + 1) 78 { 79 tmp = data[last--]; 80 } 81 else 82 { 83 tmp = data[i - 1]; 84 for (int j = i; j <= last; ++j) 85 { 86 data[j] = data[j + 1]; 87 } 88 } 89 return tmp; 90 } 91 92 public T GetElem(int i) 93 { 94 if (i < 1 || i > last + 1) 95 { 96 return; 97 } 98 return date[i - 1]; 99 } 100 101 public int Locate(T value) 102 { 103 int i=0; 104 for (i = 0; i < last; i++) 105 { 106 if (value.Equals(date[i])) 107 108 { 109 break; 110 } 111 } 112 return i; 113 } 114 115 #endregion 116 }
1、求顺序表的长度
由于数组是 0 基数组,即数组的最小索引为 0,所以,顺序表的长度就是数
组中最后一个元素的索引 last 加 1。
求顺序表长度的算法实现如下:
数据结构(C#语言版)
2.2 顺序表 30
public int GetLength()
{
return last+1;
}
2、清空操作
清除顺序表中的数据元素是使顺序表为空,此时,last 等于-1。
清空顺序表的算法实现如下:
public void Clear()
{
last = -1;
}
3、判断线性表是否为空
如果顺序表的 last 为-1,则顺序表为空,返回 true,否则返回 false。
判断线性表是否为空的算法实现如下:
public bool IsEmpty()
{
if (last == -1)
{
return true;
}
else
{
return false;
}
}
4、判断顺序表是否为满
如果顺序表为满,last 等于 maxsize-1,则返回 true,否则返回 false。
判断顺序表是否为满的算法实现如下:
public bool IsFull()
{
if (last == maxsize - 1)
{
return true;
}
else
{
return false;
}
}
5、附加操作
附加操作是在顺序表未满的情况下,在表的末端添加一个新元素,然后使顺
序表的last加1。
附加操作的算法实现如下:
public void Append(T item)
数据结构(C#语言版)
2.2 顺序表 31
{
if(IsFull())
{
Console.WriteLine("List is full");
return;
}
data[++last] = item;
}
6、插入操作
顺序表的插入是指在顺序表的第i个位置插入一个值为item的新元素,插入后
使原表长为n的表(a1,a2,…,ai-1,ai,ai+1,…,an)成为表长为n+1 的表
(a1,a2,…,ai-1,item,ai,ai+1,…,an)。i的取值范围为 1≤i≤n+1,i为n+1 时,表示
在顺序表的末尾插入数据元素。
顺序表上插入一个数据元素的步骤如下:
(1)判断顺序表是否已满和插入的位置是否正确,表满或插入的位置不正
确不能插入;
(2)如果表未满和插入的位置正确,则将an~ai依次向后移动,为新的数据
元素空出位置。在算法中用循环来实现;
(3)将新的数据元素插入到空出的第 i 个位置上;
(4)修改 last(相当于修改表长),使它仍指向顺序表的最后一个数据元
素。
图 2.2 为顺序表的插入操作示意图。
插入 30
↓
11 23 36 45 80 60 40 6 …
(a) 插入前
11 23 36 45 80 60 40 6 …
(b) 移动
11 23 36 30 45 80 60 40 6 …
(c) 插入后
图 2.2 顺序表的插入操作示意图
插入操作的算法实现如下,程序中需要注意的是位置变量 i 的初始值为 1
而不是 0:
public void Insert(T item, int i)
{
// 判断顺序表是否已满
if (IsFull())
{
数据结构(C#语言版)
2.2 顺序表 32
Console.WriteLine("List is full");
return;
}
// 判断插入的位置是否正确,
// i小于1表示在第1个位置之前插入,
// i大于last+2 表示在最后一个元素后面的第2个位置插入。
if(i<1 || i>last+2)
{
Console.WriteLine( "Position is error! ");
return;
}
// 在顺序表的表尾插入数据元素
if (i == last +2)
{
data[i-1] = item;
}
else //在表的其它位置插入数据元素
{
// 元素移动
for (int j = last; j>= i-1; --j)
{
data[j + 1] = data[j];
}
//将新的数据元素插入到第i 个位置上
data[i-1] = item;
}
// 修改表长
++last;
}
算法的时间复杂度分析:顺序表上的插入操作,时间主要消耗在数据的移动
上,在第i 个位置插入一个元素,从ai到an都要向后移动一个位置,共需要移动n-i+1
个元素,而i 的取值范围为 1≤i≤n+1,当i等于 1 时,需要移动的元素个数最多,
为n个;当i为n+1 时,不需要移动元素。设在第i 个位置做插入的概率为pi,则平
均移动数据元素的次数为n/2。这说明:在顺序表上做插入操作平均需要移动表
中一半的数据元素,所以,插入操作的时间复杂度为O(n)。
7、删除操作
顺序表的删除操作是指将表中第i个数据元素从顺序表中删除,删除后使原表
长为n的表(a1,a2,…,ai-1,ai, a i+1,…,an)变为表长为n-1 的表
(a1,a2,…,ai-1,ai+1,…,an)。i的取值范围为 1≤i≤n,i为n时,表示删除顺序表末
尾的数据元素。
数据结构(C#语言版)
2.2 顺序表 33
顺序表上删除一个数据元素的步骤如下:
(1)判断顺序表是否为空和删除的位置是否正确,表空或删除的位置不正
确不能删除;
(2)如果表未空和删除的位置正确,则将ai+1 ~an 依次向前移动。在算法中
用循环来实现;
(3)修改 last(相当于修改表长),使它仍指向顺序表的最后一个元素。
图 2.3 为顺序表的删除操作示意图。
删除 45
↓
11 23 36 45 80 60 40 6 …
(a) 删除前
11 23 36 80 60 40 6 …
(b) 删除后
图 2.3 顺序表的删除操作示意图
删除操作的算法实现如下:
public T Delete(int i)
{
T tmp = default(T);
// 判断表是否为空
if (IsEmpty())
{
Console.WriteLine("List is empty");
return tmp;
}
// 判断删除的位置是否正确
// i小于1表示删除第1个位置之前的元素,
// i大于last+1 表示删除最后一个元素后面的第1个位置的元素。
if (i < 1 || i > last+1)
{
Console.WriteLine( "Position is error! ");
return tmp;
}
// 删除的是最后一个元素
if (i == last+1)
{
tmp = data[last--];
return tmp;
}
数据结构(C#语言版)
2.2 顺序表 34
else //删除的不是最后一个元素
{
// 元素移动
tmp = data[i-1];
for (int j = i; j <= last; ++j)
{
data[j] = data[j + 1];
}
}
// 修改表长
--last;
return tmp;
}
算法的时间复杂度分析:顺序表上的删除操作与插入操作一样,时间主要消
耗在数据的移动上。在第i 个位置删除一个元素,从ai+1 到an 都要向前移动一个位
置,共需要移动n-i个元素,而i 的取值范围为 1≤i≤n,当i等于 1 时,需要移动
的元素个数最多,为n-1 个;当i为n时,不需要移动元素。设在第i 个位置做删除
的概率为pi ,则平均移动数据元素的次数为(n-1)/2 。这说明在顺序表上做删除操
作平均需要移动表中一半的数据元素,所以,删除操作的时间复杂度为O(n)。
8、取表元
取表元运算是返回顺序表中第 i 个数据元素,i 的取值范围是 1≤i≤last+1。
由于表是随机存取的,所以,如果 i 的取值正确,则取表元运算的时间复杂度为
O(1)。
取表元运算的算法实现如下:
public T GetElem(int i)
{
if (IsEmpty()|| (i<1) || (i>last+1))
{
Console.WriteLine("List is empty or Position is error!");
return default(T);
}
return data[i-1];
}
9、按值查找
顺序表中的按值查找是指在表中查找满足给定值的数据元素。在顺序表中完成
该运算最简单的方法是:从第一个元素起依次与给定值比较,如果找到,则返回
在顺序表中首次出现与给定值相等的数据元素的序号,称为查找成功;否则,在
顺序表中没有与给定值匹配的数据元素,返回一个特殊值表示查找失败。
按值查找运算的算法实现如下:
public int Locate(T value)
{
// 顺序表为空
数据结构(C#语言版)
2.2 顺序表 35
if(IsEmpty())
{
Console.WriteLine("list is Empty");
return -1;
}
int i = 0;
// 循环处理顺序表
for (i = 0; i <= last; ++i)
{
// 顺序表中存在与给定值相等的元素
if (value.Equals(data[i]))
{
break;
}
}
// 顺序表中不存在与给定值相等的元素
if (i > last)
{
return -1;
}
return i;
}
算法的时间复杂度分析:顺序表中的按值查找的主要运算是比较,比较的次
数与给定值在表中的位置和表长有关。当给定值与第一个数据元素相等时,比较
次数为 1;而当给定值与最后一个元素相等时,比较次数为 n。所以,平均比较
次数为(n+1)/2,时间复杂度为 O(n)。
由于顺序表是用连续的空间存储数据元素,所以按值查找的方法很多。比如,
如果顺序表是有序的,则可以用折半查找法,这样效率可以提高很多