第二章 顺序表
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
22
算法时间性能分析
时间主要花费在元素前移上
设Pi是删除第i个元素的概率,则在长度为n的线性表 中删除一个元素所需移动的元素的平均次数为:
n
Ede Pi (n i) i 1
若认为p 1 等概率
i
n
则E de
1 n
n
(n
i 1
i)
n 1 2
Tn On
故在顺序表中插入或删除一个元素时,平均移
/*顺序表当前长度,即已存入的元素个数*/
int listsize;
/*当前存储空间容量*/
}sqlist;
动态申请和释放内存 ElemType *data = (ElemType *)malloc(INITSIZE*sizeof(ElemType)); free(data);
元素存放在data[0]到data[length-1]中。
算法思想:设表L是一个空表,为使L也是非递减有序 排列,可设两个指针i,j分别指向表L1和L2中的元素, 从两个顺序表的第1个元素开始进行比较: 若L1.data[i]≤L2.data[j],将L1.data[i]插入到L表尾 若L1.data[i]>L2.data[j],将L2.data[j]插入到L表尾 如此进行下去,直到其中一个表被扫描完毕,然后再 将未扫描完的表中剩余的所有元素放到表L中。
18
顺序表插入操作时间性能分析:
插入操作的时间主要花费在元素后移上
设Pi是在第i个元素之前插入一个元素的概率,则在 长度为n的线性表中插入一个元素时,所需移动的 元素的平均次数为:
n1
Eins
P(n i
i
1)
i 1
若认为P 1 i n 1
则Eins
1
n1
n
(n i 1)
n 1 i1
Loc(a1)+(n-1)k
…
…
内存 空间
a1 a2
ai
an
…
……
逻辑 地址
1 2
i
n 空闲
Hale Waihona Puke Baidu
9
图2.1 顺序表
特点: 实现逻辑上相邻—物理地址相邻 实现随机存取
实现:可用C语言的一维数组实现, 这里采用动态分配的一维数组,在初始化时先
用函数malloc()为顺序表分配一个基本容量, 在操作过程中,若顺序表的空间不足,再用函数 realloc()增加空间。
动表的一半元素,当n很大时,效率很低
23
(7)输出操作 void print(sqlist L) { int i; for(i=0; i<L->length;i++) printf(“%4d ”,L->data[i]); printf(“\n”); }
24
例 有两个顺序表L1和L2,其元素均为非递减有 序排列, 编写算法,将其合并成一个顺序表L, 要 求L也是非递减有序排列。 例如L1=(2, 2, 3), L2=(1, 3, 3, 4), 则L=(1, 2, 2, 3, 3, 3, 4)。
int getelem(sqlist L,int i, ElemType *e) {/*取出顺序表L的第i个数据元素的值*/
if (i>=1 && i<=L.length) {*e = L.data[i-1]; return 1;}
else return 0;
} 算法性能分析:时间性能 O(1) 空间性能 O(1)
20
数组下标 内存 元素序号 数组下标 内存 元素序号
0
a1
1
1
a2 2
0
a1
1
1
a2
2
i-1 ai i
i
ai+1 i+1
i-1
ai+1
i
i
ai+2 i+1
n-1 an n
n
n+1
n-2 an n-1
n-1
n
删除前
删除后
21
图2.3 顺序表删除操作前后变化
int delete(sqlist *L,int i) { int j;
16
数组下标 内存 元素序号 数组下标 内存 元素序号
0
a1 1
1
a2 2
0
a1 1
1
a2 2
i-1 ai i
i
ai+1 i+1
n-1 an n
n
n+1
i-1 x i
i
ai i+1
ai+1
n-1 an-1 n
n
an n+1
插入前
插入后
图2.2顺序表插入操作
17
int insert (sqlist *L,int i,ElemType x) { int j;
14
(4)元素定位操作
int locate(sqlist L, ElemType x) {/*从线性表中查找具有给定值x的第一个元素 若找到,则返回其在L中的位序,否则返回0。*/
int i=0; /*从前向后扫描顺序表,没找到i值加1*/
while( i<L.length && L.data[i]!=x) i++; if(i==L.length)/*没找到返回0*/
/*检查位置的合法性*/ if(i<1 || i>L->length)
return 0; /*将表的第i个元素后面的所有元素均向前移动一 个位置*/ for(j=i;j<=L->len-1;j++)
L->data[j-1]=L->data[j]; /*表长减1*/ L->length--; return 1; }
改变为 (a1, …, ai-1, x, ai, …, an)
并且表的长度增加1 算法思想: 1)检查i值是否超出所允许的范围(1≤i≤n+1),若 超出,则进行“超出范围”错误处理; 2)存储空间不足,增加存储空间 3)将线性表的第i个元素和它后面的所有元素均向 后移动一个位置; 4)将新元素x写入到空出的第i个位置上; 5)使线性表的长度增1。
/*判断位置合法性*/ if (i<1||i>L->length+1) return 0; /*存储空间不足,增加存储空间*/ if(L->length= =L->listsize) {
L->data =(ElemType *)realloc(L->data, (L-> listsize+1) *sizeof(ElemType)); if(!L->data) {printf(“OVERFLOWER!\n”); return 0;} L->listsize++; } /*将序号i的结点及之后的结点后移一位*/ for(j=L->length-1;j >= i-1;j--) L->data[j+1]=L->data[j]; /*在序号i处放入x*/ L->data[i-1]=x; /*表长加1*/ L->length++; return 1; }
7
说明: 1 上面列出的操作,只是线性表的一些常用的基本操 作; 2 不同的应用,基本操作可能是不同的; 3 线性表的复杂操作可通过基本操作实现;
8
§2.2顺序表 -----线性表的顺序存储结构
2.2.1顺序表的定义 1.定义:用一组地址连续的存储单元将逻辑上相邻的 元素存放在物理地址也相邻的存储单元。
2.元素地址计算方法:
LOC(ai+1)=LOC(ai)+k (2≤i≤n) LOC(ai)=LOC(a1)+(i-1)*k (1≤i≤n) 其中:
k— 一个元素占用的存储单元个数 LOC(ai)—顺序表第i个元素的地址 LOC(a1)—顺序表的基址
…
…
Loc(a1) Loc(a1)+k
Loc(a1)+(i-1)k
L =(a1, a2, … ai-1,ai, ai+1 ,…, an)
线性起点
下标i,是元素ai 的序号 ,表示ai
在表中的位置
数据元素
ai的直接前趋 ai的直接后继 线性终点
n=0时称为 空表
n为元素总个
数,即表长
5
说明: 1、数据元素可以是一个数,一个符号或一个记录等,但 同一线性表中的元素必须属于同一种数据对象。
例1、一年的月份号(1,2,3,4,5,…,12) 例2、英文字母表(a, b, c, , ,z ) 例3、某单位的电话号码簿
姓名
电话号码
蔡颖
63214444
陈红
63217777
刘建平 63216666
王小林 63218888
张力
63215555
2、线性表的..结. 构是通过数据元素之间的相邻关系来体现的。
return 0; else return i+1;/*找到返回位序*/
算法} 性能分析:
时间性能 查找成功:平均时间复杂度 T(n)= 查找失败: T(n)=n=O(n)
n
pi*ti=
i=1
_1_ n
n i=1
i= n_+2_1
=O(n)
空间性能 O(1)
15
(5)插入操作 在线性表中指定位置i前插入一个元素x,成功返回1,失 败返回0。 插入元素时,线性表的逻辑结构由 (a1, …, ai-1, ai, …, an)
3
2.5 队列 2.5.1队列的定义及其基本操作 2.5.2顺序队列的表示和实现
*2.5.3链队列的表示和实现
2.6 串 2.6.1串的定义及其基本操作 2.6.2顺序串的表示和实现
*2.6.3链串的表示和实现 *2.6.4串的模式匹配
4
§2.1 线性表的定义及基本操作
2.1.1线性表的基本概念 定义:线性表是n(n≥0)个数据元素的有限序列,可记作:
除最后一个外,集合中每个元素均只有一个后继
2
第二章 线性表
2.1 线性表定义及基本操作 2.2 线性表的顺序存储 2.3 线性表的链式存储
2.3.1 单链表 2.3.2 双向链表 2.3.3 循环链表 2.4 栈 2.4.1栈的定义及其基本操作 2.4.2顺序栈的表示和实现 * 2.4.3链栈的表示和实现
11
2.2.2基本操作在顺序表上的实现
(1)初始化操作:构造一个空的顺序表L
void initlist (sqlist *L) { /* 构造一个空的顺序表L*/
L->data = (ElemType *)malloc(INITSIZE *sizeof(ElemType)); if (!L->data) {printf(“OVERFLOW! \n ”); exit(1); /* 存储分配失败*/ } L->length = 0; /* 长度为0*/ L->listsize =INITSIZE; /* 初始存储容量*/ }
10
顺序表的类型定义 :
typedef int ElemType; /*在实际问题中,根据需要定义所需的数据类型*/
#define INITSIZE 100 /*顺序表存储空间的初始分配量*/
typedef struct
{ ElemType *data; /*存储空间基地址*/
int length;
算法性能分析:时间性能 O(1) 空间性能 O(1)
12
(2)求表长操作 统计顺序表L数据元素的个数 int getlen(sqlist L) {/*统计顺序表L数据元素的个数*/
return(L.length); }
算法性能分析:时间性能 O(1) 空间性能 O(1)
13
(3)取元素操作 取出顺序表L的第i个数据元素的值,将值通过 参数e带回,成功返回1,失败返回0. 注意i的合法取值范围: 1≤ i ≤ length
逻辑结构唯一 存储结构不唯一
运算的实现依赖 于存储结构
第2章 线性表
栈和队列
线性结构
串
(逻辑、存储
第3章 数组和广义表
和运算)
线性结构特点:在数据元素的非空有限集
(a1,a2, …,an)中
存在唯一的一个被称作“第一个”的数据元素
存在唯一的一个被称作“最后一个”的数据元素
除第一个外,集合中每个数据元素均只有一个前驱
2
T n On
19
(6)删除操作 在顺序表中删除第i个元素: 顺序表的逻辑结构由(a1, …, ai-1, ai, ai+1, …, an) 改变为 (a1, …, ai-1, ai+1, …, an)
算法思想 1)检查i值是否超出所允许的范围(1≤i≤n),若 超出,则进行“超出范围”错误处理; 2)将表的第i个元素后面的所有元素均向前移动一 个位置; 3)使表的长度减1。
由于上述关系是线性的-------------线性结构。
6
2.1.2线性表的基本操作
(1) 初始化操作 initlist(L) 建立一个空表。 (2) 求表长操作 getlen(L) 返回线性表L的长度。 (3) 元素定位操作locate(L,x)
返回元素x在线性表L中第一次出现的位置,存在,返 回其位序,否则,返回-1 (4) 取元素操作 getelem(L, i) 返回线性表L的第i个元素的值。 (5) 插入操作 insert(L,x,i) 在线性表L 的第i个位置上插入一个值为x的元素。 i的合法取值范围是:1≤i≤n+1 (6) 删除操作 delete(L,i) 删除线性表L的第i个元素,i的合法到值范围是: 1≤i≤n+1 (7) 输出操作 print(L) 按先后顺序输出线性表L的所有元素值。
算法时间性能分析
时间主要花费在元素前移上
设Pi是删除第i个元素的概率,则在长度为n的线性表 中删除一个元素所需移动的元素的平均次数为:
n
Ede Pi (n i) i 1
若认为p 1 等概率
i
n
则E de
1 n
n
(n
i 1
i)
n 1 2
Tn On
故在顺序表中插入或删除一个元素时,平均移
/*顺序表当前长度,即已存入的元素个数*/
int listsize;
/*当前存储空间容量*/
}sqlist;
动态申请和释放内存 ElemType *data = (ElemType *)malloc(INITSIZE*sizeof(ElemType)); free(data);
元素存放在data[0]到data[length-1]中。
算法思想:设表L是一个空表,为使L也是非递减有序 排列,可设两个指针i,j分别指向表L1和L2中的元素, 从两个顺序表的第1个元素开始进行比较: 若L1.data[i]≤L2.data[j],将L1.data[i]插入到L表尾 若L1.data[i]>L2.data[j],将L2.data[j]插入到L表尾 如此进行下去,直到其中一个表被扫描完毕,然后再 将未扫描完的表中剩余的所有元素放到表L中。
18
顺序表插入操作时间性能分析:
插入操作的时间主要花费在元素后移上
设Pi是在第i个元素之前插入一个元素的概率,则在 长度为n的线性表中插入一个元素时,所需移动的 元素的平均次数为:
n1
Eins
P(n i
i
1)
i 1
若认为P 1 i n 1
则Eins
1
n1
n
(n i 1)
n 1 i1
Loc(a1)+(n-1)k
…
…
内存 空间
a1 a2
ai
an
…
……
逻辑 地址
1 2
i
n 空闲
Hale Waihona Puke Baidu
9
图2.1 顺序表
特点: 实现逻辑上相邻—物理地址相邻 实现随机存取
实现:可用C语言的一维数组实现, 这里采用动态分配的一维数组,在初始化时先
用函数malloc()为顺序表分配一个基本容量, 在操作过程中,若顺序表的空间不足,再用函数 realloc()增加空间。
动表的一半元素,当n很大时,效率很低
23
(7)输出操作 void print(sqlist L) { int i; for(i=0; i<L->length;i++) printf(“%4d ”,L->data[i]); printf(“\n”); }
24
例 有两个顺序表L1和L2,其元素均为非递减有 序排列, 编写算法,将其合并成一个顺序表L, 要 求L也是非递减有序排列。 例如L1=(2, 2, 3), L2=(1, 3, 3, 4), 则L=(1, 2, 2, 3, 3, 3, 4)。
int getelem(sqlist L,int i, ElemType *e) {/*取出顺序表L的第i个数据元素的值*/
if (i>=1 && i<=L.length) {*e = L.data[i-1]; return 1;}
else return 0;
} 算法性能分析:时间性能 O(1) 空间性能 O(1)
20
数组下标 内存 元素序号 数组下标 内存 元素序号
0
a1
1
1
a2 2
0
a1
1
1
a2
2
i-1 ai i
i
ai+1 i+1
i-1
ai+1
i
i
ai+2 i+1
n-1 an n
n
n+1
n-2 an n-1
n-1
n
删除前
删除后
21
图2.3 顺序表删除操作前后变化
int delete(sqlist *L,int i) { int j;
16
数组下标 内存 元素序号 数组下标 内存 元素序号
0
a1 1
1
a2 2
0
a1 1
1
a2 2
i-1 ai i
i
ai+1 i+1
n-1 an n
n
n+1
i-1 x i
i
ai i+1
ai+1
n-1 an-1 n
n
an n+1
插入前
插入后
图2.2顺序表插入操作
17
int insert (sqlist *L,int i,ElemType x) { int j;
14
(4)元素定位操作
int locate(sqlist L, ElemType x) {/*从线性表中查找具有给定值x的第一个元素 若找到,则返回其在L中的位序,否则返回0。*/
int i=0; /*从前向后扫描顺序表,没找到i值加1*/
while( i<L.length && L.data[i]!=x) i++; if(i==L.length)/*没找到返回0*/
/*检查位置的合法性*/ if(i<1 || i>L->length)
return 0; /*将表的第i个元素后面的所有元素均向前移动一 个位置*/ for(j=i;j<=L->len-1;j++)
L->data[j-1]=L->data[j]; /*表长减1*/ L->length--; return 1; }
改变为 (a1, …, ai-1, x, ai, …, an)
并且表的长度增加1 算法思想: 1)检查i值是否超出所允许的范围(1≤i≤n+1),若 超出,则进行“超出范围”错误处理; 2)存储空间不足,增加存储空间 3)将线性表的第i个元素和它后面的所有元素均向 后移动一个位置; 4)将新元素x写入到空出的第i个位置上; 5)使线性表的长度增1。
/*判断位置合法性*/ if (i<1||i>L->length+1) return 0; /*存储空间不足,增加存储空间*/ if(L->length= =L->listsize) {
L->data =(ElemType *)realloc(L->data, (L-> listsize+1) *sizeof(ElemType)); if(!L->data) {printf(“OVERFLOWER!\n”); return 0;} L->listsize++; } /*将序号i的结点及之后的结点后移一位*/ for(j=L->length-1;j >= i-1;j--) L->data[j+1]=L->data[j]; /*在序号i处放入x*/ L->data[i-1]=x; /*表长加1*/ L->length++; return 1; }
7
说明: 1 上面列出的操作,只是线性表的一些常用的基本操 作; 2 不同的应用,基本操作可能是不同的; 3 线性表的复杂操作可通过基本操作实现;
8
§2.2顺序表 -----线性表的顺序存储结构
2.2.1顺序表的定义 1.定义:用一组地址连续的存储单元将逻辑上相邻的 元素存放在物理地址也相邻的存储单元。
2.元素地址计算方法:
LOC(ai+1)=LOC(ai)+k (2≤i≤n) LOC(ai)=LOC(a1)+(i-1)*k (1≤i≤n) 其中:
k— 一个元素占用的存储单元个数 LOC(ai)—顺序表第i个元素的地址 LOC(a1)—顺序表的基址
…
…
Loc(a1) Loc(a1)+k
Loc(a1)+(i-1)k
L =(a1, a2, … ai-1,ai, ai+1 ,…, an)
线性起点
下标i,是元素ai 的序号 ,表示ai
在表中的位置
数据元素
ai的直接前趋 ai的直接后继 线性终点
n=0时称为 空表
n为元素总个
数,即表长
5
说明: 1、数据元素可以是一个数,一个符号或一个记录等,但 同一线性表中的元素必须属于同一种数据对象。
例1、一年的月份号(1,2,3,4,5,…,12) 例2、英文字母表(a, b, c, , ,z ) 例3、某单位的电话号码簿
姓名
电话号码
蔡颖
63214444
陈红
63217777
刘建平 63216666
王小林 63218888
张力
63215555
2、线性表的..结. 构是通过数据元素之间的相邻关系来体现的。
return 0; else return i+1;/*找到返回位序*/
算法} 性能分析:
时间性能 查找成功:平均时间复杂度 T(n)= 查找失败: T(n)=n=O(n)
n
pi*ti=
i=1
_1_ n
n i=1
i= n_+2_1
=O(n)
空间性能 O(1)
15
(5)插入操作 在线性表中指定位置i前插入一个元素x,成功返回1,失 败返回0。 插入元素时,线性表的逻辑结构由 (a1, …, ai-1, ai, …, an)
3
2.5 队列 2.5.1队列的定义及其基本操作 2.5.2顺序队列的表示和实现
*2.5.3链队列的表示和实现
2.6 串 2.6.1串的定义及其基本操作 2.6.2顺序串的表示和实现
*2.6.3链串的表示和实现 *2.6.4串的模式匹配
4
§2.1 线性表的定义及基本操作
2.1.1线性表的基本概念 定义:线性表是n(n≥0)个数据元素的有限序列,可记作:
除最后一个外,集合中每个元素均只有一个后继
2
第二章 线性表
2.1 线性表定义及基本操作 2.2 线性表的顺序存储 2.3 线性表的链式存储
2.3.1 单链表 2.3.2 双向链表 2.3.3 循环链表 2.4 栈 2.4.1栈的定义及其基本操作 2.4.2顺序栈的表示和实现 * 2.4.3链栈的表示和实现
11
2.2.2基本操作在顺序表上的实现
(1)初始化操作:构造一个空的顺序表L
void initlist (sqlist *L) { /* 构造一个空的顺序表L*/
L->data = (ElemType *)malloc(INITSIZE *sizeof(ElemType)); if (!L->data) {printf(“OVERFLOW! \n ”); exit(1); /* 存储分配失败*/ } L->length = 0; /* 长度为0*/ L->listsize =INITSIZE; /* 初始存储容量*/ }
10
顺序表的类型定义 :
typedef int ElemType; /*在实际问题中,根据需要定义所需的数据类型*/
#define INITSIZE 100 /*顺序表存储空间的初始分配量*/
typedef struct
{ ElemType *data; /*存储空间基地址*/
int length;
算法性能分析:时间性能 O(1) 空间性能 O(1)
12
(2)求表长操作 统计顺序表L数据元素的个数 int getlen(sqlist L) {/*统计顺序表L数据元素的个数*/
return(L.length); }
算法性能分析:时间性能 O(1) 空间性能 O(1)
13
(3)取元素操作 取出顺序表L的第i个数据元素的值,将值通过 参数e带回,成功返回1,失败返回0. 注意i的合法取值范围: 1≤ i ≤ length
逻辑结构唯一 存储结构不唯一
运算的实现依赖 于存储结构
第2章 线性表
栈和队列
线性结构
串
(逻辑、存储
第3章 数组和广义表
和运算)
线性结构特点:在数据元素的非空有限集
(a1,a2, …,an)中
存在唯一的一个被称作“第一个”的数据元素
存在唯一的一个被称作“最后一个”的数据元素
除第一个外,集合中每个数据元素均只有一个前驱
2
T n On
19
(6)删除操作 在顺序表中删除第i个元素: 顺序表的逻辑结构由(a1, …, ai-1, ai, ai+1, …, an) 改变为 (a1, …, ai-1, ai+1, …, an)
算法思想 1)检查i值是否超出所允许的范围(1≤i≤n),若 超出,则进行“超出范围”错误处理; 2)将表的第i个元素后面的所有元素均向前移动一 个位置; 3)使表的长度减1。
由于上述关系是线性的-------------线性结构。
6
2.1.2线性表的基本操作
(1) 初始化操作 initlist(L) 建立一个空表。 (2) 求表长操作 getlen(L) 返回线性表L的长度。 (3) 元素定位操作locate(L,x)
返回元素x在线性表L中第一次出现的位置,存在,返 回其位序,否则,返回-1 (4) 取元素操作 getelem(L, i) 返回线性表L的第i个元素的值。 (5) 插入操作 insert(L,x,i) 在线性表L 的第i个位置上插入一个值为x的元素。 i的合法取值范围是:1≤i≤n+1 (6) 删除操作 delete(L,i) 删除线性表L的第i个元素,i的合法到值范围是: 1≤i≤n+1 (7) 输出操作 print(L) 按先后顺序输出线性表L的所有元素值。