DS--线性表

1 线性表的定义
2 基于抽象数据类型线性表的操作
3 线性表的存储结构
4 基于顺序存储结构的线性表操作算法
5 基于链式存储的线性表操作算法
6 循环链表的操作算法
7 双向链表的操作算法
8 顺序存储线性表与链式存储线性表的比较
9 一元多项式的表示及相加

-----------------------------------------------------------------------

1、名词术语
·线性表--n个数据元素的有限序列。记为(a1,a2,……,ai-1,ai,ai+1,……,an)。
 例如:26英文字母表(A,B,C,……,X,Y,Z)、一个班级的学生成绩报表等
·表长--线性表中元素的个数
·直接前驱元素--线性表中ai-1领先于ai,则ai-1是ai的直接前驱元素
·直接后继元素--线性表中ai领先于ai+1,则ai+1是ai的直接后继元素

2、线性表的抽象数据类型定义
ADT List{
 数据对象:D={ai|ai∈ElemSet,i=1,2,……,n,n≥0}
 数据关系:R1={<ai-1,ai>|ai-1,ai∈D,i=2,……,n}
 基本操作:InitList(&L)
 操作结果:构造一个空的线性表L。
 ……
}ADT List

·基于抽象数据类型线性表的操作
1、建立一个空的线性表   
2、求线性表中元素个数
3、判断线性表L是否为空 
4、取线性表L中第i个元素
5、在线性表中插入某元素
6、在线性表中删除某元素
7、求线性表中某元素的前驱元素
8、求线性表中某元素的后继元素
9、在线性表中查找某元素 
10、两个线性表进行合并

·线性表的存储结构   
1、两种存储结构:顺序存储--数组,链式存储--链表

-----------------------------------------------------------------------
类型定义:
//---线性表的动态分配顺序存储结构---
#define LIST_INIT_SIZE 100  //线性表存储空间的初始分配量
#define LISTINCREMENT 10  //线性表存储空间的分配增量
typedef struct{
 ElemType *elem; //存储空间基址
 int length; //当前长度
 int listsize; //当前分配的存储容量(以sizeof(ElemType)为单位)
}SqList; 

1、创建一个空的线性表
Status InitList_Sq(SqList &L){ // 构造一个空的线性表L。
 L.elem=(ElemType *)malloc(LIST_INIT_SIZE * sizeof(ElemType));
 if (!L.elem) exit(OVERFLOW); //存储分配失败
 L.length=0; //空表长度为0
 L.listsize=LIST_INIT_SIZE; //初始存储容量
 return OK;
}//InitList_Sq

2、插入元素算法
Status ListInsert_Sq(SqList &L,int i,ElemType e){ //在顺序线性表L中第i个位置之前插入新的元素e
 if(i<1 || i>L.length+1) return ERROR;  //i的值不合法,i的合法值为1≤i≤Listlength_Sq(L)+1
if(L.length>=L.listsize){   //当前存储空间已满,增加分配
  newbase=(ElemType *)realloc(L.elem,(L.listsize+LISTINCREMENT)* sizeof(ElemType));
  if(!newbase) exit(OVERFLOW);   //存储分配失败
  L.elem=newbase;    //新基址
  L.listsize+=LISTINCREMENT;   //增加存储容量
 }
 q=&(L.elem[i-1]); //q为插入位置
 for(p=&(L.elem[L.length-1]); p>=q; --p)
  *(p+1)=*p; //插入位置及之后的元素右移
 *q=e; //插入e
 ++L.length; //表长增1
return OK;
} //ListInsert_Sq

3、删除元素算法
Status ListDelete_Sq(SqList &L,int i,ElemType &e){ //在顺序线性表L中删除第i个元素,并用e返回其值
 if((i<1)||(i>L.length)) return ERROR;  //i的值不合法,i的合法值为1≤i≤Listlength_Sq(L)
 p=&(L.elem[i-1]);    //p为被删除元素的位置
 e=*p;      //被删除元素的值赋给e
 q=L.elem+L.length-1;    //表尾元素的位置
 for(++p; p<=q; ++p) *(p-1)=*p;   //被删除元素之后的元素左移
 --L.length;     //表长减1
 return OK;
}//ListDelete_Sq

4、查找元素算法
int LocateElem_Sq(Sqlist L,ElemType e,Status(*compare)(ElemType,ElemType)){  //在顺序线性表L中查找第1个值与e满足compare()的元素的位序
          //若找到,则返回其在L中的位序,否则返回0。
i=1;       //i的初值为第1个元素的位序
p=L.elem;      //p的初值为第1个元素的存储位置
while(i<=L.length &&! (*compare)(*p++,e)) ++i;
if(i<=L.length) return i;
else return 0;
}//LocateElem_Sq

5、两表合并算法
void MergeList_Sq(SqList La,SqList Lb,SqList &Lc){  //已知顺序线性表La和Lb的元素按值非递减排列
       //归并La和Lb得到新的顺序线性表Lc,Lc的元素也按值非递减排列
 pa=La.elem;
 pb=Lb.elem;
 Lc.listsize=Lc.length=La.length+Lb.length;
 pc=Lc.elem=(ElemType *)malloc(Lc.listsize * sizeof(ElemType));
 if(!Lc.elem) exit(OVERFLOW); //存储分配失败
 pa_last=La.elem+La.length-1;
 pb_last=Lb.elem+Lb.length-1;
 while(pa<=pa_last && pb<=pb_last){ //归并
  if(*pa<=*pb) *pc++=*pa++;
  else *pc++=*pb++;
 }
 while(pa<=pa_last) *pc++=*pa++; //插入La的剩余元素
 while(pb<=pb_last) *pc++=*pb++; //插入Lb的剩余元素
} //MergeList_Sq

-----------------------------------------------------------------------
类型定义:
//---线性表的单链表存储结构---
typedef struct LNode{
 ElemType data;          
 struct LNode *next;
}LNode,*LinkList;

1、创建一个带头结点的单链表
void CreateList_L(LinkList &L,int n){ //逆位序输入n个元素的值,建立带表头结点的单链线性表L。
 L=(LinkList) malloc (sizeof (LNode));
 L->next=NULL; //先建立一个带头结点的单链表
 for (i=n; i>0; --i){
  p=(LinkList) malloc (sizeof (LNode)); //生成新结点
  scanf(&p->data); //输入元素值
  p->next=L->next;
  L->next=p; //插入到表头
 }

2、链表中插入结点算法
Status ListInsert_L(LinkList &L, int i, ElemType e){ //在带头结点的单链线性表L中第i个位置之前插入元素e
 p=L;
 j=0;
 while (p && j<i-1) {p=p->next; ++j;} //寻找第i-1个结点
 s=(LinkList) malloc (sizeof (LNode)); //生成新结点
 s->data=e;
 s->next=p->next; //插入L中
 p->next=s;
 return OK;
}//ListInsert_L

3、链表中删除结点算法
Status ListDelete_L(LinkList &L, int i, ElemType &e){ //在带头结点的单链线性表L中,删除第i个元素,并由e返回其值
 p=L;
 j=0;
 while (p->next && j<i-1){ //寻找第i个结点,并令p指向其前趋
  p=p->next;
  ++j;
 }
 if (!(p->next) || j>i-1)   return ERROR; //删除位置不合理
 q=p->next;
 p->next=q->next; //删除并释放结点
 e=q->data;
 free(q);
 return OK;
}//ListDelete_L

4、两个有序链表合并成一个有序链表
void MergeList_L(LinkList &La,LinkList &Lb,LinkList &Lc){  //已知单链线性表La和Lb的元素按值非递减排列
        //归并La和Lb得到新的单链线性表Lc,Lc的元素也按值非递减排列。
 pa=La->next;
 pb=Lb->next;
 Lc=pc=La;  //用La的头结点作为Lc的头结点
 while (pa && pb){
  if (pa->data<=pb->data){
  pc->next=pa;
  pc=pa;
  pa=pa->next;
 }
 else {
  pc->next=pb;
  pc=pb;
  pb=pb->next;
 }
}
pc->next=papa:pb; //插入剩余段
free(Lb); //释放Lb的头结点
}//MergeList_L

-----------------------------------------------------------------------

循环链表
是另一种形式的链式存储结构。它的特点是表中最后一个结点的指针域指向头结点,整个链表形成一个环。
由此,从表中任一结点出发均可找到表中其他结点。
循环链表的操作与单链表基本一致,差别仅在于算法中的循环条件不是P或P->next是否为空,而是它们是否等于头指针。
-----------------------------------------------------------------------

双向链表
为了克服单链表单向性的缺点,可利用双向链表,在它的结点中有两个指针域,其一指向直接后继,另一指向直接前趋。
//-------线性表的双向链表存储结构---------     
typedef struct DuLNode{       
 ElemType data;       
 struct DuLNode *prior;       
 struct DuLNode *next;     
}DuLNode, *DuLinkList;

1.在双向链表中插入节点
Status ListInsert_Dul(DuLinkList &L,int i,ElemTypee){  //在带头结点的双链循环线性表L中第i个位置之前插入元素e           
 if (!(p=GetElemp_DuL(L,i)))    //i的合法值为1≤i≤表长+1。在L中确定第i个元素的位置指针p
  return ERROR;     //p=NULL,即第i个元素不存在       
 if(!(s=(DuLinkList) malloc (sizeof (DuLNode)))) return ERROR;       
 s->data=e;       
 s->prior=p->prior;
 p->prior->next=s;       
 s->next=p;
 p->prior=s;       
 return OK;     
}//ListInsert_DuL

2.在双向链表中删除节点
Status ListDelete_Dul(DuLinkList &L,int i,ElemType &e){ //删除带头结点的双链循环线性表L中第i个元素,i的合法值为1≤i≤表长。       
 if (!(p=GetElemp_DuL(L,i)))    //在L中确定第i个元素的位置指针p         
 return ERROR;       
 e=p->data;       
 p->prior->next=p->next;       
 p->next->prior=p->prior;       
 free(p);
 return OK;     
}//ListDelete_DuL
-----------------------------------------------------------------------
顺序存储线性表与链式存储线性表的比较
顺序表的优缺点:存取数据速度快、占用的存储空间小;但需占用连续存储空间、插入操作需移动元素
链表的优缺点:不需占用连续存储空间、插入操作不需移动元素;但存储数据麻烦、速度慢、占用的存储空间大  

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值