线性表的抽象数据类型描述
类项名称:线性表(list)
数据对象集:n个元素的构成的有序序列(n=>0)
操作集:L ∈ List,X ∈ ElementType,整线性表的基本操作主要有:(如下)
/* 线性表的基本操作*/
List MakeEmpty();//初始化一个空的线性表
ElementType FindKth(int K,List L);//返回位序K处的元素
int Find(ElementType X,List L);//在线性表L中查找X第一次出现的位置
void Insert(ElementType X,int i,List L);//在位序i前插入新元素X
void Delete(int i,List L);//删除指定位序i的元素
int Length(List L);//返回线性表L的长度n
线性表的顺序存储
插入元素时,必须从最后一个元素开始往后移,逐步腾出存放插入元素的空间。若从里至外往后移,即
for(j=i-1;j<=PtrL->Last;j++)
PtrL->Data[j+1] = PtrL->Data[j];
则会导致Data[i-1]到Data[PtrL->Last+1]都是同一个元素,即Data[i-1]。
顺序存储为利用数组的连续空间顺序存放线性表的各元素, 注意链表元素起始点和末点的下标,还有指针Last指示最后一个元素。
typedef struct LNode*List;
struct LNode{
ElementType Data[MAXSIZE]; //定义一个数组
int Last; //代表线性表的最后一个元素
};
struct LNode L;
List PtrL; //线性表结构的指针
线性表长度:L.Last+1 或 Ptrl->Last+1
访问下标为i的元素:L.Data[i] 或PtrL->Data[i]
线性表顺序存储的主要操作实现 (初始化 查找 插入 删除)
代码如下:
/*初始化*/
List MakeEmpty()
{ List Ptrl;
ptrl = (List)malloc(sizeof(struct LNode));//建立空栈表
PtrL->Last = -1; // 空表,所以last指向-1
return Ptrl; //返回结构指针
}
/*查找 */
int Find(ElementType X,List PtrL)
{ int i=0;
/*从i=0的位置开始查找,当i<=指针Last所在位置,且指向元素不等于目标X时,i就不断往后移动,也就是i++*/
/*最终肯定会跳出while循环,则进行if-else判断*/
while(i<=PtrL->Last && PtrL->Data[i]!=X)
i++;
if(i>PtrL->Last) return -1; //如果没找到,返回-1
else return i; //找到后就返回此时的i,即存储位置
} /*平均比较次数为(n+1)/2,平均时间性能为O(n)*/
/*插入第i(1≤i≤n+1)个元素*/
void Insert(ElementType X,int i,List PtrL)
{ int j;
if(PtrL->Last==MAXSIZE-1){ //表空间已满,不能插入
Printf("表已存满");
return;
}
if(i<1||i>PtrL->Last+2){ //检查插入位置的合法性
Printf("位置不合法");
return;
}
for(j=PtrL->Last;j>=i-1;j--)
PtrL->Data[j+1] = PtrL->Data[j]; //从最后一个元素开始,将ai~an倒序向后移动
PtrL->Data[i-1]=X; //新元素插入
PtrL->Last++; //Last仍指向最后元素
return;
}/*平均移动次数为n/2,平均时间性能为O(n)*/
/*删除第i(1≤i≤n)个元素*/
void Delete(int i,List PtrL)
{ int j;
if(i<1 || i>PtrL->Last+1){ //检查空表及删除位置的合法性
printf("不存在第%d个元素",i);
return;
}
for(j=i;j<=PtrL->Last;j++)
PtrL->Data[j-1] = PtrL->Data[j]; // 将a(i+1)~a(n)顺序向前移动
PtrL->Last--; //Last仍指向最后元素
return;
} /*平均移动次数为(n-1)/2,平均时间性能为O(n)*/
线性表的链式存储
不需要逻辑上相邻的两元素物理上也相连,插入、删除时不需要移动数据元素,只需要修改链。
要在链式存储上插入新元素,首先构造新元素S,再将P的next指针指向S,S的next指针则指向先前P的下一个元素。两个顺序不可调换。
typedef struct LNode*List;
struct LNode{
ElementType Data;
List Next;
};
struct LNode L;
List PtrL;
线性表链式存储的主要操作实现
代码如下:
/*求表长*/
int Length(List PtrL)
{ List p=PtrL; //p指向表的1第一个节点
int j=0;
while (p){
p=p->Next; //p不断往后移,直到到最后一个节点,其值为NULL,跳出while循环
j++; //当前p指向的是第j个节点
}
return j;
}
/*查找1:按序号查找:FindKth*/
List FindKth(int K,List PtrL)
{ List p=PtrL;
int i=1;
while(p!=NULL && i<K){
p = p->Next;
i++;
}
if(i==K)return p; //找到第K个元素,返回指针
else return NULL; //否则为空
}
/*查找2:按值查找,Find*/
List Find(ElementType X,List PtrL)
{ List p=PtrL;
while(p!=NULL && p->Data!=X)
p=p->Next;
return p;
}
/*插入(在第i-1个节点后插入新元素,1≤i≤n+1)*/
List Insert(ElementType X,int i,List PtrL)
{ List p,s;
if(i==1){ //新节点插入在表头
s=(List)malloc(sizeof(struct LNode)); //申请,填装节点
s->Data=X;
s->Next=PtrL;
return s;
}
p=FindKth(i-1,Ptr); //查找第i-1个节点
if(P==NULL){ //第i-1个不存在,不能插入
printf("参数i错");
return NULL;
}
else{
s=(List)malloc(sizeof(struct LNode)); //申请、填装节点
s->Data=X;
s->Next=p->Next; //新节点插入在第i-1个节点的后面
p->Next=s;
return PtrL;
}
}
/*删除*/
List Delete(int i,List PtrL)
{ List p,s;
if(i==1){ //若要删除的是表的第一个节点
s=PtrL; //s指向第1个节点
if(PtrL!=NULL)
PtrL=PtrL->Next; //从链表中删除
else return NULL;
free(s); //释放被删除的节点
return PtrL;
}
p=FindKth(i-1,PtrL);
if(P==NULL){
printf("第%d个节点不存在",i-1);
return NULL;}
else if(p->Next==NULL){
printf("第%d个节点不存在",i);
return NULL;}
else {
s=P->Next; //s指向第i个节点
p->Next=s->Next; //从链表中删除
free(s); //释放被删除的节点
return PtrL;
}
}