郝斌数据结构视频教程笔记
指针:
指针占的总是四个字节,和它指向的数据无关。
Malloc函数:
C语言里面用malloc函数分配了内存,必须要自己手动用free()函数去除,不然会发生内存溢出,很危险;java里面就有自动内存清理机制。
C语言里面,要跨函数调用内存,就必须要通过函数来实现,要使用动态分配。
静态分配的,函数一执行完就没了,动态分配的却还存在。
链表:
确定链表只需要头结点一个参数即可。
链表不是一个连续的,如果要往后移的话,就需要p = p->Next;
算法
狭义的算法与数据的存储方式密切相关。
广义的算法是与数据的存储方式无关。
泛型:
利用某种技术达到的效果就是:不同的存数方式,执行的操作是一样的。
C语言中没有bool类型,C++里面才有bool类型。可以用加上include
堆:动态分配,由程序员分配。
栈:静态分配,由操作系统分配。
应用:函数调用,中断,表达式求值,内存分配,缓冲处理,迷宫。
队列
一种先进先出的存储结构。
分类:链式队列:用链表实现。
静态队列:用数组实现,通常都必须是循环队列(只能够增加,不能够减少的话,数组的空间就全部浪费了)。
循环队列的讲解:
1. 静态队列为什么必须是循环队列。
2. 循环队列需要几个参数来确定。及其含义的讲解。
2个,front和rear。
头部:front(指向第一个元素),尾部:rear(指向最后一个元素的下一个元素)。
两个参数不同场合有着不同的意义:
3. 队列初始化 front和rear的值都是0.
4. 队列非空
front代表队列的第一个元素,rear代表队列最后一个有效元素的下一个元素。
5. 队列空。
front和rear的值相等,但是并不一定是0。
6. 循环队列各个参数的含义。
7. 循环队列入队伪算法讲解。
两步完成:
8. 将值存入r所代表的位置。
9. 错误的写法r=r+1(这样会内存溢出,爆掉)
正确的写法:r = (r+1)%数组的长度;
10. 循环队列出队伪算法讲解。
f = (f+1)%数组的长度;
11. 如何判断循环队列是否为空。
如果front和rear相等,则该队列一定为空。
12. 如何判断循环队列已满。
预备知识:front和rear可大可小,可相等。
两种方式:
13. 多增加一个标志识参数。
14. 少用一个元素[通常用这种方式]。
如果rear和front的值紧挨着,则队列已满。
用C语言的伪算法表示就是如下:
If((r+1)%数组的长度 == f){
满了。
}else{
不满。
}
队列算法:
(1)压栈。
(2)出栈。
队列的具体应用:所有与时间有关的操作都与队列有关,
递归
定义:一个函数直接或者间接的调用自己。
直接调用,间接调用。
递归必须满足的三个条件:
15. 必须有一个明确的终止条件。
16. 该函数所处理的数据必须在递减。(值可以递增,但处理的值必须递减)。
17. 这个转化必须是可解的。(所有的循环都可以用递归实现,反之不成立)
递归的循环的比较:
递归:易于理解,速度慢,存储空间大。
循环:不易理解,速度快,存储空间小。
举例:
1.1+2+3+……+100的和。
2.求阶乘。
数字一大的话,就会发生溢出。
在visual C++里面,整型和长整型占的字节数一样。
18. 汉诺塔。
(这不是线性递归,而是个非线性递归)。
N = 1 1
N = 2 3
N = 3 7
……
N = 64 2的64次方减1[这为一个天文数字]
4.走迷宫。
递归的应用:
(1)树和森林就是以递归的方式定义的。
(2)树和图的很多算法都是以递归来实现的。
(3)很多数学方式就是以递归的方式来定义的。
斐波拉契数列
模块二:树和图 (非线性结构)
树:
专业定义:
19. 有且只有一个称为根的节点。
20. 有若干个互不相交的子树,这些子树本身也是一棵树。
通俗的定义:
21. 树是由节点和边组成。
22. 每个节点只可以有一个父节点,但可以有多个子节点。
23. 但有一个节点例外,该节点没有父节点,此节点称为根节点。
专业术语:
节点 父节点 子节点
子孙 堂兄弟
深度:
从根节点到最底层节点的层数称为深度。
叶子节点:没有子节点的节点。
非终端节点:实际就是非叶子节点。
度:子节点的个数称为度。
整个树的度挑最大的那个点。
分类:
一般树:
任意一个节点的子节点的个数不受限制。
二叉树:
任意一个节点的子节点的个数最多是两个,且子节点的位置不可更改(为有序树)。
分类:
一般二叉树:
满二叉树:
在不增加树的层数的前提下,无法再增加一个节点的二叉树就是满二叉树。
完全二叉树:(包含了满二叉树)
如果只是删除了满二叉树,最底层,最右边的连续的若干个节点,这样形成的树就是完全二叉树。
森林:
N个互不相交的树的集合。
树的存储:
二叉树的存储:
连续存储[完全二叉树]:
优点:查找某个节点的父节点和子节点(也包括判断有没有子节点)的速度很快。
缺点:耗用内存空间过大。
链式存储(不是链表存储):
一般树的存储:(解决非线性用线性解决的方法)
24. 双亲表示法。
求父节点方便。
25. 孩子表示法。
求子节点方便。
26. 双亲孩子表示法。
求父节点和子节点都方便。
27. 二叉树表示法。
把一个普通树,转化为二叉树来存储,
具体转化方法:
设法保证任意一个节点的:
左子针域指向它的第一个孩子,右指针域指向它的下一个兄弟。
只要能够满足此条件,就可以把一个普通树转化为二叉树。
一个普通树转化成的二叉树一定没有右子树。
森林的存储:
先把森林转化成二叉树,再存储二叉树。
操作:
遍历:
先序遍历:(本质上是一个递归的过程)
先访问根节点
再先序访问左子树
再先序访问右子树
中序遍历:
中序遍历左子树
再访问根节点
再中序遍历右子树
后序遍历:
中序遍历左子树
再中序遍历右子树
再访问根节点
已知两种遍历序列求原始二叉树:
研究发现:通过先序和中序 或者中序和后续,我们可以还原出原始二叉树,但是通过先序和后续是无法还原出原始的二叉树的。
换一种说法:
只有通过先序和中序,或者中序和后序,我们才可以唯一的确定一个二叉树。
应用:
(1)树是数据库中数据组织的一种重要形式。
(2)操作系统子父进程的关系本身就是一棵树。
(3)面向对象语言中类的继承关系本身就是一棵树。
链式二叉树遍历具体程序实现:静态分配的内存在函数执行完之后,就消失了,动态分配的却还存在,还能够就访问(malloc函数写的)。
一个int类型的数据占四个字节。
模块三:查找和排序
折半查找
排序:
冒泡:
插入:
选择:
快速排序:经过一次排序只能够把第一个元素的确切位置找到(也是利用递归的思想),其它元素依然是无序的。
归并排序:
稳定排序和不稳定排序(相等的话,原来在前面的还是要在前面)。
排序和查找的关系:
排序是查找的前提
Java中容器和数据结构相关知识:
Iterator接口。
Map
哈希表。
数据结构定义:是研究数据的存储和数据的操作的一门学科。
数据的存储分为两个:
28. 个体的存储。
29. 个体关系的存储。
最核心的就是数据关系的存储,个体的存储可以忽略不计。
再次说明什么是泛型:
同一种逻辑结构,无论该逻辑结构物理存储是什么样子,我们可以对它执行相同的操作。
注意:剩下的图的相关知识,需要自己去学习和完善。