您的位置:首页 > 理论基础 > 数据结构算法

数据结构学习笔记之线性表

2017-11-05 11:52 423 查看

线性表

线性表的类型定义:

ADT List{
数据对象:
数据关系:
基本操作:
InitList(&L)
操作结果:构造一个空的线性表L。
DestroyList(&L)
初始条件:线性表L已存在。
操作结果:销毁线性表L。
ClearList(&L)
初始条件:线性表L已存在。
操作结果:将L重置为空表。
ListEmpty(&L)
初始条件:线性表L已存在。
操作结果:若L为空表,则返回TRUE,否则返回FALSE。
ListLength(L)
初始条件:线性表L已存在。
操作结果:返回L中数据元素个数。
GetElem(L,i,&e)
初始条件:线性表L已存在,1<=i<=ListLength(L)。
操作结果:用e返回L中第i个数据元素的值。
LocateElem(L,e,compare())
初始条件:线性表L已存在,compare()是数据元素判定函数。
操作结果:返回L中第1个与e满足关系compare()的数据元素的位序。若这样的数据元素不存在,则返回值为0。
PriorElem(L,cue_e,&pre_e)
初始条件:线性表L已存在。
操作结果:若cur_e是L的数据元素,且不是第一个 ,则用pre_e返回它的前驱,否则操作失败,pre_e无定义。
NextElem(L,cur_e,&next_e)
初始条件:线性表L已存在。
操作结果:若cur_e是L的数据元素,且不是最后一个,则用next_e返回它的后继,否则操作失败,pre_e无定义。
ListInsert(&L,i,e)
初始条件:线性表L已存在,1<=i<=ListLength(L)+1。
操作结果:在L中的第i个位置之前插入新的数据元素e,L的长度加1.
ListDelete(&L,i,&e)
初始条件:线性表L已存在且非空,1<=i<=ListLength(L)。
操作结果:删除L的第i个元素,并用e返回其值,L的长度减1.
ListTraverse(L,visit())
初始条件:线性表L已存在。
操作结果:依次对L的每个数据元素调用函数visit()。一旦visit()失败,则操作失败。
}ADT List


算法2.1

void union(List &La,List Lb){
//将所有在线性表Lb中但不再La中的数据元素插入到La中
La_len=ListLength(La);
Lb_len=ListLength(Lb);//求线性表的长度
for(i=1;i<Lb_len;i++){
GetElem(Lb,i,e);//取Lb中第i个数据元素赋给e
if(!LocateElem(La,e,equal))
ListInsert(La,++La_len,e);//La中不存在和e相同的数据元素,则插入之
}
}//union


算法2.2

void MergeList(List La, List Lb, List &Lc){
//已知线性表La和Lb中的数据元素按值非递减排列。
//归并La和Lb得到新的线性表Lc,Lc的数据元素也按值非递减排列。
InitList(Lc);
i=j=1;
k=0;
La_len=ListLength(La);
Lb_len=ListLength(Lb);
while((i<=La_len) && (j<=Lb_len)){//La和Lb均非空
GetElem(La,i,ai);
GetElem(Lb,j,bj);
if(ai<=bj){
ListInsert(Lc,++k,ai);
++i;
}
else{
ListInsert(Lc,++k,bj);
++j;
}
}
while(i<=La_len){
GetElem(La,i++,ai);
ListInsert(Lc,++k,ai);
}
while(j<=Lb_len){
GetElem(Lb,j++,bj);
ListInsert(Lc,++k,bj);
}
}//MergeList


线性表的顺序表示和实现

#define LIST_INIT_SIZE 100      //线性表存储空间的初始分配量
#define LISTINCREMENT 10        //线性表存储空间的分配增量
typedef struct{
ElemType *elem;     //存储空间基址
int length;         //当前长度
int listsize;       //当前分配的存储容量(以sizeof(ElemType)为单位)
}SqList;


算法2.3

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.4

Status ListInsert_Sq(SqList L1,int i,ElemType e){
//在顺序线性表L中第i个位置之前插入新的元素e,
//i的合法值为1<=i<=ListLength_Sq(L)+1
if(i<1 || i>L.length+1)return ERROR;    //i值不合法
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


算法2.5

Status ListDelete_Sq(SqList &L,int i,ElemType &e){
//在顺序线性表L中删除第i个元素,并用e返回其值
//i的合法值为1<=i<=ListLength_Sq(L)
if((i<1)||(i>L.length))return ERROR;    //i值不合法
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


算法2.6

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


算法2.7

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;
pa_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 LnNde *next;
}LNode, *LinkList;


算法2.8

Status GetElem_L(LinkList L,int i,ElemType &e){
//l为带头节点的单链表的头指针。
//当第i个元素存在时,其值赋给e返回OK,否则返回ERROR
p=L->next;j=1;      //初始化,p指向第一个结点,j为计数器
while(p&&j<i){      //顺指针向后查找,直到p指向第i个元素或p为空
p=p->next;++j;
}
if(!p||j>i)return ERROR;    //第i个元素不存在
e=p->data;      //取第i个元素
return OK;
}//GetElem_L


算法2.9

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个结点
}
if(!p||j>i-1)return ERROR;  //i小于1或者大于表长加1
s=(LinkList)malloc(sizeof(LNode));  //生成新结点
s->data=e;s->next=p->next;      //插入L中
p->next=s;
}//ListInsert_L


算法2.10

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;  //删除位置不合理
p->next=q->next;    //删除并释放结点
e=q->data;
free(q);
return OK;
}//ListDelete_L


算法 2.11

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;      //插入到表头
}
}//CreateList_L


算法2.12

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;
e833

}
else{
pc->next=pb;
pc=pb;
pb=pb->next;
}
}
pc->next=pa?pa:pb;      //插入剩余段
free(Lb);       //释放Lb的头结点
}//MergeLis_L


线性表的静态单链表存储结构

#define MXASIZE 1000    //链表的最大长度
typedef struct{
ElemType data;
int cur;
}component,SLinkList[MAXSIZE];


算法 2.13

int LocateElem_SL(SLinkList S,ElemType e){
//在静态单链线性表L中查找第1个值为e的元素。
//若找到,则返回它在L中的位序,否则返回0。
i=S[0].cur;         //i指示表中的第一个结点
while(i && S[i].data!=e)
i=S[i].cur;     //在表中顺链查找
return i;
}//LocateElem_SL


算法2.14

void InitSpace_SL(SLinkList &space){
//将一维数组space中各分量连成一个备用链表,space[0].cur为头指针,
//“0”表示空指针
for(i=0;i<MAXSIZE-1;++i)
space[i].cur=i+1;
space[MAXSIZE-1].cur=0;
} //InitSpace_SL


算法2.15

int Malloc_SL(SLinkList &space){
//若备用空间链表非空,则返回分配的结点下标,否则返回0
i=space[0].cur;
if(space[0].cur)space[0].cur=space[i].cur;
return i;
} //Malloc_SL


算法2.16

void Free_SL(SLinkList &space,int k){
//将下标为k的空闲结点回收到备用链表
space[k].cur=space[0].cur;space[0].cur=k;
}//Free_SL


算法2.17

void difference(SLinkList &space,int &S){
//依次输入集合A和集合B的元素,在一维数组space中建立表示集合(A-B)并上(B-A)
//的静态链表,S为其头指针。假设备用空间足够大,space[0].cur为其头指针。
InitSpace_SL(space);        //初始化备用空间
S=Malloc_SL(space);         //生成S的头结点
r=S;        //r指向S的当前最后结点
scanf(m,n);         //输入A和B的元素个数
for(j=1;j<=m;++j){
i=Malloc_SL(space);         //分配结点
scanf(space[i].data);       //输入A的元素值
space[r].cur=i;r=i;         //插入到表尾
} //for
space[r].cur=0;        //尾结点的指针为空
for(j=1;j<=n;++j){     //依次输入B的元素,若不在当前表中,则插入,否则删除
scanf(b);p=S;k=space[S].cur;        //k指向集合A中的第一个结点
while(k!=space[r].cur && space[k].data!=b){     //在当前表中查找
p=k;k=space[k].cur;
}//while
if(k==space[r].cur){        //当前表中不存在该元素,插入在r所指结点之后,且r的位置不变
i=Malloc_SL(space);
space[i].data=b;
space[i].cur=space[r].cur;
space[r].cur=i;
}//if
else{       //该元素已在表中,删除之
space[p].cur=space[k].cur;
Free_SL(space,k);
if(r==k)r=p;        //若删除的是r所指结点,则需修改尾指针
}//else
}//for
}//difference


循环链表

线性表的双向链表存储结构

typedef struct DuLNode{
ElemType data;
struct DuLNode *prior;
struct DuLNode *next;
}DuLNode,*DuLinkList;


算法2.18

Status ListInsert_DuL(DuLinkList &L,int i,ElemType e){
//在带头结点的双链循环线性表L中的第i个位置之前插入元素e,
//i的合法值为1<=i<=表长+1。
if(!(p=GetElemP_DuL(L,i)))      //在L中确定插入位置
return ERROR;       //p=NULL,即插入位置不合法
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.19

Status ListDelete_DuL(DuLinkList &L,int i,ElemType &e){
//删除带头结点的双链循环线性表L的第i个元素,i的合法值为1<=i<=表长
if(!(p=GetElem_DuL(L,i)))       //在L中确定第i个元素的位置指针为p
return ERROR;       //p=NULL,即第i个元素不存在
e=p->data;
p->prior->next=p->next;
p->next->prior=p->prior;
free(p);
return OK;
}//ListDelete_DuL


带头结点的线性链表类型定义

typedef struct LNode{//结点类型
ElemType data;
struct LNode *next;
}*Link,*Position;

typedef struct{ //链表类型
Link head,tail;     //分别指向线性链表中的头结点和最后一个结点
int len;        //指示线性链表中数据元素的个数
}LinkList;

Status MakeNode(Link &p,ElemType e);
//分配由p指向的值为e的结点,并返回OK;若分配失败,则返回ERROR
void FreeNode(Link &p);
//释放p所指结点
Status InitList(LinkList &L);
//构造一个空的线性链表L
Status DestroyList(LinkList &L);
//销毁线性链表L,L不再存在
Status ClearList(LinkList &L);
//将线性链表L重置为空表,并释放原链表的结点空间
Status InsFirst(Link h,Link s);
//已知h指向线性链表的头结点,将s所指结点插入在第一个结点之前
Status DelFirst(Link h,Link &q);
//已知h指向线性链表的头结点,删除链表中的第一个结点并以q返回
Status Append(LinkList &L,Link s);
//将指针s所指(彼此以指针相连)的一串结点连接在线性链表L的最后一个结点之后,
//并改变链表L的尾指针指向新的尾结点
Status Remove(LinkList &L,Link &q);
//删除线性链表L中的尾结点并以q返回,改变链表L的尾指针指向新的尾结点
Status  InsBefore(LinkList &L,Link &p,Link s);
//已知p指向线性链表L中的一个结点,将s所指结点插入在p所指结点之前,
//并修改指针p指向新插入的结点
Status InsAfter(LinkList &L,Link &p,Link s);
//已知p指向线性链表L中的一个结点,将s所指结点插入在p所指结点之后,
//并修改指针p指向新插入的结点
Status SetCurELem(Link &p,ElemType e);
//已知p指向线性链表中的一个结点,用e更新p所指结点中数据元素的值
ElemType GetCurElem(Link p);
//已知p指向线性链表中的一个结点,返回p所指结点中数据元素的值
Status ListEmpty(LinkList L);
//若线性链表L为空表,则返回TRUE,否则返回FALSE
int ListLength(LinkList L);
//返回线性链表L中元素个数
Position GetHead(LinkList L);
//返回线性链表L中头结点的位置
Position GetLast(LinkList L);
//返回线性链表L中最后一个结点的位置
Position PriorPos(LinkList L,Link p);
//已知p指向线性链表L中的一个结点,返回p所指结点的直接前驱的位置,
//若无前驱,则返回NULL
Position NextPos(LinkList L,Link p);
//已知p指向线性链表L中的一个结点,返回p所指结点的直接后继的位置,
//若无后继,则返回NULL
Status LocatePos(LinkList L,int i,Link &p);
//返回p指示线性链表L中第i个结点的位置并返回OK,i值不合法时返回ERROR
Position LocateElem(LinkList L,ElemType e,Status (*compare)(ElemType,ElemType));
//返回线性链表L中第1个与e满足函数compare()判定关系的元素的位置,
//若不存在这样的元素,则返回NULL
Status ListTraverse(LinkList L,Status (*visit)());
//依次对L的每个元素调用函数visit()。一旦visit()失败,则操作失败。


算法2.20

Status ListInsert_L(LinkList &L,int i,ElemType e){
//在带头结点的单链线性表L的第i个元素之前插入元素e
if(!LocatePos(L,i-1,h))
return ERROR;       //i值不合法
if(!MakeNode(s,e))
return ERROR;       //结点存储分配失败
InsFirst(h,s);      //对于从第i个结点开始的链表,第i-1个结点是它的头结点
return OK;
}//ListInsert_L


算法2.21

Status MergeList_L(LinkList &La,LinkList &Lb,LinkList &Lc,int (*compare)(ElemType,ElemType)){
//已知单链线性表La和Lb的元素按值非递减排列。
//归并La和Lb得到新的单链线性表Lc,Lc的元素也按值非递减排列。
if(!InitList(Lc))
return ERROR;       //存储空间分配失败
ha=GetHead(La);     //ha和hb分别指向La和Lb的头结点
hb=GetHead(Lb);
pa=NextPos(La,ha);      //pa和pb分别指向La和Lb中当前结点
pb=NextPos(Lb,hb);
while(pa&&pb){
a=GetCurElem(pa);       //La和Lb均非空
b=GetCurElem(pb);
if((*compare)(a,b)<=0){     //a<=b
DelFirst(hb,q);
Append(Lc,q);
pa=NextPos(La,ha);
}
else {      //a>b
DelFirst(hb,q);
Append(Lc,q);
pb=NextPos(Lb,hb);
}
}//while
if(pa)  Append(Lc,pa);      //连接La中剩余结点
else Append(Lc,pb);     //连接Lb中剩余结点
FreeNode(ha);       //释放La和Lb的头结点
FreeNode(hb);
return OK;
}MergeList_L


抽象数据类型一元多项式的定义

ADT Polynomial{
数据对象:
数据关系:
基本操作:
CreatPolyn(&P,m)
操作结果:输入m项的系数和指数,建立一元多项式P。
DestroyPolyn(&p)
初始条件:一元多项式P已存在。
操作结果:销毁一元多项式P。
PrintPolyn(P)
初始条件:一元多项式P已存在。
操作结果:打印输出一元多项式P。
PolyLength(P)
初始条件:一元多项式P已存在。
操作结果:返回一元多项式P中的项数。
AddPolyn(&Pa,&Pb)
初始条件:一元多项式Pa和Pb已存在,
操作结果:完成多项式相加运算,即:Pa=Pa+Pb,并销毁一元多项式Pb。
SubstractPolyn(&Pa,&Pb)
操作结果:完成多项式相减运算,即:Pa=Pa-Pb,并销毁一元多项式Pb。
MultiplyPolyn(&Pa,&Pb)
初始条件:一元多项式Pa和Pb已存在。
操作结果:完成多项式相乘运算,即:Pa=Pa*Pb,并销毁一元多项式Pb。
} ADT Polynomial

typedef struct{     //项的表示,多项式的项作为LinkList的数据元素
float coef;     //系数
int expn;       //指数
}term,ElemType;     //两个类型名:term用于本ADT,ElemType为LinkList的数据对象名

typedef LinkList polynomial;        //用带表头结点的有序链表表示多项式

void CreatPolyn(polynomial &P,int m);
//输入m项的系数和指数,建立一元多项式的有序链表P
void DestroyPolyn(polynomial &P);
//销毁一元多项式P
void PrintPolyn(polynomail P);
//打印输出一元多项式P
int PolynLength(polynomail P);
//返回一元多项式P中的项数
void AddPolyn(polynomail &Pa,polynomial &Pb);
//完成多项式相加运算,即:Pa=Pa+Pb,并销毁一元多项式Pb
void SubtractPolyn(polynomail &Pa,polynomial &Pb);
//完成多项式相减运算,即:Pa=Pa-Pb,并销毁一元多项式Pb
void MultiplyPolyn(polynomial &Pa,polynomail &Pb);
//完成多项式相乘运算,即:Pa=Pa*Pb,并销毁一元多项式Pb
int cmp(term a,term b);
//依a的指数值<(或=)(或>)b的指数值,分别返回-1、0和+1


算法2.22

void CreatPolyn(polynomail &P,int m){
//输入m项的系数和指数,建立表示一元多项式的有序链表P
InitList(P);
h=GetHead(P);
e.coef=0.0;
e.expn=-1;
SetCurElem(h,e);    //设置头结点的数据元素
for(i=1;i<=m;i++){  //依次输入m个非零项
scanf(e.coef,e.expn);
if(!LocateElem(P,e,q,(*cmp)())){    //当前链表中不存在该指数项
if(MakeNode(s,e)) InsFirst(q,s);    //生成结点并插入链表
}
}
} //CreatPolyn


算法2.23

void AddPolyn(polynomail &Pa, polynomail &Pb){
//多项式加法:Pa=Pa+Pb,利用两个多项式的结点构成“和多项式”
ha=GetHead(Pa); hb=GetHead(Pb); //ha和hb分别指向Pa和Pb的头结点
qa=NextPos(Pa,ha);
qb=NextPos(Pb,hb);  //qa和qb分别指向Pa和Pb中当前结点
while(qa&&qb){  //qa和qb均非空
a=GetCurElem(qa);
b=GetCurElem(qb);   //a和b为两表中当前比较元素
switch(*cmp(a,b)){
case -1:    //多项式PA中当前结点的指数值小
ha=qa;
qa=NextPos(Pa,qa);
break;
case 0:     //两者的指数值相等
sun=a.coef+b.coef;
if(sum!=0.0){   //修改多项式PA中当前结点的系数值
SetCurElem(qa,sum);
ha=qa;
}
else{   //删除多项式PA中当前结点
DelFirst(ha,qa);
FreeNode(qa);
qb=NextPos(Pb,hb);
qa=NextPos(Pa,ha);
break;
}
case 1:     //多项式PB中当前结点的指数值小
DelFirst(hb,qb);
InsFirst(ha,qb);
qb=NextPos(Pb,hb);
ha=NextPos(Pa,ha);
break;
} //switch
} //while
if(!ListEmpty(Pb))  Append(Pa,qb);      //连接Pb中剩余结点
FreeNode(hb);       //释放Pb的头结点
} //AddPolyn
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  数据结构 线性表