数据结构
定义
数据结构是计算机中存储, 组织数据的方式 --维基百科
研究内容
- 如何把现实中庞大复杂的信息数据存储到内存中
数据的存储涉及两个方面
- 元素的存储 : 以什么样的数据类型来存储特定数据
- 元素之间关系的存储 : 以什么样的存储结构来存储一些数据
分类
以物理硬件上的存储方式分类
- 连续存储: 数组
- 离散存储: 链表, 树, 图
以逻辑思维上的研究形式分类
- 线性结构 : 数组, 链表
- 栈和队列 是线性结构的两种具体应用
- 非线性结构 : 树, 图
内存
- 内存是用来存储数据的设备, 速度介于寄存器和硬盘之间
- 内存是cpu唯一可以直接访问的大容量存储设备, 所有硬盘中的程序和数据需要先存入内存之后才可以被cpu执行, cpu不能直接处理硬盘中的数据
- 内存的问题是软件开发的核心问题
- 内存是多字节组成的线性一维存储空间
- 内存划分的基本单元是字节 (存储单元), 一个字节是8位
- 字节和编号一一对应 (存储单元和地址一一对应)
- 一个系统所能管理的内存空间大小取决于参与编号的二进制位数 (地址总线的数量)
程序运行与内存的关系
- 程序运行前需要向操作系统申请一块存储空间用来存放程序运行过程中所使用的变量以及相关信息, 在内存空闲空间充足时, 操作系统将为该程序分配一块内存空间, 同时从硬盘中将该程序拷入该内存空间, 运行该程序
- 程序运行期间, 该程序所占用的内存空间不再被分配给其它程序
- 程序运行完毕后, 操作系统将回收该块内存空间的控制权限 (即内存释放), 使得该块空间可以继续被分配给其它程序使用. 但是不会清楚内存空间中存储的内容
- 虽然内存释放后, 通过地址仍然可以访问到该空间中的内容, 但是禁止这样做, 因为这是不安全的. 当操作系统分配空间频繁时, 该块内存可能很快就会被分配给其它程序使用, 里面存储的内容也会被改变.
- 因此变量一般都需要被赋值后再使用, 不然里面存储的很可能就是上个程序遗留的垃圾数据
- 变量定义 实际上就是为该变量分配一块内存空间, 变量赋值, 才是往内存空间中存入内容.
地址和指针
- 地址
- 内存单元的编号
- 从0开始的非负数
- 指针
- 指针就是地址, 地址就是指针
- 指针变量存放的是内存单元地址的变量
- 指针的本质是一个操作受限制的非负整数 (只在特定场景下有±操作, 没有*/)
- 指针的±操作都是根据存储的地址所指向的变量的类型所占的字节数为单位的. 比如int* 指针变量±都是以4个字节为单位.
- 常量和表达式前不能加&
- 非指针变量前不能加*
- 如果想通过被调函数改变主调函数中的值, 必须满足下列条件
- 实参必须是该变量的地址 (如果是指针变量, 明确是想改变指针所指向的内容, 还是指针变量本身所存储的地址)
- 形参必须是指向该变量类型的指针变量
- 被调函数通过*修改主调函数中的变量的值
- c语言中%p以十六进制输出指针
- 数组作为形参传入函数需要两个相关参数
- 第一个参数是数组名(数组首元素的地址)
- 第二个参数是数组的长度
- 指针变量统一占四个字节, 无论存储的是什么数据类型的地址. 因此作为参数传递时, 往往传入指针, 节省空间, 速度提升.
结构体
typedef struct Student {
int id;
char name[200];
int age;
}ST, *PST;
- typedef 将结构体 struct Student赋予了一个别名ST, 将结构体指针struct Student* 赋予了别名PST
- 直接一次性赋值 ST student= {1000, “yyy”, 22};
- 属性赋值ST student; student.age=22;
- PST pSt; pSt->id = 12;
student.name = "yyy"; // error 不能将一个字符串赋值给一个指针变量
strcpy(student.name, “yyy”);
- 使用结构体变量的两种方式
- 变量名.属性
- 指针->属性
- 结构体变量不能进行算数运算, 但是可以相互赋值
- c 和 c++ 中可以直接使用数组名 输出整个字符串, 即%s 接收char* 指针变量.
- 结构体由于一般所占内存较大, 因此通常使用结构体指针作为参数传递.
学习
郝斌老师的数据结构入门