数据结构主要可以分为两大模块:
- 线性结构
- 非线性结构
本文主要开始讲线性结构。
什么是线性结构
线性结构,顾名思义,就是这些数据所有节点都能被一根线(指针)联系起来的一种结构。
线性结构的存储方式:
- 连续存储:【数组】
- 离散存储:【链表】
线性结构的常见应用方式:
- 栈
- 队列
专题 :【递归】
数组和链表
本小节学习数组和链表,从底层去了解和实现数组与链表,并分析两者对应的优缺点
数组
数组是最常见的链式存储结构,它是一段连续的内存空间,在内存中我们可以简单表示为下图样式
通过上图我们可以把代码中int arr[6] = {1,2,3,4,5,6};
执行的操作从内存中脑补出来,同时我们可以简单分析一下,数组应该有的一些基本使用。如
- 初始化、
- 添加新元素、
- 插入新元素、
- 删除某个元素、
- 判断是否为空数组、
- 是否是满数组、
- 排序
- 倒序
- 查询是否包含某个元素
- ······
本小节就带着你手把手实现一个简单的数组的封装,借此来了解数组的数据结构以及内部的一些基本算法知识。这里就简单的以一个 int 类型的数组来示例,后面学到泛型的时候便可更加好的理解数组的实现。
首先简单分析一下数组中基本的属性,我们有上面的数组内存中的逻辑图可以确定数组有对应的内存空间,有一个内存起始地址,因为系统分配内存的时候长度是一定的,所以数组中有一个表示最大长度的属性,数组中的元素也可能会根据实际个数不定,所以肯定有元素个数的标记,这个标记不仅可以拿来查看数组元素个数,也能确定了元素的下标。通过简单的分析我们可以总结数组中基本的属性如下:
- 【pBase】 数组首字节地址
- 【length】 数组长度(决定分配的内存大小)
- 【count】 数组中有效元素个数
下面就根据上面的分析来实现一个简单的数组,这里只说一下思路,完整代码请在这里下载数组实现代码
- // 定义个数组
- typedef struct Array {
- int length; // 数组长度
- int count; // 数组当前元素数 count
- int *pBase; // 数组的首字节地址
- }* PMyArray,MyArray; //两个别名,PMyArray 类似java中类名,定义的对象不带 * , MyArray类似于OC中的类型,定义的对象带 * 。
-
- // 要实现的一些基本方法
-
- /** 初始化数组*/
- void init_Arr(MyArray *pArr, int len);
- /** 追加数组*/
- bool append_Arr(MyArray *pArr, int value);
- /** 插入数组*/
- bool insert_Arr(MyArray *pArr, int index , int value);
- /** 删除数组*/
- bool delete_Arr(MyArray *pArr, int index , int * pVal);
- /** 是否满载*/
- bool is_full(MyArray *pArr);
- /** 是否为空*/
- bool is_empty(MyArray *pArr);
- /** 排序数组*/
- void sort_Arr(MyArray *pArr);
- /** 展示数组*/
- void show_Arr(MyArray *pArr);
- /** 倒序数组*/
- void inversion_Arr(MyArray *pArr);
-
- /** 获取一个默认初始化的数组*/
- MyArray * get_Arr(void);
-
-
- int main(void) {
-
- MyArray arr; // 声明
- int len = 6; // 定义数组长度
- init_Arr(&arr,len); // 初始化
-
- // 添加元素
- int time = 0;
- while (time < len) {
- append_Arr(&arr, 100 + time);
- time++;
- }
-
- insert_Arr(&arr, 6, 200); // 插入元素
- insert_Arr(&arr, 7, 300);
- insert_Arr(&arr, arr.count, 400)