数据结构
定义
我们如何把现实中大量而复杂的问题以特定的数据类型和特定的存储结构保存到主存储器(内存)中,以及在此基础上为实现某个功能(比如查找某个元素,删除某个元素,所对应元素进行排序)而执行的相应操作,这个相应的操作也叫算法。
数据结构是专门研究数据存储的问题。
数据的存储包含两方面:个体的存储和个体关系的存储。
算法是对存储数据的操作。
- 数据结构 = 个体和个体之间的关系
- 算法 = 存储对象的操作
衡量算法的标准
- 时间复杂度:大概程序要执行的次数,而非执行的事件
- 空间复杂度:算法执行过程中大概所占用的最大内存
- 难易程度
- 健壮性
线性结构
把所有的节点用一根线穿起来
数组(连续存储)
什么叫数组
元素类型相同,大小相等
数组的优缺点
优点:
存储元素的效率非常高
缺点:
事先必须知道数组的长度
需要大块连续的内存块
插入删除元素的效率很低
链表(离散存储)
定义
n个节点离散分配,彼此通过指针相连,每个节点只有一个前驱节点,每个节点只有一个后续节点,首届点没有前驱节点,未见点没有后续节点
- 首节点:第一个有效节点
- 尾节点:最后一个有效节点
- 头结点:第一个有效节点之前的那个节点,头结点并不存放有效数据,加头结点的目的主要是为了方便对链表的操作
- 头指针:指向头结点的指针变量
- 尾指针:指向尾节点的指针变量
确定一个链表需要几个参数
只需要头指针就可以推算出链表的其他所有参数
分类
- 单链表
- 双向链表:每个节点有两个指针域
- 循环链表:能通过任何一个节点找到其他所有节点
- 非循环链表
算法
- 遍历
- 查找
- 清空
- 销毁
- 求长度
- 排序
- 删除节点
- 插入节点
算法:狭义的算法是与数据的存储方式密切相关的
,广义的算法是与数据的存储方式无关
泛型:利用某种技术达到的效果就是不同的存储方式,执行的操作是一样的
链表的优缺点
优点:
空间没有限制
插入删除元素很快
缺点:
存储速度很慢
线性结构的两种常见应用----栈
定义
一种可以实现“先进后出”的存储结构,栈类似于箱子
分类
- 静态栈
- 动态栈
算法
- 入栈
- 出栈
应用
- 函数调用
- 中断
- 表达式求值
- 内存分配
- 缓冲处理
- 迷宫
线性结构的两种常见应用----队列
定义
一种可以实现“先进先出”的存储结构
分类
- 链式队列(链表实现)
- 静态队列(数组实现)
静态队列通常都必须是循环队列
循环队列
1.静态队列威慑么必须是循环队列
当静态队列不断入队出队的时候,由于队列特性“先进先出”,头尾不断向前移动,导致队列中的地址只能使用一次(假溢出),所以引入循环队列。
2.循环队列需要几个参数确定
front和rear
1).队列初始化
front
和rear
的值都是零
2).队列非空
front
代表的是队列的第一个元素
rear
代表的是队列的最后一个有效元素的下一个元素
3).队列为空
front
和rear
的值相等,但不一定为零
3.循环队列入队伪算法
rear = (rear + 1) % 数组的长度
4.循环队列出队伪算法
front = (front + 1) % 数组的长度
5.循环队列是否为空
如果front和rear的值相等,队列一定为空
6.循环队列是否为满
(rear + 1) % 数组长度?=front
队列应用
所有和时间有关的操作都与队列有关
递归
定义
一个函数自己直接或间接调用自己
举例
- 阶乘
- 求和
- 汉诺塔
- 迷宫
递归满足的三个条件
- 递归必须有一个明确的终止条件
- 该函数所处理的数据规模必须在递减
- 这个转化必须可解的
递归与循环
递归:易于理解,速度慢,存储空间大
循环:不易于理解,速度快,存储空间小
递归的基本思想
某件规模为n的事情如果想完成,必须要你借助他n-1的规模完成。
树
定义
有且只有一个称为根的节点,有若干个互不相交的子树,这些子树本身也是树。
树是由节点和边组成,每个节点只有一个父节点但可以有多个子节点,但根节点没有父节点。
深度:从根节点到最底层节点的层数
叶子节点:没有子节点的节点
非终端节点:实际就是非叶子节点
度:子节点的个数
分类
一般的树:任意一个节点的子节点的个数都不受限制
二叉树:任意一个节点的子节点个数最多只有两个,且子节点的位置不可更改
森林:n个互不相交的树的集合
存储
二叉树存储:
连续存储:如果用数组的方式存储,必须要是完全二叉树
- 优点:查找某个节点的父节点和子节点
- 缺点:占用内存空间大
链式存储
一般二叉树的存储
- 双亲表示法:求父节点方便
- 孩子表示法:求子节点方便
- 双亲孩子表示法:求父节点和子节点都很方便,但是操作不方便
- 孩子兄弟表示法(二叉树表示法):把一个普通树转换成二叉树进行存储(设法保证任意一个节点的左指针域指向他的第一个孩子,右指针域指向下一个兄弟,只要满足这个条件,就能把一个普通树转化成二叉树)
一个普通的树转化成的二叉树一定没有右子树
森林的存储
- 先把森林转化成二叉树,在存储成二叉树(把每个树当做前一个的兄弟)
操作
二叉树
分类
- 一般二叉树
- 满二叉树:在不增加树的层数的前提下,无法再多添加一个节点的二叉树
- 完全二叉树:如果只是删除了满二叉树最底层最右边的连续若干个节点,所形成的二叉树
二叉树操作
遍历
- 先序遍历:
先访问根节点
再先序访问左子树
再先序访问右子树
- 中序遍历
中序访问左子树
再访问根节点
中序访问右子树
- 后序遍历
后序访问左子树
后序访问右子树
再访问根节点
已知两种遍历序列求原始二叉树
通过先序和中序或者中序和后续乐意还原出原始二叉树,但是通过先序和后续无法还原出原始的二叉树
应用
- 树谁数据库中数据组织的一种重要形式
- 操作系统子父进程的关系本身是一棵树
- 面向对象语言中类的集成关系本身是一棵树
- 赫夫曼树