数据结构 第二章 线性表
线性结构的特点:
(1)存在唯一的一个被称做“第一个”的数据元素;
(2)存在唯一的一个被叫做“最后一个”的数据元素;
(3)除第一个之外,集合中的每个数据元素均只有一个前驱;
(4)除最后一个之外,集合中每个数据元素均只有一个后驱;
2.1线性表的类型定义
ADT List{数据对象:数据关系:基本操作:InitLisst(&L);DestroyList(&L);ClearList(&L);ListEmpty(L);ListLength(L);GetElem(L,i,&e);LocateElem(L,e,compare());PriorElem(L,cur_e,&pre_e);NextElem(L,cur_e,&next_e);ListInsert(&L,i,e);ListDelet(&L,i,e);ListTraverse(L,visit());
}ADT List
/*算法2.1两个线性表的合并*/
void union(List &La,List Lb)
{la_len=ListLength(La);lb_len=ListLength(Lb);for(i=1;i<lb_len;i++){GetElem(Lb,i,e);if(!LocateElem(La,e,equal))ListInsert(La,++La_len,e);}
}
/*算法2.2将两个非递减序列线性链表合并成非递减线性链表*/
void MergeList(List La,List Lb,List &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(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);ListInert(Lc,++k,ai);}while(j<=Lb_len){GetElem(Lb,j++,bi);ListInsert(Lc,++k,bj);}
}
2.3线性表的顺序表示和实现
/*线性表的动态分配顺序存储结构*/
#define LIST_INIT_SIZE 100
#define LISTINCREMENT 10
typedef struct
{ElemType *elem;//存储空间基址int length;int listsize;//当前分配存储容量
}SqList;
/*算法2.3顺序表的初始化*/
Status InitList_Sq(SqList &L)
{L.elem=(ElemType *)malloc(LIST_INIT_SIZE*sizeof(ElemType));if(!L.elem)eixt(OVERFLOW); L.length=0;L.listsize=LIST_INIT_SIZE;return OK;
}
//算法2.4线性表的插入操作
Status ListInsert_Sq(SqList &L,int i,ElemType)
{if(i<1||i>L.length+1)return ERROR;if(L.length>=L.listsize){newbase=(ElemType *)realloc(L.elem,L.(listsize+LISTINREMENT)*sizeof(ElemType));if(!newbase)exit(OVERFLOW);L.elem=newbase;L.listsize+=LISTINCREMENT;}q=&(L.elem[i-1]);for(p=&(L.elem[L.length-1]);p>=q;--p)*(p+1)=*p;*q=e;++L.length;return OK;
}
//算法2.5线性表的第i个元素删除操作
Status ListDelete_Sq(SqList &L,int i,ElemType &e)
{if((i<1||(i>L.length))return ERROR;p=&(L.elem[i-1]);e=*p;q=L.elem+L.length-1;for(++p;p<=q;++p)*(p-1)=*p;--L.Length;return OK;
}
int LocateElem_Sq(SqList L,ElemType e,Status(*compare)(ElemType,ElemType))
{//在顺序表L中查找第1个值与e满足compare()元素的位序//若找到,则返回其在L中的位序,否则返回0i=1; //i的初始值为第一个元素的位序p=L.elem; //p的初值为第1个元素的为序while(i<=L.length&&!(*compare)(*p++,e)) ++1;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++; //插入La的剩余元素while(pb<=pb_last) *pc++=*pb++; //插入Lb的剩余元素
}
2.3线性链表的表示和实现
//线性链表的单链表存储结构
typedef struct LNode
{ElemType data;struct LNode *next;
}LNode,*LinkList;
//单链表是非随机存储的数据结构
//算法2.8
Status GetElem_L(LinkList L,int i,ElemType &e)
{//L为带头结点的单链表的头指针//当第i个元素存在时,其值赋给e并返回OK,否则返回falsep=L->next; j=1;//初始化,p指向第一个节点,j为计数器while(p&&j<i){p=p->next; ++j;}if(!p||j>j) return EROOR;//第i个元素不存在e=p->data;return OK;
}
/*除了函数的参数需要说明类型外,算法中使用的辅助变量可以不作变量说明
,必要时对其作用给予注释。一般而言,a,b,c,d,e等用作数据元素名,i,j,k,l,m,n
等用作整型变量名,p,q,r等用作指针变量名。当函数返回值为函数结果状态代码时,
函数定义为Status类型。为了便于描述,除了值调用方式外,增添了C++语言引用调用
的参数传递方式。在形参表中,以&打头的参数即为引用参数*/
//算法2.9
Status ListInsert_L(LinkList &L,int i,ElemType e)
{//在带头结点的单线性链表中第i个位置之前插入元素ep=L; j=0;while(p&&j<=i-1){p=p->next; ++j;//寻找第i-1个节点}if(!p||j>i-1)return ERROR;//i小于或者大于表长+1s=(LinkList)malloc(sizeof(LNode));s->data=e;s->next=p->next;p->next=s;return OK:
}
//算法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;//删除位置不合理q=p->next; p->next=q->next; //删除并释放结点e=q->data; free(q);
}
//算法2.11
void CreateList_L(LinkList &L,int n)
{//逆位序输入n个元素的值,建立带表头结点的单线性链表LL=(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.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;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=pa?pa:pb; //插入剩余段free(Lb); //释放Lb的头结点
}
静态链表
//线性表的静态单链表存储结构
#define MAXSIZE 1000//链表的最大长度
typedef struct
{ElemType data;int cur;
}component,SLinkList[MAXSIZE];
//算法2.13
int LocateElem_SL(SLinkList S,ElemTpye e)
{//在静态单线性表L中查找第1个值为e的元素//若找到,则返回它在L中的位序,否则返回0i=S[0].cur; //i指示表中的第一个结点while(i&&S[i].data!e) i=S[i].cur; //在表中顺序查找return i;
}
/*【例2-3】运算(A-B)U(B-A)*/
//假设由终端输入集合元素,先建立表示集合A的静态链表S
//而后在输入集合B的元素的同时查找S表,若存在和B相同的元素
//则从S表中删除之,否则将此元素插入S表//算法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;
}
//算法2.15 从备用链表中申请一个结点空间
int Malloc_SL(SLinkList &space)
{//若备用链表非空,则返回分配的结点的下标,否则返回0i=space[0].cur;if(space[0].cur) space[0].cur=space[i].cur;return i;
}
//算法2.16 将下标为k的空闲空间回收到备用链表
void Free_SL(SLinkList &space,int k)
{space[k].cur=space[0].cur; space[0].cur=k;
}
//算法2.17
void differnce(SLinkList &space,int k)
{//依次输入集合A和B的元素,在一维数组space中建立表示集合(A-B)U(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=1; //插入到表尾}space[r].cur=0; //尾点指针为空for(j=1;j<=n;j++){//依次输入B的元素值,若不在当前表中,则插入,否则删除scanf(b);p=S;k=space[S].cur;//k指向集合中第一个节点while(k!=space[k].cur&&space[k].data!b)//在当前表中查找{p=k;k=space[k].cur;}//whileif(k==space[r].cur)//当前表中不存在该元素,插入在r所在结点之后,且r的位置不变{i=Malloc_SL(space);space[i].data=b;space[i].cur=space[r].cur;space[r].cur=i;}//ifelse{ //该元素已在表中,删除它space[p].cur=space[k].cur;Free_SL(space,k);if(r==k) r=p;}//else}//for
}//difference
循环链表
双向链表
//线性表的双向链表存储结构
typedef struct DuLNode
{ElemType data;struct DuLNode *prior;struct DuLNode *next;
}DuLNode,*DuLinkList;
Status ListDelete_DuL(DuLinkList &L,int i,ElemType &e)
{//删除带头结点的双链循环线性表L中第i个元素,i的合法值为1<=i<=表长if(!(p=GetElemP_DuL(L,i)))return ERROR;e=p->data;p->prior->next=p->next;p->next->prior=p->prior;free(p);return OK;
}//ListDelete_DuL
Status ListInsert_DuL(DuLinkList &L,int i,ElemType e)
{//在带头结点的双链循环线性表L中第i个位置之前插入元素e//i的合法值为1<<i<<表长+1if(!(p=GetElemP_DuL(L,i)))//在L中确定插入位置指针preturn ERROR;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
由于链表在空间的合理利用上和插入、删除时不需移动等优点,
在很多场合下,它是线性表的首选存储结构。然而,它也存在着实现
某些基本操作,如求线性表的长度时不如顺序存储结构的缺点;
另一方面,由于在链表中,结点之间的关系用指针来表示,则数据元素在线性表中的“位序”概念已弱化,而被数据元素在线性表中的“位置”所代替。
为此,从实际应用出发角度重新定义线性表及其基本操作
带头结点的线性链表
//一个带头结点的线性链表类型定义如下
typedef struct LNode
{ElemType data;struct LNode *next;
}*Link,*Position;typedef struct //链表类型
{Link head,tail; //分别指向线性链表中的头结点和最后一个结点int len; //指示线性表中数据元素的个数
}LinkList;
//算法2.21
Status ListInsert_L(LinkList &L,int i,ElemType e)
{//在带头结点的单链线性表L的第i个元素之前插入元素if(!LocatePos(L,i-1,h)) return ERROR; //插入位置不合理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); hb=GetHead(Lb); //ha,hb分别指向La和Lb的头结点pa=NextPos(La,ha); pb=NextPos(Lb,hb);//pa和pb分别指向La和Lb中当前结点while(pa&&pb) //La和Lb均非空{a=GetcurElem(pa); b=GetCurElem(pb);//a和b为两表中当前比较元素if((*compare)(a,b)<=0){DeFirst(hb,q);Append(Lc,q);pa=Nextpos(La,ha);}else{DeFirst(hb,q);Append(Lc,q);pb=NextPos(Lb,hb);}}//whileif(pa) Append(Lc,pa); //链接La中剩余结点else Append(Lc,pb); //链接Lb中剩余结点FreeNode(ha); FreeNode(hb);//释放La和Lb的头结点return OK;
}//MergeList_L
2.4一元多项式的表示及相加
数据结构 第二章 线性表相关推荐
- 数据结构第二章-线性表(详细知识点总结)
目录 第二章 线性表 2.1 线性表的定义和操作 2.1.1 线性表的定义 2.1.2 线性表的基本操作 2.2线性表的顺序表示 2.2.1 顺序表的定义 2.2.2 顺序表上基本操作的实现 2.3 ...
- C语言数据结构-第二章线性表-电大
第二章线性表--内容简介 本章将进入线性结构的学习. 线性结构是最简单.最常用的一种数据结构. 本章将学习线性表的定义.顺序和链式两种存储方式及相应存储结构上的运算实现.通过典型示例训练,掌握线性表的 ...
- 王道408数据结构——第二章 线性表
文章目录 一.线性表的定义和基本操作 线性表 顺序表 1.插入操作 2.删除操作 3.按值查找(顺序查找) 二.单链表 1. 头插法 2. 尾插法 3. 按序号查找 4. 按值查找 5. 插入结点 6 ...
- C++ 数据结构第二章 ----- 线性表
文章目录 线性表 线性表的顺序存储 一.基本概念 二.基本操作 线性表的链式存储 一.基本概念 二.基本操作 三.双链表 (1) 双链表的插入操作 (2) 双链表的删除操作 四.循环链表 五.循环双链 ...
- 数据结构第二章线性表学习笔记
1. C++程序设计模板 (关于template的解释)[以下内容摘自百度] 函数声明格式 template <class(或typename) any(或任意符合规则的名称)> ...
- (王道408考研数据结构)第二章线性表-第三节5:顺序表和链表的比较
文章目录 一:逻辑结构比较 二:存储结构比较 三:基本操作比较 (1)初始化操作 (2)销毁操作 (3)插入和删除 (4)查找 顺序表和链表的选取原则 一:逻辑结构比较 顺序表和链表都是线性表,都是线 ...
- (王道408考研数据结构)第二章线性表-第三节1:单链表的定义及其操作(插入和删除,建立之尾插和头插)
文章目录 一:单链表相关 (1)单链表的定义 (2)头指针与头结点 二:单链表代码描述 三:单链表的初始化 四:单链表的插入 五:单链表的删除 六:单链表查找 (1)按位查找 (2)按值查找 七:单链 ...
- (王道408考研数据结构)第二章线性表-第二节1:顺序表的定义
文章目录 一:顺序表实现 (1)静态分配 (2)动态分配 二:顺序表特点 顺序表:也叫做线性表的顺序存储结构,指的是用一段地址连续的存储单元依次存储线性表的数据元素 一:顺序表实现 (1)静态分配 静 ...
- (王道408考研数据结构)第二章线性表-第一节:线性表的定义和基本操作
文章目录 一:线性表的定义 二:线性表的基本操作 一:线性表的定义 线性表(Linear List):零个或多个数据元素的有限序列 元素之间是有顺序的 若元素存在多个,则第一个元素无前驱,最后一个元素 ...
- PTA数据结构第二章线性表
顺序表 1-8 对于顺序存储的长度为N的线性表,访问结点和增加结点的时间复杂度分别对应为O(1)和O(N). T F 1-10 对于顺序存储的长度为N的线性表,删除第一个元素和插入最后一个元素的时间复 ...
最新文章
- 数据库之字段数据类型
- Gitlab环境快速部署(RPM包方式安装)
- .NET小笔记之程序集
- javascript获取url参数的代码
- .NET平台功能最强大,性能最佳的JSON库
- 团队作业—预则立他山之石
- webmagic框架
- vbs教程(1):弹窗
- QT5.14.2 + MSVC2017_64 + MySQL5.7.29 数据库驱动编译及配置
- 【业务安全03】密码找回业务安全
- 腾讯音乐知识图谱搜索实践
- eclipse运行出现an error has occur.see the log file解决办法
- loadrunner mysql性能测试_运用Loadrunner测试Mysql数据库性能 TRON•极客
- 1到10的阶乘 java_1到10的阶乘相加java编程问题
- 在恋爱游戏里跟你实时聊天的“AI”,其实可能是一位抠脚大汉
- 常见的中间件以及什么是中间件
- 关于低功耗输电线路在线监测摄像头,你知道多少
- 机器学习02_吴恩达版学习笔记
- BAS/BRAS/RADIUS简介
- Java继承和多态——子类继承性