严蔚敏版数据结构学习笔记(1):线性表的顺序表示和实现
来源:互联网 发布:河北省中标数据网 编辑:程序博客网 时间:2024/06/05 18:42
线性结构的特点:在数据元素的非空有限集合中(1)存在唯一的一个被称作“第一个”的数据元素,(2)存在唯一的一个被称作“最后一个”的数据元素,(3)除第一个外,集合中的每一个数据元素均只有一个前驱,(4)除最后一个数据元素外,每一个元素均只有一个后继。
一个线性表是n个数据元素的有限序列。线性表的数据元素个数n(n>=0)定义为线性表的长度,n=0时称为空表。对一个线性表不仅可以进行访问,还可以进行插入和删除的操作。
例题2-1:假设利用两个线性表LA和LB分别表示两个集合A和B,现在要求一个新的集合A=A U B。
分析:此时在这个题目里面有如下的操作:(1)扩大线性表LA(2)将存于LB而不存于LA中的数据元素插入到LA中
void union(SqList &LA,SqList LB){//将所有不在LA中但是存在于LB中的数据元素插入到LA中 Int LA_len = ListLength(LA); Int LB_len = ListLength(LB); for(int i = 0;i<LB_len;i++){ GetElem(LB,i,e); if(!LocateElem(LA,e,equal))///LA中不存在和e相同的数据元素 ListInsert(LA,++LA_len,e) // 插入 }
例题2-2:已知线性表LA和LB中的元素按照值非递减的有序排列,现要求合并LA和LB为LC然后将各个数据元素任然按值非递减有序排列。
分析:只要先设一个新的线性表LC为新表,然后依次将LA和LB的元素存入LC即可,所以可以设两个指针i和j分别指向LA和LB中的某个元素,若i所指的元素为a,j所指的元素为b,那么当a>b时,c的取值为b,当a<=b时,c的取值是a;显然指针i和j的初始值都是1,在所指元素插入到LC中以后,在LA或者LB中顺序后移。
Status Mergelist(SqList LA,SqList LB,SqList &LC){//已知线性表LA和LB中的元素按照值非递减排列,LC也按照非递减排列 InitLIst(LC); int i= j=1;k=0; ElemType LA_len=ListLength(lA); ElemType LB_len=ListLength(LB); while((i<=LA_len)&&(j<=LB_len)) {//LA 和 LB均为非空 GetElem(lA,i,ai); GetElem(LB,j,bj); if(ai<=bj){ ListIntert(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); }}
对于顺序表的合并,上述的算法的基本操作是“元素赋值”,时间复杂度为O(LA.length+LB.length),该算法还可以改写成如下的算法:
void MergeList(SqList LA,SqList LB,SqList &LC){ ElemType *pa,*pb,*pc,*pa_last,*pb_last; 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的剩余元素}
该算法具有线性的时间复杂度,原因是(1):由于LA和LB中的数据元素值是递增的(同一集合中元素不等),则对LB中的每个元素,不需要在LA中从表头到表尾进行全程搜索;(2)由于用新表LC表示并集,则插入实际的操作时通过复制来进行的。其时间复杂度是O(nlogn)。
附录:ADT LIST的各个算法的实现:
ADT List{
基本操作:
InitList(&L)//构造一个空表
DestroyList(&L)//销毁线性表L
ClearList(&L)//将L重置为一个空表
ListEmpty(L)//若L为空表,则返回TRUE,否则返回FALSE
ListLength(L)//返回表L的长度(即为L的数据元素个数)
GetElem(L,i,&e)//用e返回L中第i个元素的值
LocateElem(L,e,compare())//返回L中第一个与e满足关系compare()的数据元素的位序,若这样的数据元素不存在,返回值为0
PriorElem(L,cur_e,&pre_e)//若cur_e是L的数据元素,且不是第一个,则用pre_e返回它的前驱,否则操作失败,pre_e无意义
NextElem(L,cur_e,&next_e)//若cur_e是L的数据元素,且不是最后一个,则用next_e返回它的后继,否则操作失败,next_e无意义
ListInsert(&L,i,e)//在线性表L的第i个位置上插入新的数据元素e,L的长度加1
ListDelete(&L,i,&e)//删除L的第i个数据元素,并用e返回其值,L的长度减1
ListTraverse(L,visit())//依次对L的每个数据元素调用visit(),一旦visit()失败,则操作失败
}ADT List
InitList(&L):
Status InitList(SqList& L){//构造一个空的线性表 L.elem=(ElemType *)malloc(MAX_SIZE*sizeof(ELemType));//申请内存空间 if(!L.elem) return ERROR; else{ L.length = 0; L.listsize= MAX_SIZE; return OK; } }
DestroyList(&L):
void DestroyList(SqList &L){//销毁L if(L.elem) free(L.elem);//释放线性表占据的所有存储空间}
ClearList(&L):
void ClearList(Sqlist &L){//清空L L.length=0;//将线性表的长度置为0}
ListEmpty(L):
Status ListEmpty(SqList L){ if(L.length==0)return TRUE; else return FALSE;}
ListLength(L):
Status ListLength(L){ return L.length;}
GetElem(L,i,&e):
Stutas GetElem(SqList L,int i,ElemType e){//初始条件:顺序线性表L已存在,1≤i≤ListLength(L)用e返回L中第i个数据元素的值,注意i指位置,第1个位置的数组是从0开始 if(L.length==0||i<0||i>L.length) return ERROR; else{ *e = L.elem[i-1]; return OK; }}
LocateElem(L,e,compare()):
Status LocateElem(SqList L,ElemType e,Status(*compare)(int a,int b)){//返回L中第一个大于e的数据元素的位序 实现一 for(i=0;i<=L.length-1;i++){ if(compare(L.elem[i],e)==Ok) { return i; break; }else{ continue; } } if(i==L.length-1&&(*compare)(L.elem[L.length-1],e)==FALSE) return 0;}int LocateElem(SqList L,ElemType e,Status(*compare)(ElemType,ElemType)){ int i=1; ElemType *p = L.elem; while(i<=L.length&&!(*compare)(*p++,e)){ ++i; } if(i<=L.length) return i; else return 0;}
PriorElem(L,cur_e,&pre_e):
Status PriorElem(SqList L,ElemType cur_e,ElemType *pre_e){//实现一 int i=2; ElemType *p = L.elem+1;//将p初始为L的第二个元素 while(i<=L.length&&*p!=cur_e){//从第二个元素开始,挨个与cur_e比较,直到相等或L的最后 p++; i++; } if(i>L.length) return ERROR; else { *pre_e = *--p;//将p的前一个元素赋值给pre_e return OK; }}Status PriorElem(SqList L, ElemType cur_e, ElemType *pre_e) //实现二 { int i; int *p = L.elem; for (i=0; i<L.length; i++,p++){//顺序表长度已知,故用for循环 if (i==0 && *p==cur_e) return ERROR;//此为第一个前驱 if (*p == cur_e){ //找到了当前元素且不是第一个元素, *pre_e = *--p; //将其前驱赋给引用参数 return OK; } }}
NextElem(L,cur_e,&next_e):
Status NextElem(SqList L,ElemType cur_e,ElemType *next_e){//实现一 int i=1; ElemType *p = L.elem; while(i<L.length&&*p!=cur_e){ p++; i--; } if(i==L.length) return ERROR; else{ *next_e=*++p; return OK; }}Status NextElem(sqlist L, int cur_e, int *nex_e){//最后一个元素无后继 int i; int *p = L.elem; for (i=0; i<L.length; i++) {//顺序表长度已知,故用for if (i==L.length-1 || *p==cur_e) return ERROR;//当前元素为最后一个元素,无后继 if (*p == cur_e){ *nex_e = *++p; //将后继赋给引用参数带回 return OK; } }}
ListInsert(&L,i,e):
Status ListInsert(SqList &L,int i,ElemType e){//在线性表L的第i个位置之前插入新的元素e,i的合法值为1<=i<=ListLength(L)+1; if(i<0||i>L.ListLength+1) return ERROR;//i值不合法 else{ if(L.length>=L.listsize){//当前存贮空间已经满了,增加分配 ElemType *newbase = (ElemType*)realloc(L.elem,L.length+LISTINCREMENT)*sizeof(ElemType)); if(!newbase) return ERROR; else{ 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; } }
ListDelete(&L,i,&e):
Status ListDelete(SqList &L,int i,ElemType &e){//在顺序线性表L中删除第i个元素,并用e返回其值 ,i的合法值是1<=i<=ListLength(L); if(i<1||i>L.length) return ERROR; else{ 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; } }
ListTraverse(L,visit()):
Status TravelList(SqList L,void(*visit)(SqList*)){ ElemType *p = L.elem; int i = 1; while(i<L.length){ visit(p++); i++; } return OK;}
上述代码里面提到的compare():
Stauts compare(int a,int b){ if(a>b) return OK; else ERROR;}
visit()只是个遍历的伪代码随你自己操作而定义。比如你定义个void visit(ElemType *L){printf(“%d”, L.elem[i]) ;} 输出该位置线性表的数据元素
- 严蔚敏版数据结构学习笔记(1):线性表的顺序表示和实现
- 数据结构1:线性表的顺序表示和实现
- 数据结构(1):线性表的顺序表示和实现
- 严蔚敏版数据结构学习笔记(2):线性表的链式表示和实现
- 数据结构 线性表 顺序表示和实现
- 数据结构之:线性表的顺序表示和实现
- 线性表的顺序表示和实现 - 数据结构
- 数据结构之线性表的顺序表示和实现
- 【数据结构】-线性表的顺序表示和实现
- 线性表的顺序表示和实现(数据结构)
- 数据结构---线性表的顺序表示和实现
- 2.2线性表的顺序表示和实现(1)
- 数据结构笔记(一)线性表的顺序表示和基本操作及其顺序表实现的集合运算(A-B)U(B-A)实例
- 线性表的顺序表示和实现
- 线性表的顺序表示和实现
- 线性表的顺序表示和实现
- 线性表的顺序表示和实现
- 线性表的顺序表示和实现
- Highways UVA
- backpropagation
- tcp、ip协议概述
- Thinkphp5 微信公众号token验证不成功的原因
- spring+springMVC+hibernate事务配置
- 严蔚敏版数据结构学习笔记(1):线性表的顺序表示和实现
- HDU
- Spark性能优化指南——高级篇
- tcp协议三次握手、四次挥手及其他
- 回归决策树
- 掌控之外,收获之中
- MongoDB主从模式,复制模式比较
- appium自动化参考博客
- 实施定量风险分析的工具 EMV分析与决策树学习