第二章线性表2011
第2章--线性表
1
可定义结构体数组
2
例 typedef struct card
{ int num;
char name[20];
n
char author[10];
char publisher[30];
备 float price;
用 }DATATYPE;
空 间
DATATYPE
library[M];
通信工程学院
顺序表的基本运算
从} ai+1开始向后逐个元素向前移动
a1 a2 ai-1 ai ai+1… an
for( j = i; j < list.n; j++){
list.a[ j ] = list.a[ j+1 ];
}20.09.2019
通信工程学院
删除运算
void delete( list, i , y ){
1.从ai+1节点开始向后,逐个向前搬动节点, 挤掉第i个元素
四.查找(算法2.4) 线性表的查找是指找出数据元素x在表
中的位序号,若v[i]==x,则算法返回值为i+1, 若不存在数据元素x则返回0
20.09.2019
通信工程学院
顺序存储的线性表
数组顺序存储结构的特点
任意元素获取容易实现,定位简单
存取时间短,存取时间与元素位置无关
元素更动(比如:插入和删除)时的搬移性
20.09.2019
通信工程学院
顺序存储的线性表
线性表的顺序分配是指:用一组连续编号的存 储单元依次存放各个数据元素。 根据一个数据元素占据m个存储单元,有:
LOC(ai)=LOC(a1)+(i-1)×m 用一维数组来实现线性表顺序存储结构
《数据结构》--第二章线性表
《数据结构》--第二章线性表《数据结构》第二章线性表在计算机科学中,数据结构是一门非常重要的基础课程,它为我们有效地组织和管理数据提供了理论和方法。
而在数据结构的众多内容中,线性表是一个关键且基础的概念。
线性表,简单来说,就像是一排整齐排列的元素。
这些元素按照一定的顺序依次排列,每个元素都有其特定的位置。
想象一下排队买奶茶的人群,从第一个人到最后一个人,就形成了一个线性的队列,这就是一种线性表的形象体现。
线性表具有一些显著的特点。
首先,它的元素个数是有限的。
就像排队买奶茶的队伍,长度不可能是无限的。
其次,元素具有相同的数据类型。
比如在一个记录学生成绩的线性表中,每个元素都是学生的成绩数据。
再者,元素之间是顺序排列的,有先后之分。
从存储结构上来看,线性表可以分为顺序存储和链式存储两种。
顺序存储的线性表,就好比是把一系列物品紧密地摆放在一个连续的空间里。
比如,我们可以把一系列数字存储在一个连续的数组中。
这种存储方式的优点是可以随机访问,也就是说,如果我们想获取第 5 个元素,直接通过计算就可以快速得到。
但它也有缺点,那就是插入和删除操作比较麻烦。
当我们要在中间插入一个新元素时,可能需要移动后面的一系列元素来腾出位置;删除一个元素时,又需要把后面的元素向前移动来填补空缺。
相比之下,链式存储的线性表就灵活得多。
它就像是一串珍珠,每个珍珠(节点)通过一根线(指针)与下一个珍珠相连。
每个节点包含数据域和指针域,数据域用来存放数据,指针域则指向链表中的下一个节点。
链式存储的优点是插入和删除操作比较方便,只需要修改相关节点的指针即可。
但它的缺点是不能随机访问,要找到特定位置的元素,需要从链表的头开始逐个遍历。
线性表在实际应用中无处不在。
比如,我们的通讯录就是一个线性表,按照联系人的添加顺序依次排列。
操作系统中的任务队列也是线性表,任务按照先后顺序等待被执行。
在编程实现线性表时,我们需要根据具体的需求来选择合适的存储方式。
第二章线性表
//最后元素在数组中的位置(下标值)
} SeqList;
其中elem数组的第 i 个分量为线性表第 i 个 数据元素的存储映像。注意区分元素的序号和 数组的下标,如a1的序号为1,而其对应的数组 下标为0。last 指最后一个数据元素在数组空间 中的位置。空表last置为-1
#define LIST_INIT_SIZE 100//线性存储空间 的初始分配量 #define LISTINCREMENT 10//线性表存储空 间的分配增量
内存空间状态
a1 a2
…
ai
…
an
逻辑地址
1 2
…
i
…
n
...
loc(a1)+(maxlen-1)k
顺序存储结构的C语言定义
#define maxsize=线性表可能达到的最大长度;
typedef struct
{ ElemType elem[maxsize]; // 线性表占用的数组空间
int last;
若没有与e相等的元素,则返回值为0。 Traverse(L,visit( )) 依次对L的每个元素调用函数
visit( )。一旦visit( )失败,则操作失败。
加工型操作
Clear(L) 将L置为空表。 Put(L, i, e ) 将e的值赋给L的 i号元素。
(1≤i≤Length(L) ) InsList(L,i,e) 在L的i号元素(1≤i≤Length(L)+1)
注:这里的数据元素ai(1≤i≤n)只是一个抽象的 符号,其具体含义在不同的情况下各不相同。
例1 26个英文字母组成的字母表: (A,B,C、…、Z)
例2 某校从1978年到1983年各种型 号的计算机拥有量的变化情况:
数据结构第二章:线性表
实现:可用C 实现:可用C语言的一维数组实现
6
V数组下标 0 1
内存 a1 a2
元素序号 1 2
typedef int DATATYPE; #define M 1000 DATATYPE data[M]; 例 typedef struct card { int num; char name[20]; char author[10]; char publisher[30]; float price; }DATATYPE; DATATYPE library[M];
4
{加工型操作 加工型操作} 加工型操作
ClearList( &L ) 初始条件:线性表 L 已存在。 操作结果:将 L 重置为空表。 PutElem( &L, i, &e ) 初始条件:线性表L已存在,1≤i≤LengthList(L)。 操作结果:L 中第 i 个元素赋值同 e 的值 ListInsert( &L, i, e ) 初始条件:线性表 L 已存在,1≤i≤LengthList(L)+1。 操作结果:在 L 的第 i 个元素之前插入新的元素 e,L 的长度增1。 ListDelete( &L, i, &e ) 初始条件:线性表 L 已存在且非空,1≤i≤LengthList(L)。 操作结果:删除 L 的第 i 个元素,并用 e 返回其值,L 的长度减1。 }ADT LIST
3
PriorElem( PriorElem L, cur_e, &pre_e ) 初始条件:线性表 L 已存在。 操作结果:若 cur_e 是 L 中的数据元素,则用 pre_e 返回 它的前驱,否则操作失败,pre_e 无定义。 NextElem( NextElem L, cur_e, &next_e ) 初始条件:线性表 L 已存在。 操作结果:若 cur_e 是 L 中的数据元素,则用 next_e 返 回它的后继,否则操作失败,next_e 无定义。 GetElem( GetElem L, i, &e ) 初始条件:线性表 L 已存在,1≤i≤LengthList(L)。 操作结果:用 e 返回 L 中第 i 个元素的值。 LocateElem( LocateElem L, e, compare( ) ) 初始条件:线性表 L 已存在,compare( ) 是元素判定函数。 操作结果:返回 L 中第1个与 e 满足关系 compare( ) 的元 素的位序。若这样的元素不存在,则返回值为0。 ListTraverse(L, visit( )) ListTraverse 初始条件:线性表 L 已存在,visit( ) 为元素的访问函数。 操作结果:依次对 L 的每个元素调用函数 visit( )。 一旦 visit( ) 失败,则操作失败。
第2章线性表
(1) 将线性表L中的第i+1个至第n个结点依此向前移 动一个位置。
(2) 线性表长度减1。
算法描述
Status Delete_SqList(Sqlist &L,int i, ElemType &e)
{
if (L.length==0) { printf(“线性表L为空!\n”); return ERROR; }
◆ 删除时平均移动次数:Edelete=∑pi*(n-i) (1≦i≦n) ∴ Edelete=(n-1)/2 。
平均时间复杂度:Ecompare+Edelete=n ,即为O(n)
2.3 线性表的链式存储
2.3.1 线性表的链式存储结构
链式存储 :用一组任意的存储单元存储线性表
中的数据元素。用这种方法存储的线性表简称线性链 表。
{ ElemType Elem_array[MAX_SIZE] ; int length ;
} SqList ; 如何?
(3) 用下述结构类型来定义顺序表类型,有何不同? typedef int Status ; typedef int ElemType ; #define LIST_INIT_SIZE 100 #define LISTINCREMENT 10
Status Insert_SqList(Sqlist &L,int i, ElemType e)
{if ( i<1||i>L.length+1) return ERROR ;
if (L.length>=L.listsize)
{ newbase=( ElemType* )realloc(L. elem, (L.listsize+LISTINCREMENT)*sizeof( ElemType ) ) ; if ( !newbase ) exit(OVERFLOW);
第2章 线性表(链表)
}
4.判线性表是否为空表ListEmpty(L)
若单链表L没有数据结点,则返回1,否则返回0。
int ListEmpty(LinkList *L)
{
return(L->next==NULL); }
5.求线性表的长度ListLength(L)
返回单链表L中数据结点的个数。
int ListLength(LinkList *L) { LinkList *p=L->next;int i=0; while (p!=NULL)
第三步:尾插法链接结点
r->next=s; r=s;
• 再循环23步骤直到n个结点完成插入
r
L
s
r
头结点
a
void CreateListR(LinkList *L,ElemType a[],int n) { LinkList *s,*r;int i; r=L; for (i=0;i<n;i++) { s=(LinkList *)malloc(sizeof(LinkList)); /*创建新结点*/ s->data=a[i]; r->next=s; /*将*s插入*r之后*/ r=s; } r->next=NULL; /*终端结点next域置为NULL*/ }
存储结点包含 数据域:所有存元素本身的信息;
指针域:元素之间逻辑关系的信息;包含有后 继结点的地址信息。
2个问题 如何构造链表数据类型? 链表上可进行什么基本操作?
解决第一个问题---如何构造链表数据类型
在每个结点中除包含有数据域外,只设置一个指针域, 用以指向其后继结点,这样构成的链接表称为线性单 向链接表,简称单链表;
{ s=(LinkList *)malloc(sizeof(LinkList));
第二章 线性表
插入、删除算法分析
设在线性表第 i 个元素前插入一新元素的概率为 Pi,删除 第 i 个元素的概率为 Qi,元素移动为算法的基本操作。则插 入和删除的平均移动期望值为:
3、置空线性链表
void clearList_L(LinkList *L)
{ p=L->next; L->next=NULL; while(p) { q=p->next; free(p); p=q; } }
线性链表的访问运算
4、访问第i个数据元素:先找到第i各结点
Status GetElem_L(LinkList L,int i,ElemType &e) { p=L->next;j=1;
取第个i数据元素
LocateElem(L,x):
定位函数
PriorElem(L,elm,&pre_e): 求元素elm的前驱
NextElem(L,elm,&next_e): 求元素elm的后继
ListInsert(&L,i,e):
在第个i元素之前插入元素e
ListDelete(&L,i,&e):
删除第i个元素
{ i=LocateElem_Sq(L, e,compare); if(i>=2) { pre_e=L.elem[i-2]; return(1);} else return(0); }
status NextElem_Sq(SqList L,ElemType e,ElemType &next_e, Status(*compare)(ElemType,ElemType))
第2章 线性表
(9) ListDelete (&L, i, &e)
初始条件: 表L已存在且非空, 1≤i≤ListLength(L)。
操作结果: 删除L的第i个数据元素, 并用e返回其值, L
的长度减1。 } ADT List
第2章 线 性 表 例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); } } O(Listlength(LA)* Listlength(LB))
第2章 线 性 表
假设线性表中有n个元素,每个元素占k个单元,第一
个元素的地址为loc(a1),则可以通过如下公式计算出第i个
元素的地址loc(ai):
loc(ai) =loc(a1)+(i-1)×k
其中loc(a1)称为基地址。 它是一种随机存取的数据结构。
第2章 线 性 表
存储地址 loc(a1 ) loc(a1 )+k 内存空间状态 a1 a2 逻辑地址 1 2
构类型但同一线性表中的数据元素必须属于同一数据对象。此外,
线性表中相邻数据元素之间存在着序偶关系,即对于非空的线性
表(a1, a2, …,ai-1, ai, ai+1, …, an), 表中ai-1 领先于ai,称ai-1 是ai 的直接前驱,而称ai是 ai-1的直接后继。除了第一个元素a1外,每
第二章线性表
第二章线性表1.什么是顺序存储结构?什么是链式存储结构?线性表的顺序存储指的是用一组地址连续的存储单元依次存储线性表的数据元素,它的特点是,线性表中相邻的元素a[i]和a[i+1]赋以相邻的存储位置LOC(a i) 和LOC(a i+ 1 ) 。
即,以元素在计算机内"物理位置相邻"来表示线性表中数据元素之间的逻辑关系。
简言之逻辑相邻,物理相邻。
相邻元素之间查一个元素所占的物理空间,因此,只要确定了存储线性表的起始位置,线性表中任一数据元素都可随机存取,所以线性表的顺序存储结构是一种随机存取的存储结构。
线性量的链式存储结构的特点是用一组任意的存储单元存储线性表的数据元素(这组存储单元可以是连续的,也可以是不连续的) . 因此,为了表示每个数据元素a i与其直接后继数据元素a i+ 1之间的逻辑关系,对数据元素a i来说,除了存储其本身的信息之外,还需存储-个指示其直接后继的信息〈即直接接后继的存储位置〉. 这两部份信息组成数据元素a i的存储映映像,称为结点(node) . 它包括两个域:其中存储数据元素信息的称为数据域,存储直接后继存储位置的域称为指针域. 指针域中存储的信息称做指针或链.2.线性表的顺序存储结构和链式存储结构各有什么特点?顺序存储结构,逻辑相邻的元素,物理上也相邻,每个结点只需存储数据本身,不许存储逻辑关系,节约存储空间,查找元素方便,但插入或删除元素需要大量移动元素,效率低。
适合查找多但插入删除少的情况。
链式存储结构,逻辑上相邻的元素,物理上不一定相邻,每个结点除了存储元素本身外,还要存储元素之间的逻辑关系,占用存储空间大,但查找元素都要从头开始,查找费时间,但插入或删除元素不需要大量移动元素,只需要知道插入或删除位置结点的前驱指针,进行简单的指针变换即可。
适合查找少,插入删除相对多的情况。
3.设线性表中数据元素的总数基本不变,并很少进行插入或删除工作,若要以最快的速度存取线性表中的数据元素,应选择线性表的何种存储结构?为什么?用顺序存储,原因在1 和2之间;4.线性表的主要操作有哪些?1).InitList(&L) 初始化:构造一个空的线性表L。
第2章 线性表
【例2】巳知有两个按元素值递增有序的顺序表La和 Lb,设计一个算法将表La和表Lb的全部元素归并 为一个按元素值递增有序的顺序表Lc。
算法思路:用i扫描顺序表La,用j扫描顺序表Lb。 当表La和表Lb都未扫描完时,比较两者的当前元 素,将较小者插入表Lc的表尾,若两者的当前元 素相等,则将这两个元素依次插入表Lc的表尾。 最后,将尚为扫描完的顺序表的余下部分元素依 次插入表Lc的表尾。算法如下: void MergeList_Sq(SqList La, SqList Lb, SqList &Lc)
表中ai-1领先于ai,称ai-1是ai的直接前驱,ai+1是 ai的直接后继。
线性表的抽象数据类型定义 (参见教材)
返回本章目录
2.2 线性表的顺序存储结构
线性表的顺序存储是指在内存中用地址连续的一块存储空间 依次存放线性表的数据元素,用这种存储形式存储的线性表 称其为顺序表。 假设每个数据元素占d个存储单元,且将ai的存储地址表示为 Loc(ai),则有如下关系: Loc(ai)=Loc(a1)+(i-1)*d Loc(a1)是线性表的第一个数据元素a1的存储地址,通常 称作线性表的基地址。
【例1】 编写一算法,从顺序表中删除自第i个元素开 始的k个元素。 算法思路: 为保持顺序表的逻辑特性,需将i+k ~ n位 置的所有元素依次前移k个位置。算法如下:
int deleteK(Sqlist &sq,int i,int k)
{ if (i<1||k<1||i+k-1>sq.len) return 0; for (j=i+k-1;j<=sq.len-1;j++) sq.data[j-k]=sq.data[j]; sq.len-=k; return 1; }// deleteK
2011年自考数据结构课后习题答案_黄刘生
第一章绪论1.1 简述下列概念:数据、数据元素、数据类型、数据结构、逻辑结构、存储结构、线性结构、非线性结构。
● 数据:指能够被计算机识别、存储和加工处理的信息载体。
● 数据元素:就是数据的基本单位,在某些情况下,数据元素也称为元素、结点、顶点、记录。
数据元素有时可以由若干数据项组成。
● 数据类型:是一个值的集合以及在这些值上定义的一组操作的总称。
通常数据类型可以看作是程序设计语言中已实现的数据结构。
● 数据结构:指的是数据之间的相互关系,即数据的组织形式。
一般包括三个方面的内容:数据的逻辑结构、存储结构和数据的运算。
● 逻辑结构:指数据元素之间的逻辑关系。
● 存储结构:数据元素及其关系在计算机存储器内的表示,称为数据的存储结构.● 线性结构:数据逻辑结构中的一类。
它的特征是若结构为非空集,则该结构有且只有一个开始结点和一个终端结点,并且所有结点都有且只有一个直接前趋和一个直接后继。
线性表就是一个典型的线性结构。
栈、队列、串等都是线性结构。
● 非线性结构:数据逻辑结构中的另一大类,它的逻辑特征是一个结点可能有多个直接前趋和直接后继。
数组、广义表、树和图等数据结构都是非线性结构。
1.2 试举一个数据结构的例子、叙述其逻辑结构、存储结构、运算三个方面的内容。
答:例如有一张学生体检情况登记表,记录了一个班的学生的身高、体重等各项体检信息。
这张登记表中,每个学生的各项体检信息排在一行上。
这个表就是一个数据结构。
每个记录(有姓名,学号,身高和体重等字段)就是一个结点,对于整个表来说,只有一个开始结点(它的前面无记录)和一个终端结点(它的后面无记录),其他的结点则各有一个也只有一个直接前趋和直接后继(它的前面和后面均有且只有一个记录)。
这几个关系就确定了这个表的逻辑结构是线性结构。
这个表中的数据如何存储到计算机里,并且如何表示数据元素之间的关系呢? 即用一片连续的内存单元来存放这些记录(如用数组表示)还是随机存放各结点数据再用指针进行链接呢? 这就是存储结构的问题。
02-第2章线性表第1讲-线性表的基本概念
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;
【示例2-1】利用两个线性表LA和LB分别表示两个集合 A和B,现要求一个新的集合A=A∪B。
代码实现:
void Union(SqList &La, SqList Lb)
{
ElemType e;
int La_len, Lb_len;
int i;
La_len = ListLength(La);
// 求线性表的长度
求线性表中第i个元素GetElem(L,i,e)。其作用是 返回线性表L的第i个数据元素。
按值查找LocateElem(L,x)。若L中存在一个或多个 值与x相等的元素,则其作用是返回第一个值为x的元 素的逻辑序号。
插入元素ListInsert(L,i,x)。其作用是在线性表L 的第i个位置上增加一个以x为值的新元素
}
else {
ListInsert(Lc, ++k, bj);
++j;
}
}
// 以下两个while循环只会有一个被执行
while(i <= La_len) {
// 表La非空且表Lb空
GetElem(La, i++, ai);
ListInsert(Lc, ++k, ai);
数据结构 第二章 线性表
2.2 线性表的顺序存储
2.2.1 顺序表
线性表的结点按逻辑次序存放在一组地址连续 的存储单元里。 设LOC( ai )为顺序中第i个结点的存储地址,则 LOC( ai )=LOC( ai-1 )+*c LOC( ai )=LOC( a1 )+( i-1 )*c 1≤ i ≤n 其中 n为表长,c为每个结点存储单元长度。
第二章 线性表
☞ ☞ ☞ ☞ 线性表的概念及运算 线性表的顺序存储 线性表的链表存储 顺序表和链表的比较
2.1 线性表的概念及运算
2.1.1线性表的逻辑结构
定义:线性表(Linear List)是由n(n ≥ 0)个 数据元素a1,a2,a3,……. , an组成的有限序列。 其中数据元素个数n为表的长度。n=0时表为空 表,非空的线性表(n≥0)可记作: ( a1,a2,a3,……. , an ) 即表示为数据元素的非空有限集合。
datatype Get(LIST *L, int i) 取结点(第i个结点)
int Locate(LIST *L, datatype x) 定位(首个值为x的结点位置) void Insert(LIST *L, datatype x, int i) 插入(在i与i+1结点之间) void Delete(LIST *L, int i) 删除(第i结点) bool Empty(LIST *L) 判表空
Eis P ) i (n i 1
i 1 n 1
若认为Pi
1 n ห้องสมุดไป่ตู้1
T n On
1 n 1 n 则Eis ( n i 1 ) n 1 i 1 2
int Deletet(LIST *L, int i) //删除表中第i个结点 { if( i<1 || i> L→ last+1) //判无效位置
数据结构导论 第2章 线性表
线性表是一种线性结构,线性结构的特点是数据元 素之间是一种线性关系,数据元素“一个接一个的 排列”。 线性结构是n(n>=0)个结点的有穷序列。对于 n>0的线性结构表示成: (a1,a2,… ai-1,ai,ai+1,…an) a1称为起始结点 an称为终端结点 起始结点, 终端结点; 起始结点 终端结点 ai-1 称为 ai 的直接前趋 i+1 称为 ai 的直接后继 直接前趋,a 直接后继。 直接前趋 直接后继
4.查找(定位) locate(L,x): .查找(定位) :
依次将顺序表L中的每个元素与给定的值x进行比 较。若找到则返回其序号(下标+1),否则返回0。 int locate (sqlist L, datatype x) { int i; for ( i=0; i<st; i++) if (L.data[i]==x) return (i+1); return(0); }
void insert (sqlist *L, datatype x, int i ) { if (i<1 || i>L->last+1) error (“插入位置错误”); else if (L->last==maxsize) error (“溢出”); else { for (j=L->last-1; j>=i-1; j--) //往后移动元素 //往后移动元素 L->data[j+1]=L->data[j]; L->data[i-1]=x; //插入x L->last++; //修改表长 } }
常见的线性表的基本运算有以下几个: 常见的线性表的基本运算有以下几个:
第二章_线性表(参考答案)
第二章线性表一、填空题1、数据逻辑结构包括线性结构、树型结构、图型结构这三种类型,树形结构和图形结构合称为非线性结构。
2、在线性结构中,第一个结点没有前驱结点,其余每个结点有且只有个前驱结点,最后一个结点没有后续结点,其余每个结点有且只有一个后续结点。
3、在顺序表中插入或删除一个元素,需要平均移动一半元素,具体移动的元素个数与插入或删除的位置有关。
4、在顺序表中,逻辑上相邻的元素,其物理位置一定相邻。
在单链表中,逻辑上相邻的元素,其物理位置不一定相邻。
5、在带头结点的非空单链表中,头结点的存储位置由头指针指示,首元素结点的存储位置由头结点的next域指示,除首元素结点外,其它任一元素结点的存储位置由其直接前趋结点的next域指示。
6、阅读下列算法,并补充所缺内容。
void purge_linkst( ListNode *& la ){// 从头指针为 la 的有序链表中删除所有值相同的多余元素,并释放被删结点空间ListNode *p,*q;if(la==NULL) return;q=la; p = la->link;while (p){if (p && ___(1)p->data!=q->data___) {q=p; p = p->link;}else{q->link= ___(2)p->link___;delete(p);p=___(3)q->link___;}}//while}// purge_linkst二、选择题1、在数据结构中,从逻辑上可以把数据结构分成 C。
A、动态结构和静态结构B、紧凑结构和非紧凑结构C、线性结构和非线性结构D、内部结构和外部结构2、线性表的逻辑顺序与存储顺序总是一致的,这种说法 B。
A、正确B、不正确3、线性表若采用链式存储结构时,要求内存中可用存储单元的地址D。
A、必须是连续的B、部分地址必须是连续的C、一定是不连续的D、连续或不连续都可以4、在以下的述叙中,正确的是B。
数据结构第二章线性表
线性表的顺序存储结构可用数组来实现。 数组元素的类型就是线性表中数据元素 的类型,数组的大小,最好大于线性表 的长度。因此,顺序存储结构是把线性 表中每个元素a1, a2, a3, …, an依次存放到数 组下标为0, 1, 2,…, n1的位置上。
假设用数组data[MAXSIZE]存储线性 表 A =(a1, a2, a3, …, an) 其顺序存储结构如图2.1所示。
➢2.2.1 线性表的顺序存储结构 ➢2.2.2 顺序表的基本运算 ➢2.2.3 插入和删除运算的时间分析 ➢2.2.4 顺序表的优点和缺点
2.2.1 线性表的顺序存储结构
线性表的顺序存储方法是:将线性表的所有元素 按其逻辑顺序依次存放在内存中一组连续的存储 单元中,也就是将线性表的所有元素连续地存放 到计算机中相邻的内存单元中,以保证线性表元 素逻辑上的有序性。 顺序表的特点是:其逻辑关系相邻的两个结点在 物理位置上也相邻,结点的逻辑次序和物理次序 一致。
图2.1 顺序存储结构示意图
由于线性表中所有结点的数据类型是相同 的,因此每个结点占用的存储空间也是
相同的。假设每个结点占用d个存储单元,
若 线 性 表 中 第 一 个 结 点 a1 的 存 储 地 址 为 LOC(a1) , 那 么 结 点 ai 的 存 储 地 址 LOC(ai) 可以通过下面的公式计算得到:
【例2.3】学生成绩统计表也是一个线性表, 见表2.1。在线性表中每个学生的成绩是
一个数据元素,它由学号、姓名、数学、 外语、物理、总分这6个数据项组成。该 线性表的长度为5。
学号 1 2 3 4 5
姓名 李华 王放 张利 田勇 成惠
表 2.1 某班学生成绩统计表
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
2.2.2
典型操作的算法实现
1. 初始化线性表L int InitList(SQ_LIST *L) { L->item=(EntryType*)malloc(LIST_MAX_LENGTH *sizeof(EntryType)); //分配空间 if (L->item==NULL) return ERROR; 成功,返回ERROR //若分配空间不
设n个人围坐在一个圆桌周围,现在从第s个人开始报数, 数到第m个人,让他出局;然后从出局的下一个人重新开始报 数,数到第m个人,再让他出局,……,如此反复直到所有的 人全部出局为止。下面要解决的Josephus问题是:对于任意给 定的n, s和m,求出这n个人的出局序列。请以n = 9, s = 1, m = 5 为例,人工模拟Josephus的求解过程以求得问题的解。
数据元素之间的前后关系,即线性表的逻辑结构与存 储结构(物理结构)一致;
(2)在访问线性表时,可以利用上述给出的数学 公式,快速地计算出任何一个数据元素的存储地址。 因此,我们可以粗略地认为,访问每个数据元素所花 费的时间相等。这种存取元素的方法被称为随机存取 法,使用这种存取方法的存储结构被称为随机存储结 构。 在C语言中,实现线性表的顺序存储结构的类型定 义 #define LIST_MAX_LENGTH 100 //线性表的 最大长度 typedef struct { EntryType *item; //指向存放线性表中数据元 素的基地址 int length; //线性表的当前长度 }SQ_LIST;
0
k=9 k=8 k=7 k=6 k=5 k=4 k=3 k=2 1 1 2 2 2 2 2 2 8 逆置 5
1
2 2 3 3 3 6 8 8 2 1
2
3 3 4 4 6 8 9 9 9 7
3
4 4 6 6 8 9 6 6 6 4
4
5 6 7 8 9 3 3 3 3 3
5
6 7 8 9 4 4 4 4 4 6
head
a
b
c
d
^
图 2-3 单联表结构示意图
其中,head是头指针,它指向单链表中的第一个 结点,这是单链表操作的入口点。由于最后一个结点 没有直接后继结点,所以,它的指针域放入一个特殊 的值NULL。NULL值在图示中常用(^)符号表示。 带头结点的单链表 为了简化对链表的操作,人们经常在链表的第一 个结点之前附加一个结点,并称为头结点。这样可以 免去对链表第一个结点的特殊处理。如下图2-4所示:
线性表的链式存储结构 线性表的链式存储结构是指用一组任意的存储单 元(可以连续,也可以不连续)存储线性表中的数据 元素。为了反映数据元素之间的逻辑关系,对于每个 数据元素不仅要表示它的具体内容,还要附加一个表 示它的直接后继元素存储位置的信息。假设有一个线 性表(a,b,c,d),可用下图2-2所示的形式存储:
图2-1 线性表顺序存储结构示意图
其中,L为每个数据元素所占据的存储单元数目。
相邻两个数据元素的存储位置计算公式 LOC(ai+1)=LOC(ai)+L 线性表中任意一个数据元素的存储位置的计算公 式为:
LOC(ai+1)=LOC(a1)+(i-1)*L
顺序存储结构的特点
(1)利用数据元素的存储位置表示线性表中相邻
2.1.2
线性表的基本操作
1. 初始化线性表L InitList(L) 2. 销毁线性表L DestoryList(L)
3. 清空线性表L ClearList(L)
4. 求线性表L的长度 ListLength(L) 5. 判断线性表L是否为空 IsEmpty(L) 6. 获取线性表L中的某个数据元素内容 GetElem(L,i,e) 7. 检索值为e的数据元素 LocateELem(L,e) 8. 返回线性表L中e的直接前驱元素 PriorElem(L,e) 9. 返回线性表L中e的直接后继元素 NextElem(L,e) 10. 在线性表L中插入一个数据元素 ListInsert(L,i,e) 11. 删除线性表L中第i个数据元素 ListDelete(L,i,e)
6
7 8 9 7 7 7 7 7 7 9
7
8 9 1 1 1 1 1 1 1 2
8
9 5 5 5 5 5 5 5 5 8 第5人出局, i = 4 第1人出局, i = 0 第7人出局, i = 4 第4人出局, i = 2 第3人出局, i = 1 第6人出局, i = 1 第9人出局, i = 2 第2人出局, i = 0 第8人出局, i = 0 最终出局顺序
2.3 线性表的链式存储结构
线性表顺序存储结构的特点 它是一种简单、方便的存储方式。它要求线性表 的数据元素依次存放在连续的存储单元中,从而利用 数据元素的存储顺序表示相应的逻辑顺序,这种存储 方式属于静态存储形式。 暴露的问题 在做插入或删除元素的操作时,会产生大 量的数据元素移动; 对于长度变化较大的线性表,要一次性地 分配足够的存储空间,但这些空间常常又得不到充分 的利用; 线性表的容量难以扩充。
插入算法的分析
假设线性表中含有n个数据元素,在进行插入操作 时,若假定在n+1个位置上插入元素的可能性均等,则 平均移动元素的个数为:
删除算法的分析
在进行删除操作时,若假定删除每个元素的可能 性均等,则平均移动元素的个数为:
1 n 1 Edl (n i) n i 1 2
n
分析结论 顺序存储结构表示的线性表,在做插入或删除操 作时,平均需要移动大约一半的数据元素。当线性表 的数据元素量较大,并且经常要对其做插入或删除操 作时,这一点需要值得考虑。
head
a
b
c
d ^
图 2-4 带头结点的单链表结构示意图
链式存储结构的特点 (1)线性表中的数据元素在存储单元中的存放顺
序与逻辑顺序不一定一致;
(2)在对线性表操作时,只能通过头指针进入链
表,并通过每个结点的指针域向后扫描其余结点,这
样就会造成寻找第一个结点和寻找最后一个结点所花 费的时间不等,具有这种特点的存取方式被称为顺序 存取方式。
在C语言中,实现线性表的链式存储结构的类型定义 typedef strcut node{ //结点类型
EntryType item;
struct node *next;
}NODE;
typedef struct{ //链表类型
NODE *head;
}LINK_LIST;
2.3.2 典型操作的算法实现 1. 初始化链表L
int GetElem(SQ_LIST L,int i,EntryType *e) { if (i<1||i>L.length) return ERROR; 若不合理,返回ERROR *e=L.item[i-1]; //数组中第i-1的单元存储着线性表中 //判断i值是否合理,
第i个数据元素的内容 return OK; }
举例 La=(34,89,765,12,90,-34,22) 数据元 素类型为int。 Ls=(Hello,World, China, Welcome) 数据 元素类型为string。 Lb=(book1,book2,...,book100) 数据元素类型为下列 所示的结构类型: struct bookinfo{ int No; //图书编号 char *name; //图书名称 char *auther; //作者名称 ...; }
int InitList(LINK_LIST *L)
{ L->head=(*NODE)malloc(sizeof(NODE)); //为头结点分配存储单元 if (L->head) {L->head->next=NULL; return OK;} else return ERROR ; }
存储地址 100 ... 120 ... 144 ... 160 ...
内容 b ... c ... a ... d ...
首元素位置
直接后继存储地 址 120 ... 160 .. 100 ... NULL ...
图2-2 线性表链式存储结构示意图
术语 表示每个数据元素的两部分信息组合在一起被称 为结点; 其中表示数据元素内容的部分被称为数据域 (data); 表示直接后继元素存储地址的部分被称为指针或 指针域(next)。 单链表简化的图2-3描述形式
2.2 线性表的顺序存储结构
2.2.1 线性表的顺序存储结构
线性表的顺序存储结构是指用一组连续的存储单
元依次存储线性表中的每个数据元素。如下图2-1所示:
存储地址 d d+L d+2L ... d+(i-1)L ... d+(n-1)L ...
内存单元 ... a1 a2 a3 ai an ...
7. 在线性表L中检索值为e的数据元素
int LocateELem(SQ_LIST L,EntryType e) { for (i=0;i< L.length;i++) if (L.item[i]==e) return i+1;元素之前插入数据元素e int ListInsert(SQ_LIST *L,int i,EntryType e) { if (L->length==LIST_MAX_LENGTH) return ERROR; //检查是否有剩余空间 if (i<1||i>L->length+1) return ERROR; //检查i 值是否合理 for (j=L->length-1;j>=i-1;i++) //将线性表第i个元素之 后的所有元素向后移动 L.->item[j+1]=L->item[j]; L->item[i-1]=e; //将新元素的内容放入线性表的第i 个位置, L->length++; return OK; }