当前课程知识点:数据结构 >  第2章 线性表 >  2.2 线性表的顺序实现——顺序表 >  讲解(上)

返回《数据结构》慕课在线视频课程列表

讲解(上)在线视频

下一节:讲解(中)

返回《数据结构》慕课在线视频列表

讲解(上)课程教案、知识点、字幕

刚才,我们讲了线性表的逻辑结构

现在,我们再来看线性表的物理结构

第一种物理结构——以顺序方式实现的线性表

称为顺序表

在这里有一个图,画出了以顺序方式存储的线性表

在内存当中的结构

n个元素

大家看到,占据着连续的存储单元

这时候,就称为顺序表

如果我们要找ai这个元素

它的地址,也就是Location(ai),它的地址

应该等于它的前驱地址

加上每个元素所占的字节数

在左边的图当中

我们并没有清晰地画出,每个元素到底占多少个字节

因为,这个d取决于你要表达的应用

每个元素的类型不同

它占的字节数可能不同

如果继续向前推

可以用a1的地址来表示

ai的地址

因为,ai这个元素和a1这个元素

它们之间相隔了

i-1个元素

所以,ai的地址就是a1的地址

加上i-1乘上d,这个公式

就是著名的随机存取公式

随机存取的本质

就是:在一段连续的存储空间当中

找任何一个元素

它的位置,应该是在单位时间内找到的

因为,找任何一个元素ai的地址

实际上,CPU是做一个加法

一个首地址加上一个偏移量

无论给出来的偏移量是多少

CPU执行这个加法的时间是一样

我个人认为

随机存取的这个随机

翻译地不太确切

Random

我认为翻译成任意,比较合适一点

任意存取

就是:找一段连续的内存当中,任何一个元素

任意一个元素,所耗费的时间是一样的

就是首地址加上一个偏移量

我们在学C语言的时候,曾经学过一个等价的写法

ai这个元素

它的地址,实际上是等价于a+i的

我们知道,C语言的数组名代表着:数组所占连续存储空间的首地址

也就是a

ai这个元素,它的地址就是:首地址

加上一个偏移量

因为,C语言的数组下标从0开始

而刚才描述一个线性表的时候

第一个元素,是a1开始的;第n个元素,下标是n

所以,这里是i-1。在C语言里面,下标是从0开始的

所以,ai和a0这两个元素之间,实际上相隔了i个元素。有的同学可能会奇怪

为什么没有在i后面

再乘上每个元素所占的字节数呢

这是因为,C语言是一门高级语言

高级语言通常不关心

一个占了若干字节的数据

在内存当中的非首字节

比如,一个整型

假设是16位的,它占2个字节

我们在描述这个整型的地址的时候

描述的都是它所占2个字节的

第1个字节的地址

我们不会关心它的第2个字节

如果是汇编这样的语言

可能会关心它的高字节

但是,在高级语言当中,不会关心

除了首字节之外的其他字节

接下来,我们就要开始写代码了

用类C的代码,来描述出顺序表

首先,我们定义了一个宏

名字叫LIST_INIT_SIZE,从宏名可以看出

它代表着顺序表的初始容量

我们把它定义成100

紧接着,我们又定义了一个LIST_INCREMENT,线性表的增量

主要是用于:当线性表的空间不够的时候

要为线性表追加内存

我们一次追加多少呢

我们一次追加10个元素

所占用的字节

紧接着,我们定义了一个类型

我们给int型起了一个别名,叫ElemType,类似于这种代码

后面,我们会遇到很多次

这样做的目的,主要是为了让后面的代码显得更通用

我们定义了一个类型叫元素类型

只不过,为了能够让它是合法的代码

我们必须为一个已存在的类型

比如int,起一个新的名字

ElemType

这里,为了简单起见

我们就认为,线性表当中的元素都是整型

紧接着,我们定义了一个结构体

这个结构体是没有名字的

struct关键字

后面没有名字

它有3个成员

第1个成员,是指向ElemType类型的指针

大家注意到

elem这个成员

它是一个指针

elem的类型

我们刚才已经定义过了

elem代表的就是:连续存储空间的首地址

有了首地址

我们还必须告诉编译器

这一段连续的存储空间有多长

所以,有第3个成员,叫size,它代表的是线性表的容量

注意

容量跟长度是有区别的

容量是表示线性表能够存放的最多的元素个数

我们为线性表

假设分配了这么多的容量

那在某一个时刻,这一段内存当中

哪些位置才是属于线性表的呢

尽管在图上,我们可以用白色和灰色背景来标识

有些元素

比如灰色的,是不属于线性表的

但是,在内存当中

在任何时刻,内存都是有值的

你怎么知道一个线性表当中

从首地址开始

到哪个地方,才是属于线性表的元素呢

于是,我们还需要第2个成员length,来标识

线性表到底有多少个元素,也就是表长

然后,我们用typedef

给这样一个无名的结构体起了一个别名

叫SqList

这里的Sq

就是Sequential的意思

顺序表

我们来看几个表达式

第一个表达式,SqList L

我们声明了一个SqList类型的变量L

大家注意到,这里的L,已经是结构体类型了

千万不要在SqList的左边

再加上struct关键字

因为,刚才我们用typedef定义别名的时候

实际上就是给一个结构体定义的别名

L这个结构体,它的elem成员表示

连续存储空间的首地址

elem[0],大家看到,我们这里把首地址当作一个数组名来用

这是C语言的特性之一

其实数组名就是一个地址

你定义的指针elem,实际上也可以当做数组名来用

既然下标是0

说明取的就是第1个元素

也就是a1

L.length,代表的是表长

也就是线性表

有多少个元素

L.elem[L.length - 1],表长减1

肯定是最后一个元素

an的下标

这个表达式,代表的是an这个元素

L.size,代表的是线性表的容量

再次强调

这个size,表示的是:线性表能够存放的最多的元素个数

现在,我们来看第一个算法实现:初始化

在内存当中

我们要为L分配内存

然后,给L的各个成员赋以合适的初值

因为,L从无到有

所以,前面加了引用参数

我们现在使用C语言的malloc库函数

这个malloc

m代表的是memory

后面是allocate

内存分配函数

这是C语言的一个动态内存

分配API。它的参数是你想分配多少字节的内存

注意,这个单位是字节

我们刚才定义了一个宏,叫做

LIST_INIT_SIZE,就是第一次创建线性表的时候

我们定义的是100,我们为线性表分配100个元素所占的内存

那每一个元素占多少字节呢

我们用sizeof这个运算符取出来,sizeof的参数

元素类型——刚才定义的ElemType,线性表的容量乘以每个元素占的字节数

最后,我们再强制转换一下。这个强制转换,代表malloc分配的连续的存储空间

将来只能存放ElemType类型的数据,不能存放别的类型数据

malloc的返回值——如果成功,是你分配的这一段连续存储空间

它的首地址

也就是第一个元素所占的地址

我们将这个地址赋给L的elem成员

因为,elem成员代表的就是连续存储空间的首地址

当然

为了算法的健壮性

有可能指定的容量太大了

那么,malloc失败,也就是:没有足够的内存分配给你的线性表

这时候,malloc返回的实际上是0

也就是NULL

需要注意

C语言中,大写的NULL,并不是一个关键字

而是一个宏

如果大家打开

stdio这个头文件

你会发现,这个宏,它的值实际上是0

而C语言用0表示假,那么,非0就是真

那 !L.elem,就等价于L.elem==0,或者说==NULL,等于空

也就是,malloc返回0

我们要执行这个if语句

这时候,内存不够

我们直接就退出,exit是结束程序运行,参数是退出状态码,这个状态码

一般不会用到

正常情况下

这个if是不会成立的

也就是成功

分配了内存

这时候,我们将length定成0,表示是一个空表

然后将size

修改成LIST_INIT_SIZE

因为,初始大小就是LIST_INIT_SIZE

数据结构课程列表:

第0章 课程简介

-讲解

-作业

-讨论1

-讨论2

第1章 绪论

-1.1 数据结构是什么

--讲解

--作业

-1.2 概念和术语

--讲解

--作业1

--作业2

-1.3 抽象数据类型

--讲解(上)

--讲解(下)

--作业

-1.4 算法及其设计要求

--讲解

--作业

-1.5 算法分析与度量

--讲解(上)

--讲解(下)

--作业1

--作业2

--讨论

第2章 线性表

-2.1 概念及ADT

--讲解

--作业

-2.2 线性表的顺序实现——顺序表

--讲解(上)

--讲解(中)

--讲解(下)

--作业1

--作业2

-2.3 线性表的链式实现——链表

--讲解(上)

--讲解(中)

--讲解(下)

--作业1

--作业2

-2.4 线性表的应用——多项式

--讲解

--作业

-讨论

第3章 栈和队列

-3.1 栈的定义及ADT

--讲解

--作业

-3.2 栈的顺序实现——顺序栈

--讲解

--作业

-3.3 栈的应用

--讲解

--作业

-3.4 栈与递归

--讲解(上)

--讲解(下)

--作业

-3.5 队列的定义及ADT

--讲解

--作业

-3.6 队列的顺序实现——循环队列

--讲解(上)

--讲解(下)

--作业

-讨论

第4章 数组

-4.1 数组的定义

--讲解

--作业

-4.2 数组的顺序实现

--讲解

--作业1

--作业2

-4.3 特殊矩阵的压缩存储

--讲解

--作业

-4.4 稀疏矩阵的压缩存储

--讲解(上)

--讲解(下)

--作业

-讨论

第5章 树和二叉树

-5.1 概念及术语

--讲解

--作业

-5.2 二叉树及其性质

--讲解

--作业1

--作业2

-5.3 二叉树的存储

--讲解

--作业

-5.4 二叉树的遍历及创建

--讲解(上)

--讲解(下)

--作业

-5.5 线索二叉树

--讲解

--作业

-5.6 树与森林

--讲解

--作业

-5.7 Huffman树

--讲解(上)

--讲解(下)

--作业

-讨论

第6章 图

-6.1 概念和术语

--讲解

--作业

-6.2 存储与实现

--讲解(上)

--讲解(下)

--作业

-6.3 遍历

--讲解(上)

--讲解(下)

--作业

-6.4 最小生成树

--讲解(上)

--讲解(下)

--作业1

--作业2

-6.5 拓扑排序

--讲解

--作业

-6.6 最短路径

--讲解

--作业

-讨论

第7章 查找

-7.1 概念和术语

--讲解

--作业

-7.2 静态查找表

--讲解(上)

--讲解(下)

--作业

-7.3 二叉排序树

--讲解(上)

--讲解(下)

--作业

-7.4 平衡二叉树

--讲解

--作业

-7.5 哈希表

--讲解(上)

--讲解(下)

--作业

-讨论

第8章 排序

-8.1 概念

--讲解

--作业

-8.2 插入排序

--讲解(上)

--讲解(下)

--作业

-8.3 交换排序

--讲解(上)

--讲解(下)

--作业

-8.4 选择排序

--讲解(上)

--讲解(中)

--讲解(下)

--作业

-8.5 归并排序

--讲解

--作业

-讨论

讲解(上)笔记与讨论

也许你还感兴趣的课程:

© 柠檬大学-慕课导航 课程版权归原始院校所有,
本网站仅通过互联网进行慕课课程索引,不提供在线课程学习和视频,请同学们点击报名到课程提供网站进行学习。