数据结构学习笔记之线性表
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
相关文章推荐
- 【Java数据结构学习笔记之一】线性表的存储结构及其代码实现
- 数据结构学习笔记 --- 线性表 (顺序表)
- 数据结构学习笔记--线性结构(链表)
- 数据结构学习笔记 --- 线性表 (单链表)
- 网易云课堂-陈越、何钦铭-数据结构-2016春,02-线性结构1 一元多项式的乘法与加法运算,学习笔记
- 数据结构学习笔记(10)---基于线性表的查找
- 数据结构学习笔记 --- 线性表 (双向链表、循环链表)
- 数据结构学习笔记 --- 线性表 (单链表)
- 严蔚敏版数据结构学习笔记(1):线性表的顺序表示和实现
- 数据结构学习笔记-线性表顺序存储(C语言实现)
- 数据结构学习笔记 --- 线性表 (应用举例)
- 数据结构学习笔记之线性表
- 【C++数据结构学习笔记---线性表】带头结点的双向循环链表
- 数据结构学习笔记 --- 线性表 (一元多项式的表示及相加)
- 数据结构学习笔记 --- 线性表 (一元多项式的表示及相加)
- 严蔚敏版数据结构学习笔记(2):线性表的链式表示和实现
- 数据结构学习笔记 --- 线性表 (一些常见的关于链表的算法和面试题)
- 数据结构 学习笔记(二):线性结构:线性表(顺序表,链表,广义表,多重链表)
- 数据结构学习笔记 --- 线性表 (应用举例)
- 数据结构学习笔记(3.线性表之循环链表)