预备知识
指针
cup与内存间有三条线,地址线用来确定对哪一条数据进行操作;控制线来判断他是读还是写;数据线进行传输数据。
指针与指针变量是两个不同的概念
指针就是地址,而指针变量是存放内存变量地址的变量。指针的本质是一个操作受限的非负整数。
不管是什么变量,如果想改变他的值,那么只要发送地址就可以了。如果想改变一个指针变量的值,那么需要 在传送地址时写成**p。
结构体
为什么会出现结构体?
结构体是类的一个过度,为了表示一些复杂的数据,而单个变量无法表示。
如何使用结构体变量
为什么一个指针变量占四个字节
一个字节是一个编号,一个编号是八个bit,八位确定一个地址编号。指针类型她所存的是地址的编号,而计算机是32位,他有32个地址总线,每个地址,都是由32个地址总线靠0或1来编写代表的,一个字节是八个地址总线,那32个地址总线就需要4个字节。
malloc()动态分配内存
黑色的是len
malloc函数返回类型是指针,表示数组首元素的地址,所以int*的目的是告诉他这个变量占几个字节。malloc里面则是存放的字节个数。
如果想改变一个变量的值,那么一定要传递他的地址,指针变量也不例外。
这个函数可以使p指向一个合法的地址,但是,当这个函数调用结束后,这个s变量就不存在了,所以,p就不再指向一个合法的地址。
动态分配的内存必须手动通过free函数来释放
这个函数是输出的作用
数据结构的定义
typedef的用法
为已有的数据类型起个名字。
使定义变量更加简便
若在haha前面加上一个*
两个变量时
链表
定义
专业术语
链表对函数传参
链表结点的数据类型表示
链表的分类
双链表:就是有两个指针域,但是前面的指针域只能指向前面,后面的指针域只能指向后面。
循环链表:最后一个结点的指针域可以指向第一个结点。
非循环链表插入结点
其中,q,p,r都是指针变量。pNext 是代表上面结点的pNext成员, q->pNext 代表q这个指针变量指向上面结点的pNext这个成员
非循环链表删除结点
p->pNext指向的是第二个结点的地址,p->pNext->pNext指向的是第三个结点的地址。内存不用需要用free()手动释放,要用r保存第二个结点的地址才能释放。
free p是释放p指向的那个内存,而不是p所存的内存。
链表的代码
链表的创建和链表的遍历算法
判断链表是否为空与输出链表的长度
对链表进行排序
在列表指定位置插入一个结点
删除列表指定位置的结点
插入和删除的略微差别
一个是NULL != p,一个是NULL != p->Pnext,这是因为插入时,可以在有效结点的后一个插入,但是删除时,只能删除有效结点里面的内容。
连续存储和离散存储的优缺点
栈
栈的定义
栈的代码
对栈的初始化
向栈内输入元素
遍历栈元素
从栈内取元素
清空栈
栈的应用
队列
队列的定义和分类
静态队列通常都必须是循环队列
循环队列需要几个参数来确定,及其含义的讲解
需要两个参数
入队的伪算法
出队的伪算法
如何判断队列是否为空
如何判断一个队列是否已满
队列的代码
队列的初始化
入队+判断队列是否已满
出队+判断队列是否为空
队列的遍历
队列的具体应用
递归
递归定义及其可以满足的条件
递归为什么可以自己调自己
递归和循环比较
汉诺塔问题
树
定义
专业术语
树的存储
二叉树的存储
父节点和子节点)非常快
用顺序存储时为什么要用完全二叉树去存?
任意给一个结点就能快速判断他的层数
为什么存他的父节点可以用数组,但存子节点不可以?
以为子节点可以有0个,一个或多个,没有办法用数组存,只能用链表存
普通树的存储方式
森林的存储
先把森林转化为二叉树,在进行存储
树的应用
静态创建一个树,并用先中后序查找这棵树
创建树
先序遍历这棵树
中序遍历这棵树
后序遍历这棵树
快速排序
算法
快速排序代码
再次讨论什么是数据结构
在此讨论什么是泛型
这里面同一种逻辑结构指的是都是树,或都是图这种。物理存储不同指的是使用数组或链表存储两种不同
时间复杂度
时间复杂度就是计算运行次数
字符串的时间复杂度计算
字符串有n个
二分法的时间复杂度计算
要求数据必须有序
二分法也符合按最坏的计算的情况,当其中有n个数时,最后要找到只剩一个数,及最后的结果为1
递归调用
递归次数*每次递归调用的次数