数据结构主要可以分为两大模块:
- 线性结构
- 非线性结构
本文主要开始讲线性结构。
什么是线性结构
线性结构,顾名思义,就是这些数据所有节点都能被一根线(指针)联系起来的一种结构。
线性结构的存储方式:
- 连续存储:【数组】
- 离散存储:【链表】
线性结构的常见应用方式:
- 栈
- 队列
专题 :【递归】
数组和链表
本小节学习数组和链表,从底层去了解和实现数组与链表,并分析两者对应的优缺点
数组
数组是最常见的链式存储结构,它是一段连续的内存空间,在内存中我们可以简单表示为下图样式
通过上图我们可以把代码中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)