目录
首先,先要知道什么为线性表,它的特点是啥,然后就是知道它的就基本操作(无非就是创销,增删改查),最后它的物理结构(本文讲解顺序表,下一节为链表)
一、线性表的定义
L = (a1, a2, a3 .... an)
相同数据类型的n(n>=0)个数据元素的有限序列
n为表长(位序),当n=0时,为空表。
二、线性表的特点
除表头外,每个元素有且只有一个直接后继
除表尾外,每个元素有且只有一个直接前继
三、基本操作
特别说明:参数带&表示需要将修改的操作结果带回到引用处
InitList(&L): 初始化,给表L分配空间
DestroyList(&L): 销毁表L,释放空间
ListInsert(&L,i,e): 在表L的第i个位置插入元素e
LocateElem(L,e): 查找表L中值为e的元素
GetElem(L,i): 查找表L中第i个位置的元素
ListDelete(&L,i,&e): 删除表L的第i个元素,并返回被删除元素的值e
Length(L): 求表长
PrintList(L): 打印表
Empty(L): 判空操作
四、线性表的物理结构
顺序表和链表
以下为顺序表的相关知识点
顺序表
用顺序存储的方式实现线性表,即在主存中分配一组地址连续的存储单元来用于依次存储元素
在逻辑上相邻的元素存储在物理位置也相同的存储单元里,元素之间的关系由存储单元的邻接关系来体现
相关操作的具体说明:
本次实例用的是C语言,静态分配,数据类型为int
注意:
C语言中数组的下标是从0开始
的,而顺序表中元素的序号是从1开始
的,即线性表中第i
个元素存储在数组中下标为i-1
的位置,即逻辑上L(i)=L.data[i-1]
1.顺序表的存储结构定义
#define MaxSize 100 //线性表的最大容量
typedef struct {
int data[MaxSize]; //数组存储元素
int length; //使用的表长
}SqList;
2.初始化
无需对数组进行初始化,因为打印时一般不会打印大于已使用的表长(此时为<=L.length)额外的元素数据
要打印所有元素(即即使表没存满,也打印后续元素,>L.length)需要对数组进行初始化,不然会有“脏数据”遗留
void InitList(SqList* L)
{
L->length = 0;
}
3.创建一个你所需要的线性表
因为我们将元素的具体内容放在数组中,所以我们需要在引用前建立一个你所需要的数组a[](后续main中有具体操作),用来作为媒介放入线性表的data[]中
int CreatList(SqList* L, int a[], int n)
{
if(n > MaxSize)
{
printf("表长有误,无法创建线性表\n");
return 0; //退出程序
}
for(int i = 0; i < n; i++)
{
L->data[i] = a[i];
}
L->length = n;
return 1;
}
4.判空
int Empty(SqList* L)
{
if(L->length == 0)
return 1;
else
return 0;
}
5.求表长
int Length(SqList* L)
{
return L->length;
}
6.打印表
void PrintList(SqList* L)
{
for (int i = 0; i < L->length; i++)
printf("%d ",L->data[i]);
}
7.查找
按位查找
int GetElem(SqList* L, int i,int* e) //查找第i个位置,返回值e
{
if(i < 1 || i > L->length) //先判断查找位置是否有效
{
printf("查找条件有误\n");
return 0;
}
else
{
/*注意:表位置为i, 数组中为data[i-1]*/
*e = L->data[i-1]; //将元素值赋值给e
return 1;
}
}
按值查找
int LocateElem(SqList* L, int n)
{
for(int i = 0; i < L->length; i++)
{
if(L->data[i] == n)
return i+1; //返回在表中的序号
}
return 0;
}
8.插入
bool ListInseret(SqList* L, int i, int e)
{
//先判断是否能插入
if (i < 1 || i > L->length+1) //插入位置不合理
return false;
if(L->length >= MaxSize) //表满了
return false;for(int j = L->length; j >= i; j--) //从最后的开始后移
L->data[j] = L->data[j-1];
L->data[i-1] = e; //插入元素
L->length ++; //表长加一
return true;
}
9.删除
bool ListDelete(SqList* L, int i, int* e)
{
if(i < 1 || i > L->length) //删除位置不合理
return false;
*e = L->data[i-1];
for(int j = i; j < L->length; j++)
{
L->data[j-1] = L->data[j];
}
L->length--; //表长减一
return true;}
10.销毁
顺序表是静态存储分配时,在顺序表变量退出作用域时,自动释放该变量所占内存单元。因此,顺序表无须销毁
五、具体实现代码
int main()
{
int a[5] = {1,2,3,4,5};
//定义
SqList L;
//创建
CreatList(&L,a,5);
//判空
if(Empty(&L))
printf("线性表为空\n");
else
printf("线性表不为空\n");
//求表长
printf("当前线性表的长度为:%d\n", Length(&L));
//打印表
printf("当前线性表的数据为:");
PrintList(&L);
//按位查找
int i = 2, e;
if (GetElem(&L, i, &e) == 1)
{
printf("\n第%d个元素的值为:%d\n", i, e);
}
else
{
printf("\n表中没有第%d个位置元素\n",i);
}
//按值查找
int n = 5;
if(LocateElem(&L,n) == 0)
{
printf("查找失败\n");
}
else
{
printf("值为%d的元素位置为%d\n",n,LocateElem(&L,n));
}
//插入
int x = 2;
int y = 6;
if(ListInseret(&L,x,y))
{
printf("已在表的第%d个位置插入元素= %d\n", x,y);
printf("打印第一次修改后的表\n");
PrintList(&L);
}
else
{
printf("插入失败,请检查\n");
}
//删除
int v = 5;
int w = -1;
if(ListDelete(&L,v,&w))
{
printf("\n删除表的第%d个位置元素,值为%d\n",v,w);
printf("打印第二次修改后的表\n");
PrintList(&L);
}
else
{
printf("删除失败,请检查\n");
}
return 0;
}
输出结果: