线性表(List)零个或多个数据元素的有限序列。
线性表的抽象数据类型定义如下:
ADT 线性表(List)
Data
线性表的数据对象集合为{a1,a2,a3......an},每个元素的类型均为DataType。其中,除第一个元素a1外,每一个元素有且只有一个直接前驱元素,除了最后一个元素an外,每一个元素有且只有一个直接后继元素。数据元素之间的关系是一对一的关系。
Operation
InitList(*L) :初始化操作,建立一个空的线性表L
ListEmpty(L) :若线性表为空,返回true,否则返回false
ClearList(*L) :将线性表清空
GetElem(L,i,*e): 将线性表L中的第i个元素值返回给e
LocateElem(L,e): 将线性表L中查找与给定值e相等的元素,如果查找成功,返回该元素在表中序号表示成功,否则返回0表示失败
ListInsert(*L,i,e):在线性表L中的第i个位置插入新元素e
ListDelete(*L,i,*e): 删除线性表L中第i个位置元素,并用e返回其值
ListLength(L) :返回线性表L的元素个数
endADT
线性表的优点:
无须为表示表中元素之间的逻辑关系而增加额外的存储空间
可以快速的存取表中任一位置的元素
线性表缺点:
插入和删除操作需要移动大量元素
当线性表长度变化较大时,难以确定存储空间的容量
造成存储空间的”碎片”
具体实现代码如下:
#include<stdio.h>
#define OK 1
#define MAXSIZE 20 //存储空间初始分配量
#define ERROR 0
#define TRUE 1
#define false 0
typedef int Status; //Status是函数的类型,其值是函数结果状态代码,如OK等
typedef int ElemType; //ElemType类型根据实际情况而定,这里假设为int
typedef struct{
ElemType data[MAXSIZE];
int length;
}SqList;
Status visit(ElemType c){
printf("%d ",c);
return OK;
}
//如何初始化线性表
//初始化线性表就是把线性表的长度改为0
Status InitList(SqList *L){
L->length=0;
return OK;
}
//判断线性表是否为空
Status ListEmpty(SqList L){
if(L.length==0)
return true;
else
return false;
}
//清空线性表
Status ClearList(SqList *L){
L->length=0;
return OK;
}
//在线性表L中查找与给定元素e相等的元素,如果查找成功,返回该元素在表中序号表示成功,否则返回0表示失败
Status LocateElem(SqList L,ElemType e){
int i;
if(L.length==0)
return false;
for(i=1;i<=L.length;i++){
if(L.data[i-1]==e){
break;
}
}
if(i>=L.length)
return false;
return i;
}
//返回线性表L的元素个数
Status ListLength(SqList L){
return L.length;
}
//向线性表中插入数据
//初始条件:顺序线性表L已经存在,1<=i<=ListLength(L)
//操作结果,在L中第i个位置插入新的数据元素e,L的长度加1
Status ListInsert(SqList *L,int i,ElemType e){
//在第i个位置插入元素e
//首先进行判断是否可以插入 是否超出线性表范围
int k;
if(L->length==MAXSIZE)
return ERROR;
if(i<1 || i>L->length+1) //当i表第一位置小或者比最后一位置后一位置还要大时
return ERROR;
if(i<=L->length) //如果插入数据位置不在表尾部的时候
{
for(k=L->length-1;k>=i-1;k--)
L->data[k+1]=L->data[k];
}
L->data[i-1]=e;
L->length++;
return OK;
}
//获得元素操作
/*
*Status 是函数的类型,其值是函数结果状态代码,如OK等
初始条件,顺序线性表L已存在,1=<i<=ListLength(L)
操作结果:用e返回L中第i个元素的值
*/
Status GetElem(SqList L,int i,ElemType *e){
if(L.length==0 || i<1 || i>L.length)
return ERROR;
*e=L.data[i-1];
return OK;
}
Status ListDelete(SqList *L,int i,ElemType *e){
int k;
if(L->length==0) //线性表为空
return ERROR;
if(i<1 || i>L->length) //删除位置不正确
return ERROR;
//如删除第i个元素,第i个元素后面所有的数据都需要往前移一位
*e=L->data[i-1];
if(i<L->length){ //删除位置不是最后位置
for(k=i-1;k<=L->length;k++)
L->data[k]=L->data[k+1];
}
L->length--;
return OK;
}
//列出所有元素
Status ListTraverse(SqList L){
int i;
for(i=0;i<L.length;i++)
visit(L.data[i]);
printf("\n");
return OK;
}
Status unioL(SqList *L,SqList Lb){
int l_len,lb_len,i;
ElemType e; //声明L和Lb相同的元素e
l_len=ListLength(*L);
lb_len=ListLength(Lb);
for(i=1;i<=lb_len;i++){
GetElem(Lb,i,&e); //去Lb中第i个元素赋给e
if(!LocateElem(*L,e))
ListInsert(L,++l_len,e);
}
return OK;
}
int main(){
SqList L; //声明结构体变量 *L是指指向SqList结构体的数据的指针
int i,j,num,e;
InitList(&L);
//输出线性表的长度
printf("初始化L后,L.length=%d\n",L.length);
//向线性表中插入数据
for(j=1;j<=5;j++)
ListInsert(&L,1,j);
printf("向表头依次插入1~5之后: L.data=");
ListTraverse(L);
printf("L.length=%d \n",L.length);
//获得第几个元素
printf("请输入你想查找的数据的位置:");
scanf("%d",&num);
GetElem(L,num,&e); //将线性表L中的第i个位置元素返回给e
printf("你所查找的元素是=%d\n",e);
//删除元素
int q;
printf("请输入你想要删除的元素的位置\n");
scanf("%d",&q);
ListDelete(&L,q,&e); //删除线性表L中的第i个元素,并用e返回其值
ListTraverse(L);
i=ListEmpty(L);
printf("L是否为空:i=%d(1:是 0:否)\n",i);
i=ClearList(&L);
printf("清空L后:L.length=%d\n",L.length);
printf("L是否为空:i=%d(1:是 0:否)\n",i);
for(i=1;i<=10;i++)
ListInsert(&L,i,i);
printf("在L的表尾依次插入1~10后:L.data=");
ListTraverse(L);
printf("请输入您所要查找的元素");
scanf("%d",&e);
i=LocateElem(L,e); //在线性表L中查找与给定元素e相等的元素,如果查找成功,返回该元素在表中序号表示成功,否则返回0表示失败
printf("你所查找的元素所在的位置是=%d\n",i);
i=ListLength(L);
printf("该线性表长度为=%d\n",i);
SqList Lb;
InitList(&Lb);
for(i=6;i<=15;i++)
ListInsert(&Lb,1,i);
ListTraverse(Lb);
unioL(&L,Lb); //将所有在lb中,但不在L中的元素插入到L中
printf("输出合并后的数据\n");
ListTraverse(L);
}