文章目录
数据结构
数据结构概述
定位
我们如何把现实中大量而复杂的问题以特定的数据类型和特定的存储结构保存到内存储器(内存)中,以及在此基础上为实现某个功能(ps:查找某个元素,删除某个元素,对所有元素进行排序)而执行的相应操作,这个相应的操作也叫算法。
数据结构 = 个体的存储 + 个体的关系存储
算法 = 对存储数据的操作(狭义的算法)(泛型 广义的算法)
泛型:同一种逻辑结构,无论逻辑结构物理结构存储是什么样子的,我们对他执行相同的操作
算法
解题的方法和步骤
衡量算法的标准
- 时间复杂度: 大概要执行的次数,而非执行的时间
- 空间复杂度: 算法执行过程中,大概所占用的最大内存
- 难易程度(应用到应用程序中 最关键)
- 健壮性
数据结构的地位
数据结构是软件中最核心的课程
程序 = 数据的存储 + 数据的操作 + 可以被计算机执行的语言(程序 = 算法 + 数据结构)
预备知识
指针
- 指针的重要性:指针是C语言的灵魂
- 定位:地址
- 内存单元的编号
- 从0开始的非负整数 范围(0—FFFFFFFF
- 指针 指针就是地址,地址就是指针
指针变量的存放单元地址的变量
指针的本质是一个操作首先的非负整数
指针变量也是变量,只不过他存放的不能是内存单元的内容,只能存放内存单元的地址 - 分类
1.基本类型的指针
结构体
- 为什么会出现结构体
结构体是用户根据实际需求,自己定义的复杂数据类型 - 如何使用结构体
struct Student st = {1000,“sdasda”,20}
struct Student pst =&st;
1.st.sid
2.pst->sid
pst 所指向的结构体变量中的sid这个成员 - 注意事项:结构体变量不能加减乘除,但是可 以赋值,普通结构体变量和结构体指针变量作为函数传参的问题
动态内存的分配和释放
模块1 线性结构(把所有的节点用一条直线穿起来)
连续存储(数组)
1.什么叫做数组
元素类型相同,大小相等
2.数组的优缺点
优点:存储速度快
缺点:事先必须知道数组的长度
插入和删除
元素会很慢
空间是比较有限的
需要大块连续的内存块
离散存储(链表)
-
定义:
n个节点离散分配
彼此通过指针相连
每个节点只有一个前驱节点,每个节点只有一个后续节点
首节点没有前驱节点,尾结点没有后续节点- 专业术语:
首节点:第一个有效的节点
尾节点:最后一个有效的节点
头结点:头结点的数据类型和首节点类型一样
第一个有效之前的那个节点
头结点并不存放有效数据
加头结点的目的主要是为了方便对链表的操作
头指针:指向头结点的指针变量
尾指针:指向尾节点的指针变量
- 专业术语:
-
确定链表的几个参数(如果希望通过函数对链表进行处理,我们至少需要接受链表的哪些参数):
只需要一个参数:头指针
因为我们通过头指针可以推算出链表的其他所有信息 -
分类;
单链表:
双链表:每一个节点,有两个指针域,前面指向前面的,后面指向后面的
循环链表:能通过任何一个节点,可以找到其他所有的节点 -
算法;
遍历
查找
清空
销毁
求长度
排序
删除
插入 -
算法:狭义的算法是域数据存储方式密切相关
广义的算法与数据的存储方式无关 -
泛型:利用某种技术达到的效果就是,不同的存数方式,执行操作是一样的
-
优缺点:
优点:空间没有限制,插入元素很快
缺点:存取的速度很慢
线性结构的两种常见应用之一 栈:
- 定义 :一种可以实现“先进后出”的存储结构
栈类似于一个箱子,先放后出 - 分类:分为静态栈和动态栈
动态栈: - 算法
出栈:
压栈: - 应用:
1.函数调用,
2.中断
3.表达式求值 (利用两个栈 编写计算器)
4.内存分配
5.缓存处理
6.迷宫
线性结构的两种常见应用之一 队列:
- 定义:一种可以实现“先进先出”的存储结构
只能在一端,单项的,两端的 - 分类:
1.链式队列:用链表实现
2.静态队列:用数组实现
静态队列通常都是必须是循环队列
-
循环队列的:
静态队列为什么是必须是循环队列 -
循环队列需要几个参数来确定:以及队列的含义:
需要两个参数来确定,不同的场所有不同的含义。1》
1.对列初始化:font rear的值都是零
2。队列非空:font代表队列的第一个元素
rear代表的是队列的最后一个有效元素
3.队列空:font和rear的值相等,但不一定是零 -
循环队列入队伪算法:
第一步,将值存入r所代表的位置,正确的写法r = (r+1)%数组的长度 -
循环队列出队伪算法:
f = (f+1)%数组的长度 -
如何判断循环队列是否为空
如果font和rear的值相等,那么该队列一定为空 -
如何哦按段循环队列已满
font的值可能比rear大,也可能比rear小,也可能两者相等,
两种方式:1.多增加一个标识符参数,2,少用一个元素, -
队列的具体应用:所有的时间和有关操作都与队列有关
递归
- 定义:一个函数自己直接或者间接调用自己
- 递归要满足的三个条件:
1.递归必须有个明确的中止条件
2.该函数所处理的数据规模必须在递减
3.这个转化必须是可解的 - 递归和循环
递归:易于理解,速度慢,存储空间大
循环:不易理解,速度快,存储空间小 - 递归的应用
1.树和森林就是以递归的方式定义的
2.树和图的很多算法都是以递归来实现的
3.很多数学公司就是以递归的方式定义的
斐波拉契序列 1 2 3 5 8 13 21 34 - 举例
1.求阶层
2.1+2+3+4+…100的和
3.汉诺塔
4.走迷宫
模块2:非线性结构
树
- 专业定义
1.有且只有一个称为根的节点
2.有若干个互不相交的子树,这些子树本身也是一课树 - 通俗的定义:
- 树是节点和边组成
- 每一个节点,只有一个父节点,但可以有多个子节点
- 但是每一个节点例外,该节点没有父节点,此节点称为根节点
- 专业术语:
- 节点
- 父节点
- 子节点
- 深度:从根节点到最底层节点的层数,称之为深度
- 叶子节点:没有子节点的节点
- 非终端节点:实际就是非叶子节点
- 度:子节点的个数
手打
树定义:
树分类:
- 一般的树:任何一个节点的子节点的个数都不受限制
- 二叉树:任意一个节点的子节点的个数,最多两个,且子节点的位置不可更改(有序的 左右节点不可以更改)
- 一般二叉树
- 满二叉树:再不增加层数的前提下,无法再增加一个节点的二叉树就是满二叉树。
- 完全二叉树:如果只是删除了,满二叉树,最底层,最右边的连续若干个节点,这样形成的二叉树就是完全二叉树
- 森林:n个互不相交的树的集合
树的存储:
- 二叉树的存储
- 连续存储[完全二叉树]
优点:查找某个节点的父节点和子节点(也包括判断有没有子节点)
缺点:耗用内存空间过大 - 链式存储:
- 连续存储[完全二叉树]
- 一般树的存储
- 双亲表示法:求父节点方便
- 孩子表示法:求子节点方便
- 双亲孩子表示法:求父节点和子节点都很方便
- 二叉树表示法:把一个普通数转化成二叉树来存储,具体转换方法(设法保证任意一个节点左指针域指向第一个孩子,右指针域,指向他的兄弟,只要满足此条件,就可以吧一个普通的二叉树转化成二叉树),一个普通的树,转化成的二叉树,一定没有右子树。
- 森林的存储:先把森林转化为二叉树,再存储二叉树
树操作:(通常是二叉树的操作)
- 树的遍历
- 先序遍历(先访问根节点)
- 先访问根节点
- 再先序访问左子树
- 再先序访问右节点
- 中序遍历(中间访问根节点)
- 中序遍历左子树
- 再访问根节点
- 再中序遍历右子树
- 后续遍历(嘴鸥胡访问根节点)
- 中序遍历左子树
- 中序遍历右子树
- 再访问根节点
- 先序遍历(先访问根节点)
- 已知两种遍历序列,求原始二叉树:通过先序和中序或者中序和后续我们可以还原出原始的二叉树,但是通过先序和后续无法还原二叉树的。换种说法就是,只有通过先序和中序,中序和后序推出原始二叉树。
树的应用
1.树是数据库中数据组织一种重要形式
2.操作系统子父进程的关系本身就是一课树
3.面向对象语言中,类的继承关系
4.赫夫曼树