准备考研了,我们学校使用的教材不是这一本,大概整理一下。共勉
线性结构的特点:在数据元素的非空有限集合中
存在唯一的一个被称为“第一个”的数据元素存在唯一的一个被称为“最后一个”的数据元素除了第一个之外,集合中的每个数据元均只有一个前驱除了最后一个之外,集合中的每一个元素均只有一个后继线性表是最常用 且最简单的一种数据结构,即一个线性表是n个数据元素的有限序列。例如26个英文字母表:
(a,b,c,…z)
在稍复杂的线性表中,一个数据元素可以由若干的数据项组成。此时,数据元素常常称为记录,含有大量记录的线性表又称为文件。 例如一个学校的学生健康情况登记表如下图
例2-1 假设利用两个线性表LA和LB分别表示两个集合A和B,现在求一个新的集合A=A U B(交集) 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 //La中不存在和e相同的数据元素,则插入 if(!LocateElem(La, e, equal)) ListInsert(La, ++La_len, e); } } 例2-2 已知线性表La和Lb中的数据元素按值非递减有序排列,现要求将La和Lb归并为一个新的线性表Lc,且Lc中数据元素仍按值非递减有序排列。例如LA = (1,3,4,5) LB = (2,7) LC = (1,2,3,4,5,7)
void MergeList(List La, List Lb, List &Lc){ //已知线性表La和Lb中的数据元素按值非递减排列 //归并Lb和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)){ GetElem(La, i, ai); GetElem(La, 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(La, j++, bj); ListInsert(Lc, ++k, bj); } }线性表的顺序表示指的是用一组地址连续的存储单元依次存储线性表的数据单元。线性表的这种机内表示称为线性表的顺序存储结构或者顺序映像。称这种存储结构的线性表称为顺序表。只要确定了存储线性表的起始位置,线性表中的任意一个数据单元都可随机存取,所以线性表的顺序存储结构是一种随机存取的储存结构。 图中的l代表每一个元素需要占用的l个存储单元。
//线性表的动态分配顺序存储结构 # define LIST_INIT_SIZE 100 //线性表存储空间的初始分配量 # define LISTINCREATEMENT 10 //线性表存储空间的分配增量 typedef struct{ ElemType * elem; // 存储空间基址 int length; //当前长度 int listsize; //当前分配的存储容量 }SqList;初始化线性表
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线性表的插入操作和删除操作 一般情况下,在第i(0<=i<=n)个元素之前插入一个元素时,需要将第n至第i(共n-i+1)个元素向后移动一个位置。算法实现如下。
Status ListInsert_Sq(SqList &L, int i, ElemType e){ //在顺序线性表L中的第i个位之前插入新的元素e //判断1长度的合法性 if(i<1||i>L.length+1) return ERROR; //如果内存空已满,增加分配 if(L.length>=L.listsize){ newbase = (ElemType*)realloc(L.elem,(L.listsize+LISTINCREATEMENT)*sizeof(ElemType)); if(!newbase) exit(OVERFLOW); L.elem = newbase; L.listsize += LISTINCREATEMENT; } //q为插入的位置 q = &(L.elem[i-1]); //插入位置以及之后的元素右移 for(p = &(L.elem[L.length-1]);p>=q;--p){ *(p+1) = *p; } //插入以及表长加1 *q = e; ++L.length; return OK; }//ListInsert一般情况下,删除第i(0<=i<=n)个元素需将第i+1至n(n-i)个元素依次向前移动一个位置。算法实现如下。
Status ListDelete_Sq(SqList &L, int i, ElemType &e){ //在顺序线性表L中删除第i个元素,并用e返回其值 if((i<1)||(i>L.length)) return ERROR; //p为被删除元素的地址(位置) p = &(L.elem[i-1]); // e 为 删除的值 e = *p; //表尾元素的位置 q = L.elem + L.length-1; for(++p; p>=q; ++p) *(p-1) = *p; --L.length; return OK; }//ListDelete_Sq由这两个算法得知,当在顺序储存结构的线性表中某个位置插入或者删除一个数据元素时,其时间主要消耗在移动元素上。平均需要移动一半的元素,时间复杂度为O(n)。 查找
int LocateElem_Sq(SqList L, ElemType e, Status (*compare)(ElemType, ElemType)){ //在顺序表中查找第一个值与e满足compare()的元素位序,否则返回0 i = 1; p = L.elem; while(i<L.length && !(*compare)(*p++, e)) ++i; if(i<L.length) return i; else return 0; }//LocateElem_Sq归并
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++; while(pb<pb_last) *pc++ = pb++; }//MergeList_Sq