线性表的概念及运算解读

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

InsList(L,i,e) 在L的i号元素(1≤i≤Length(L)+1)
之前插入新的元素e, L的长度增1。 DelList(L,i) 删除L的 i号元素(1≤i≤Length(L)), L的长度减1。
2.2 线性表的顺序存储
2.2.1 线性表的顺序存储结构 用一组地址连续的存储单元依次存储线性 表中的各个元素,使得线性表中在逻辑结构上 相邻的数据元素存储在相邻的物理存储单元中, 即通过数据元素物理存储的相邻关系来反映数 据元素之间逻辑上的相邻关系。采用顺序存储 结构的线性表通常称为顺序表。 假设线性表中每个元素占k个单元,第一 个元素的地址为loc(a1),则第k个元素的地址为: loc(ai) =loc(a1)+(i-1)×k
a1 a2
存储地址
Loc(a1)

ai-1 ai
内存空间状态
a1 a2

an
逻辑地址
1 2
线性表的起始地址称作线性表的基地址
Loc(a1)+(2-1)k

loc(a1)+(i-1)k

ai

i

loc(a1)+(n-1)k

an

n
...
loc(a1)+(maxlen-1)k
顺序存储结构的C语言定义
若没有与e相等的元素,则返回值为0。
Locate( L,e) 返回L中第1个与e相等的元素的位序。 Traverse(L,visit( )) 依次对L的每个元素调用函数
visit( )。一旦visit( )失败,则操作失败。
加工型操作
Clear(L) 将L置为空表。 (1≤i≤Length(L) ) Put(L, i, e ) 将e的值赋给L的 i号元素。
再看线性表的存储结构发生的变化
a1 a2 a1 a2
… ai-1 ai ai+1 … an … ai-1 ai+1 … an
表的长度减少
int DelList(SeqList *L,int i,ElemType *e) //在顺序表L中删除序号i的元素,并用e返回值 { int k; if((i<1)||(i>L->last+1)) return 0; *e=L->elem[i-1]; //将删除元素存放到*e中 for(k=i;i<=L->last;k++) // k为下标 L->elem[k-1] = L->elem[k]; //依次左移 L->last--; return 1; //表长减1,返回1 }
引用型操作:
Empty( L ) Length( L ) Prior( L,e) Next( L,e) 若L为空表,则返回TRUE,否则FALSE。 返回L中元素个数。 返回L中元素e的前驱,无则返回空元素。 返回L中元素e的后继,无则返回空元素。
Get( L, i)
返回L中i号元素的值,1≤i≤Length(L)。
用下标表示指针 i 和 j ,初值均为0。
void merge(SeqList *LA,SeqList *LB,SeqList *LC) { i=0; j=0; k=0; //下标初始化 while( i<=LA->last && j<=LB->last ) //归并 if(LA->elem[i]<=LB->elem[j]) { LC->elem[k]=LA->elem[i]; i++; k++; } else{ LC->elem[k]=LB->elem[j]; j++; k++; } while(i<=LA->last) //LA有余将剩余元素赋给表LC { LC->elem[k]=LA->elem[i]; i++; k++; } while(j<=LB->last) //LB有余将剩余元素赋给表LC { LC->elem[k]= LB->elem[j]; j++; k++; } LC->last=LA->last+LB->last+1; }
数据域
D B C H F A G E
指针域 43 13 1 NULL 37 7 19 25 31
单链表的存储结构描述
typedef struct Node //结点类型定义 { ElemType data; struct Node * next; }Node,*LinkList;//LinkList为结构指针类型
#define maxsize=线性表可能达到的最大长度; typedef struct { ElemType elem[maxsize]; // 线性表占用的数组空间 int last; //最后元素在数组中的位置(下标值) } SeqList;
其中elem数组的第 i 个分量为线性表第 i 个 数据元素的存储映像。注意区分元素的序号和 数组的下标,如a1的序号为1,而其对应的数组 下标为0。last 指最后一个数据元素在数组空间 中的位置。空表last置为-1
2. 线性表的特点 • 同一性:线性表由同类数据元素组成, 每 一 个 ai 必 须 属 于 同 一 数 据 对 象 。
• 有穷性:线性表由有限个数据元素组 成,表长度就是表中数据元素的个数。 • 有序性:线性表中相邻数据元素之间 存在着序偶关系<ai, ai+1>。
2.1.2 线性表的抽象数据类型定义
假定线性表中删除任何元素的概率都 相同, 则移动元素次数的期望值为: (n-1)/2
算法时间复杂度为: O(L->last)
例如:DelList(L, 5, e)
// i = 5 指示删除元素的序号 for(k=i;i<=L->last;k++) // k为下标 L->elem[k-1]=L->elem[k];//依次左移元素 L->last--; //表长减1 k k k i
第二章
线性表
2.1 线性表的概念及运算 2.2 线性表类型的实现 顺序映象 2.3 线性表类型的实现 链式映象 2.4 一元多项式的表示及相加
2.1 线性表的概念及运算 2.1.1 线性表的逻辑结构 1. 线性表的定义
线性表(Linear List)是由n (n≥0)个类型相同 的数据元素a1, a2, …, an 组成的有限序列的集合, 记做(a1, a2, …, ai-1, ai, ai+1, …, an)。 当集合非空(n>0)时 , 元素中必存在唯一的 “第一元素” 和唯一的 “最后元素”, 除最后 元素在外, 均有唯一的直接后继, 除第一元素之 外, 均有唯一的直接前驱。
j
0
i
j
j
j
L.last
Biblioteka Baidu
21 18 30 75 42 56 87 21 18 30 75 66 42 56 87
L.last
3. 删除操作Delete(L, i)的实现:
算法分析: 先看删除元素时, 线性表的逻辑结构发生什么变化? (a1, …, ai-1, ai, ai+1, …, an) 改变为 (a1, …, ai-1, ai+1, …, an) <ai-1, ai>, <ai, ai+1> <ai-1, ai+1>
ADT LinearList { 数据元素: D={ai| ai∈D0, i=1,2,…, n n≥0为表长, n=0 为空表 i为 ai 在线性表中的位序。D0为某一数据对象} 关系: S={ <ai, ai+1> | ai, ai+1∈D0,i=1, 2, …, n-1} 基本操作: InitList(L) 操作前提: L为未初始化线性表 操作结果: 将L初始化为空表 DestroyList(L) 操作前提: 线性表L已存在 操作结果: 将L销毁 引用型操作 加工型操作 }ADT LinearList
}
假定在线性表中任何位置上进行插入的概 率都相同等, 则移动元素的期望值为: n/2 所以算法时间复杂度为: O(L->last )
例如:InsLast(L, 5, 66)
{ for(j=L->last;j>=i-1;j--) // j为下标 L->elem[j+1]=L->elem[j]; //右移 L->elem[i-1]=e;L->last++; } //插入,表长增1
int Locate(SeqList L,ElemType e) { i=0 ; // 下标i初值为0,即从第一个元素开始比较 while ((i<=L.last)&&(L.elem[i]!=e) ) i++; // 顺序扫描直到找到值为e的元素,或直到表尾没找到 if (i<=L.last) return(i+1); //若找到值为e的元素, 则返回其序号 else return(-1); //若没找到, 则返回空序号 }
头指针
头结点
线性表为空表时, 头指针 头结点的指针域为空
空指针

a1
a2
… ...
an ^
以线性表中第一个数据元素 a1 的存 储地址作为线性表的地址,称作线性表 的头指针。 有时为了操作方便,在第一个结点之 前虚加一个“头结点”,以指向头结点 的指针为链表的头指针。
单链表的存储示例图
存储地址
头指针 H=49 31 1 7 13 19 25 31 37 43 49
21 18 30 75 42 56 87
0 L->last
21 18 30 75 56 87
L->last
例2-1 归并两个有序表
已知线性表La和Lb中的数据元素按值
非递减有序排列,现要求将La和Lb 归并
为一个新的线性表Lc, 且Lc的数组元素仍 按值非递减有序排列。
如:La=(3,5,8,11) Lb=(2,6,8, 9,11,15,20 ) Lc=(2,3,5,6,8,8,9,11,11,15,20) 可设两个指针 i 和 j 分别指向 La和Lb 中的当前元素a和b,则当前应插入Lc中的 a 当a≤b 时 元素为: c= b 当a>b 时
2. 插入元素操作 InsList(L, i, e) : 算法分析: 先看插入元素时,
线性表的逻辑结构发生什么变化? (a1, …, ai-1, ai, …, an) 变为(a1, …, ai-1, e, ai, …, an) 关系<ai-1, ai> <ai-1, e>, <e, ai>
再看线性表的存储结构发生的变化
算法时间复杂度为:
O(La->last+ Lb->last)
顺序存储结构的优点和缺点 优点: 1.无需为表示结点间的逻辑关系而增加额外的 存储空间; 2.可方便地随机存取表中的任一元素。 缺点: 1.插入或删除运算不方便,除表尾的位置外, 在表的其它位置上进行插入或删除操作都必 须移动大量的结点,其效率较低; 2.由于顺序表要求占用连续的存储空间,存储 分配只能预先进行静态分配。因此当表长变 化较大时,难以确定合适的存储规模。
2.2.2 线性表的顺序存储结构上的基本运算 1. 按内容查找操作: Locate(L, e ) 算法分析:
L.elem L. last
maxlen
23 75 41 38 54 62 17
p p p p p p 原操作是: 将顺序表中的元素逐个 和给定值e相比较。
序号i
8 4 3 2 1
e = 38 50
a1 a2

ai-1 ai

an … an
a1 a2
… ai-1 e
ai
表的长度增加
InsList(SeqList *L, int i, ElemType e) { //在L的序号i元素前插入e,1≤i≤L->last+2
if(i<1 || i>L->last+2 || L->last>maxlen-2) retun 0; //i非法 else { for(j=L->last;j>=i-1;j--) // j为下标 L->elem[j+1]=L->elem[j]; //右移 L->elem[i-1]=e; L->last++; } //插入,表长增1 retun 1;
作业:
《题集》2.2, 2.11。
2.3 线性表的链式存储 2.3.1 单链表
2.3.2 单链表上的基本运算
2.3.3 循环链表 2.3.4 双向链表 *2.3.5 静态链表 2.3.6 顺序表和链表的比较
2.3.1 单链表
结点(Node): 既要存储线性表的每个数据元 素值,又要存储指示其后继结点的地址(或位置) 信息,以表示结点间的逻辑关系。这两部分信息 组成的存储映象叫做结点(Node)。 单链表: 链表中的每个结点只有一个指针域, 我们将这种链表称为单链表。 单链表包括两个域: 数据域用来存储结点的 值; 指针域用来存储数据元素的直接后继的地 址(或位置)。
相关文档
最新文档