9232674

当前课程知识点:数据结构 >  第0章 预备知识 >  0.4 数组、指向函数的指针 >  0.4 数组、指向函数的指针

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

0.4 数组、指向函数的指针在线视频

下一节:第0章 预备知识讨论题

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

0.4 数组、指向函数的指针课程教案、知识点、字幕

同学们,大家好

我是云南大学信息学院的教师孔兵

这节我们讨论一下指针和数组

在c语言中因为数组实现的方式

数组和指针有很强的关联

数组名是数组的起始地址

这是一个常数,作为地址

我们可以把它看作是一个指针

示例中首先声明了一个包含5个整型数的数组a

a是数组名,是分配给数组空间的起始地址

声明了一个指向整型的指针p

下面看一下对数组的扫描操作

第1个循环当中,用的是大家比较熟悉的方式

也就是通过数组下标来扫描整个数组

并把数组的内容显示出来

第2个循环中

是通过指针来扫描数组的

首先,p被赋值a

也就是说让p指向数组的起始地址

当p小于a+5的时候进行循环

p是一个整型指针

*p就确定了从起始地址开始的4字节的空间

也就是数组中0号下标单元的这个整数

和a[0]的效果是一样的

随后做p++

这里要提醒大家指针的加和一般数值的加是不一样的

指针的加是带类型的

比如这里,如果p原来是100的话

因为p是整型指针

p+1应该增加一个整型空间的长度

它加了以后呢,应该是104

指向数组中1号下标单元的起始地址

这样通过声明来获得数组存储空间的方法

是静态的方法,在后续课程中

用的更多的是动态的方法

也就是通过malloc申请数组的存储空间

动态申请是在程序执行的过程当中

通过malloc动态申请分配数组存储空间

先看一下定义

首先,定义两个常量

一个是数组初始的大小LIST_INIT_SIZE

这里它定义为20,也就是说

数组初始的时候可以存20个数据

因为数组空间是动态申请的

也给了我们一个优势

就是在数组使用的过程当中

当发现空间不够使用的时候

可以通过重新申请realloc这个函数来获得一个更大的空间

第二个常量就是一个增量

数组初始大小是可以存20个元素

不够了,可以再申请空间

就是在原来空间的基础上增加一个增量的空间

20个不够增加10,获得一个30的空间

如果30不够,那么再增加10,依次类推

用这样的方法,数组的空间是可以变化的

数组被定义成了一个结构体

它包含三个成员

一个是指向整型的指针

因为示例当中我们要存的数据是整数

这个指针会指向申请空间的起始地址

操作中会把它作为一个数组名来使用

另外一个成员listsize是申请的数组空间的容量

也就是数组能存数据的个数

length是当前长度

就是说目前数组中具体存了多少个数据

length小于等于listsize

当等于的时候,说明数组已经存满

再插入新数据的时候就要重新申请空间

用typedef给这个结构体类型取个类型名叫sqlist

后面的数组就是sq list这样类型的

首先声明了一个sqlist结构体的变量L

这就是数组

这个数组本身并没有存储数据的空间

它用来存储数据的空间需要动态申请获得

我们仍然用malloc申请空间

现在要存的数据是整数

用sizeof求其字节数

要存的数据个数LIST_INIT_SIZE

这是数组初始的容量

乘上每个数据需要的字节数

得到整个数组需要空间的大小

malloc返回申请空间的起始地址以后

把它强制类型转换为一个指向整型的指针

赋值给L.elem这个指针

如图所示,这个时候呢

L.elem指向申请空间的起始

那么它是一个指针,就是一个地址

后面就把它看作是一个数组名来使用

目前数组当中没有存储元素

L.length等于0,L.Listsize等于它初始的容量

到这里,我们完成了数组的初始化

为数组准备好了存储空间,这个数组可以使用了

在这样的动态数组当中

数组元素的存取也有两种方式

第1种方式,把指针看做数组名

那么同样用中括号加下标

我们可以存取数组中的某一个元素

例子中是把下标9这个单元的内容赋值给e

第2种方式,可以通过指针来存取数组中的元素

q被赋值L.elem+9

目的是让q指向数组中下标9这个单元的起始地址

用*q把这个单元的内容赋值给e

随后q++,让q指向数组的下一个下标单元

作为动态申请的数组

当不需要这个数组的时候

可以把它的存储空间释放

这时就要用到Free这个函数

free的参数是指向这块待释放空间起始地址的指针

动态申请的空间可以释放

不过只能以成块的方式释放

也就是说申请的时候申请的是这一块

这一块只能一起释放

不能单独释放这块中的某个单元

前面提到动态申请数组空间的另一个优势可以再申请

当使用过程中发现空间不够用的时候

可以通过realloc申请一块更大的空间

realloc包含两个参数

第1个参数是指明原来空间的起始地址

第2个参数和malloc的一样

指明要申请空间的大小

这里空间的大小是通过在原来空间容量的基础上增加一个增量

然后乘以每个数据需要的存储空间大小来给出的

realloc这个函数另外有两个作用

一是把原来空间中的数据拷贝到新空间

二是把原来空间释放

realloc的返回值是新空间的起始地址

新的地址赋值给数组指针L.elem

完成新空间的申请

这个时候,整个数组空间的容量增加了

L.listsize需要重新更新

新空间的容量是在原来容量的基础上增加了一个增量

好了,同学们

我们现在已经讲解完数组和指针

下面我们将讲解指向函数的指针

指针的最后一个问题是指向函数的指针

例子中我们通过int括号*p

括号定义了一个指向函数的指针p

这里p是一个指向函数的指针

int表示这个函数指针是指向返回值为int的函数

如果函数fun是一个返回值为整型的函数

那么我们可以把这个函数名赋值给这个指向函数的指针

让p指向这个函数fun

然后就可以通过p调用函数fun

调用的方式是括号,*p括号

加上相应的参数

这样的调用方式和用函数名直接调用是等价的

当然例子中这样的做法基本上没有什么意义

一般我们是把指向函数的指针定义为函数的形式参数

它是后面章节中二叉树先序遍历的函数

目的是用先序的方式

访问二叉树每个节点一次而且仅一次

它的第1个形式参数指明

要遍历的二叉树T

第2个参数定义了一个指向函数的指针visit

从定义看visit指向返回值为status的函数

当我们要调用该函数的时候

需要把一个函数名作为实参传递给visit这个形参

在函数体中

有通过函数指针调用函数的语句(*visit)

就是说,调用visit所指的函数来处理数据a

从这里可以看出,如果作为实参的函数名不同

函数体中通过visit调用的函数也就不同

比如说有两个返回值类型为status的函数

Printelementher和 addelement

调用Preorder的时候

如果把printelement作为实参传递给visit

那么函数体中用 visit访问函数的时候

访问的函数就是printelement

如果把Addelement作为实参传递给visit

那么函数体中用 visit访问函数的时候

访问的函数就是Addelement

这样组织程序的方式有利于获得良好的程序结构

就是说如果遍历的过程不变

但是,在遍历的过程中

我们对数据的处理方式不一样的话

可以把遍历函数的形式参数定义为指向函数的指针

不同的处理方法用不同的函数实现

当这次遍历要使用某种处理方法的时候

只需要在调用时把对应的函数名

作为实参传递给作为形参的函数指针就可以了

好了,同学们

我们今天的课程就到这里,下节课再见

数据结构课程列表:

前言

-1.算法概念导入

--1.1 算法概念导入

-2.数据结构课程介绍

--2.数据结构课程介绍

-数据结构前言PPT

第0章 预备知识

-0.1变量、类型和表达式

--0.1变量、类型和表达式

-0.2 函数

--0.2 函数

-0.3 指针和单链表

--0.3 指针和单链表

-0.4 数组、指向函数的指针

--0.4 数组、指向函数的指针

-第0章 预备知识讨论题

-数据结构第0章预备知识PPT

第1章 绪论

-1.1什么是数据结构

--1.1什么是数据结构

--测试题

-1.2基本概念和术语

--1.2基本概念和术语

--测试题

-1.3数据结构的描述

--1.3数据结构的描述

--测试题

-1.4抽象数据类型的定义和实现

--1.4抽象数据类型的定义和实现

--测试题

-1.5算法和算法分析概念

--1.5算法和算法分析概念

--测试题

-1.6算法分析示例

--1.6算法分析示例

--测试题

-第1章 绪论讨论题

-数据结构第1章 绪论PPT

第2章 线性表

-2.1 线性表的类型定义

--2.1线性表的类型定义

--测试题

-2.2线性表的顺序表示和实现

--2.2 线性表的顺序表示和实现

--测试题

-2.3 线性链表

--2.3 线性链表

--测试题

-2.4 静态链表

--2.4 静态链表

--测试题

-2.5 循环链表和双向链表

--2.5 循环链表和双向链表

--测试题

-第2章 线性表讨论题

-数据结构第2章线性表PPT

第3章 栈和队列

-3.1 栈

--3.1栈

--测试题

-3.2 栈的实现

--3.2 栈的实现

--测试题

-3.3 栈的应用

--3.3 栈的应用

-3.4 栈与递归的实现

--3.4栈与递归的实现

--测试题

-3.5 队列和链队列

--3.5 队列和链队列

--测试题

-3.6 循环队列

--3.6 循环队列

--测试题

-第3章 栈和队列讨论题

-数据结构第3章栈和队列PPT

第4章 串

-4.1 串

--4.1 串

--测试题

-数据结构第4章 串PPT

第5章 数组

-5.1 数组定义和表示

--5.1 数组定义和表示

--测试题

-5.2矩阵的压缩存储

--5.2 矩阵的压缩存储

--测试题

-第5章 数组讨论题

-数据结构第5章数组PPT

第6章 树和二叉树

-6.1 树的定义和基本术语

--6.1 树的定义和基本术语

-6.2 二叉树和二叉树的性质

--6.2 二叉树和二叉树的性质

--测试题

-6.3 二叉树的存储结构

--6.3二叉树的存储结构

--测试题

-6.4 遍历二叉树

--6.4 遍历二叉树(1)

--6.4 遍历二叉树(2)

--测试题

-6.5 线索二叉树

--6.5 线索二叉树

--测试题

-6.6 树的存储

--6.6树的存储

-6.7 树的转换和遍历

--6.7 树的转换和遍历

--测试题

-6.8 赫夫曼树

--6.8 赫夫曼树

-6.9 赫夫曼编码

--6.9 赫夫曼编码

--测试题

-第6章 树和二叉树讨论题

-数据结构第6章树和二叉树PPT

第7章 图

-7.1 图的定义和术语

--7.1.1图的定义和术语(1)

--7.1.2图的定义和术语(2)

--测试题

-7.2 图的存储结构

--7.2.1 数组表示法(1)

--7.2.2 数组表示法(2)

--7.2.3 邻接表

--测试题

-7.3 图的遍历

--7.3.1 深度优先搜索

--7.3.2 广度优先搜索

--测试题

-7.4 最小生成树

--7.4.1 普里姆算法

--7.4.2 克鲁斯卡尔算法

--测试题

-7.5 有向无环图

--7.5.1 拓扑排序

--7.5.2 关键路径

--测试题

-7.6 最短路径

--7.6.1 单源最短路径-迪杰斯特拉算法

--7.6.2 每一对顶点之间的最短路径-弗洛伊德算法

--测试题

-第7章 图讨论题

-数据结构第7章图PPT

第8章 查找

-8.1 查找基本概念和顺序查找

--8.1 查找基本概念及顺序查找

--测试题

-8.2 有序表的查找

--8.2 有序表的查找

--测试题

-8.3 二叉排序树

--8.3.1 二叉排序树(1)

--8.3.2 二叉排序树(2)

--测试题

-8.4 平衡二叉树

--8.4 平衡二叉树

--测试题

-8.5 哈希表

--8.5.1 哈希表及哈希函数的构造

--8.5.2 解决冲突的方法

--8.5.3 哈希表的查找和性能分析

--测试题

-第8章 查找讨论题

-数据结构第8章查找PPT

第9章 内部排序

-9.1插入排序

--9.1.1 插入排序(1)

--9.1.2 插入排序(2)

--测试题

-9.2 希尔排序

--9.2 希尔排序

--测试题

-9.3 快速排序

--9.3 快速排序

--测试题

-9.4 选择排序

--9.4 选择排序

--测试题

-9.5 堆排序

--9.5 堆排序

--测试题

-9.6 归并排序

--9.6 归并排序

--测试题

-9.7 基数排序

--9.7 基数排序

--测试题

-9.8 排序方法总结

--9.8 排序方法总结

-第9章 内部排序讨论题

-数据结构第9章内部排序PPT

0.4 数组、指向函数的指针笔记与讨论

也许你还感兴趣的课程:

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