数据结构 第1节 什么是数据结构
数据结构概述
一、数据结构定义
如何把现实中大量而复杂的问题以特定的数据类型和特定的存储结构保存到主存储器(内存)中,以及在此基础上为实现某个功能(比如查找、删除某个元素,对所有元素排序)而执行的相应操作,这个操作也叫算法。
特定的数据类型: 个体元素
特定的存储结构:个体和个体之间的关系
数据结构 = 个体 + 个体之间的关系
算法 = 对存储数据的操作
严蔚敏 / 吴伟民 《数据结构》 伪算法。基本上是从其它地方抄来的,只不过相对抄的还行。
高一凡 将伪算法 实现了
二、算法定义
解题的方法和步骤
三、衡量算法的标准
- 时间复杂度
大概程序要执行的次数,而非执行时间。
因为相同的程序若是在不同的机器上运行,会因为机器的差异得出不同的结果,所以不能用时间来衡量。 - 空间复杂度
算法执行过程中大概占用的最大内存 - 难易程度
- 健壮性
四、数据结构的地位
数据结构是软件中最核心的课程。
1. 什么是堆?什么是栈?
很多人就以为是内存里的2块儿空间,一块儿叫堆,一块儿叫栈。其实不对。
实际上是指分配内存的方法不同的2种方式。如果是压栈出栈的方式分配和释放的内存就叫栈内存。如果是以堆排序分配的内存,就叫堆内存。
注意:数据结构里是没有堆这个概念的,堆是什么❓是分配内存的一种方式,而不是存储数据的一种结构
2. 函数调用,如何调用呢?
压栈和出栈。
- 按时间存储的东西得有个顺序吧,按顺序存储的结构就是队列。
- 编译原理得学树。
- 数据库就是数据结构的简化版,讨论的问题差不多,解决的问题更狭窄了
- 程序 = 数据的存储 ➕ 数据的操作 ➕可以被计算机执行的语言
- 站在数据结构的角度,C,C++,Java都一样,都是皮毛
- 数据结构很重要,难度大,学完很难做出东西来,学它是练内功
五、预备知识
- 指针
- 指针的重要性
指针是C语言的灵魂 - 定义
- 地址
内存单元的编号
从0开始的非负整数
范围:0 - FFFFFFFF【0 ~ 4G-1】 - 指针
指针就是地址,地址就是指针
指针的本质是一个操作受限的非负整数 - 指针变量
指针变量就的存放内存单元地址(编号)的变量 - 指针的分类
- 基本类型的指针
- 地址
#include <stdio.h>
int main(void) {
int * p; //p是个变量名字,int * 表示该P变量只能存储int类型变量的地址
int i = 10;
int j;
//(1)❌此时p还没有被赋值,里面是个垃圾值,这个垃圾值很可能正好是某个变量的地址
//所以应该在使用 *p 之前给p赋值地址:p = &i;
j = *p;
//(2)❌ 给垃圾值地址的变量赋值一个新值,垃圾值应不受你控制的,随意改内存很危险 。
//若是 先写了p = &i; 则下面等价于 i = i;
*p = i;
}
#include <stdio.h>
change_arr(int * p , int len) {
p[0] = -1; //p[0] = *(p + 0) = *p
p[2] = -9; //p[2] = *(p + 2) = *(a + 2) = a[2]
}
int main(void) {
int a[5] = {1,2,3,4,5};
printf("%d\n", a);
printf("%d\n", a + 1); //#####70 int型占4个字节
printf("%d\n", a + 2); //#####74
printf("%d\n", a + 3); //#####78
a + n = addr(a) + n * sizeof(typeof(a))
change_arr(a, 5);
printf("%d\n", a[0]); // -1
printf("%d\n", a[2]); //-9
}
程序运行期间,向OS申请内存,OS通过一个系统分配内存表为其分配内存后,将分配的内存标记为已被分配,最终此内存即可被变量使用。
- 结构体
- 动态内存的分配和释放
地址总线:确定地址。32位,能控制232个单元,所以内存最大是4G-1,再大也没意义。
控制总线:控制是可读可写,还是只读只写。
数据总线:进行数据传输(内存到CPU ,CPU到内存)
内存的编号不可以重复,但是内容你随便往里写内容。内存单元里的内容是什么含义,就看你怎么解读了。如果你以内存的形式解读,它就是个编号;如果你以整型的方式解读,它就是个整型数字。eg:十进制65,以地址形式解读,就是编号为65的内存单元,以int形式解读就是整数65,以char形式解读就是一个字符。所以内容本身没啥含义,看你如何解读。
《Java版数据结构》就是扯淡。因为数据结构需要链表,需要指针。以C指针的视角看待Java代码:
A a = new A();
a :指针变量
new A(); 相当于(A)malloc(sizeof(A)); 在堆中动态开辟一个内存空间。
a.method(); a此时已经不代表其本身了,而代表其指向的堆中的对象(*a)了。
a.free(); 不用手动回收了,因为这部分工作已经被JVM的GC机制自动做了。
预备知识点:
模块一:线性结构
- 连续存储 【数组】
- 离散存储 【链表】
- 线性结构的两种应用
1)栈
2)队列 - 专题:递归
1)1 + 2 + 3 + 4 + ...... + 100 = ❓
2)求100的阶乘
3)汉乐塔
4)走迷宫
模块二:非线性结构
- 树
- 图
模块三:查找和排序
折半查找
冒泡排序
选择排序
快速排序
归并排序
Java中容器和数据结构相关知识
Iterator
HashMap