《大话数据结构》学习笔记

程序=数据结构+算法

阅读说明:
  1. 本文是 《大话数据结构》这本书的阅读笔记,也就是说我写的这些,书中都有,想要看更详细的,可以下载原书看。原书的百度网盘:密码:u942
  2. 只记录原理和思维,不涉及编码实现。想要找代码实现的小伙伴们,这篇文章里面没有哦;
  3. 如有不正确的地方,欢迎指正。

(大家一起进步丫)



第二章 - 算法

1.什么是算法?

Ans:算法是 解决特定问题 求解步骤 的描述。

2.算法的复杂度分为哪两种?

Ans:时间复杂度 和 空间复杂度。一般而言,提算法复杂度,是指算法的时间复杂度。

3.常用的时间复杂度所耗费的时间从小到大依次为?

Ans: O ( 1 ) < O ( l o g n ) < O ( n ) < O ( n l o g n ) < O ( n 2 ) < O ( n 3 ) < O ( 2 n ) < O ( n ! ) < O ( n n ) O(1)<O(log_n)<O(n)<O(nlog_n)<O(n^2)<O(n^3)<O(2^n)<O(n!)<O(n^n) O(1)<O(logn)<O(n)<O(nlogn)<O(n2)<O(n3)<O(2n)<O(n!)<O(nn)

第三章 - 线性表

1.线性表的存储方式?以及各存储方式各自的优缺点。

Ans:存储方式有两种:顺序存储和链式存储。
图3-1 - 原创

2.单链表相关问题

3.1 单链表

3.1.1 相关概念

  • 数据域:存储数据元素信息的域
  • 指针域:存储直接后继位置的域
  • 指针(链):指针域中存储的信息
  • 结点(存储映像):数据域+指针域
    图3-2,线性表链式存储,(截图)
  • 头指针:链表中第一个结点的存储位置

图3-3,头指针(截图)

  • 头结点:在单链表的第一个节点前附设一个结点

    头结点的数据域可以不存储任何信息。也可以存储如线性表的长度等附加信息。
    图3-4,头节点(截图)

3.1.2 读取

图3-5,单链表的读取
核心思想:工作指针后移。(事先不知道要循环多少次【没有定义表长】,所以不可以用for循环)
简单来讲:从头开始找,直到找到第 i 个元素为止。该算法的时间复杂度取决于 i 的位置。最坏情况的时间复杂度为 O(n)。

3.1.3 插入

Question:假设存储元素 e 的结点为 s ,要实现结点p、p->next 和 s 之间逻辑关系的变化,只需要将结点 s 插入到结点 p 和 p->next 之间即可。如何插入呢?
图3-6,单链表插入问题  - Question ,截图
Ans:只需要让 s->next 和 p->next 的指针做一点改变即可。
图3-7 插入过程  Ans

特殊情况,对于单链表的表头和表尾的数据插入,操作是相同的!
图3-8 单链表 表头表尾 插入

总结
图3-6,单链表 插入{截图}

3.1.4 删除

图  3-7  单链表 删除操作
变换指针即可!!!

图3-8 单链表删除操作 - 算法步骤
对于插入和删除 操作越频繁的线性链表,采用链式存储越方便!!!


3.1.5 整表创建

  • 顺序存储结构的创建,其实就是一个数组的初始化,即声明一个类型和大小的数组并赋值的过程。

  • 链表存储结构不像顺序存储结构那么集中,是一种动态结构

  • 对于每个链表来说,它所占用空间的大小和位置是不需要预先分配划定的,可以根据系统的情况和实际的需求即时生成。

头插法
简要理解:最新的元素在链表的最“前”面!!!(但是,传统思维是 最新的元素要在链表的末尾!)
示意图见下:
头插法 - 示意图

头插法
尾插法
即:最新的元素在链表的末尾!!!(待补充!!!)


3.1.6 整表删除

在这里插入图片描述

3.2 静态链表

3.2.1 相关概念

  • 用数组代替指针来描述单链表
  • 数组由两个数据域组成,data 和 cur ,数据域data,用来存放数据,游标 cur 相当于单链表中的 next 指针,存放该元素的后继在数组中的下标。
  • 也可称 游标实现法

在这里插入图片描述
图片解释:

  • 对数组第一个和最后一个元素作特殊处理,不存储数据。
  • 第一个元素:即下标为 0 的元素的 cur 中存放备用链表的第一个结点的下标
  • 数组的最后一个元素:该cur中存放第一个有数值的元素的下标,相当于单链表中的头节点的作用。
  • 备用链表:未被使用的数组元素

举个例子:
甲乙丙丁戊己庚~图片是书上的!!!

  • 其中:Δ 作为下标为 0 的元素,其cur中存放备用链表(空)的第一个结点的下标,即为7(如图所示);
  • 数组的最后一个元素 庚 ,该cur中存放第一个有数值的元素的下标,即为 0(如图所示).

3.2.2 插入

核心:每当进行插入时,从备用链表上取得第一个结点作为待插入的新结点。

插入问题!
Q:如图,想要将 丙 插入到 乙 和 丁 之间,如何操作?
Ans:

  1. 首先将 丙 放在下标为 7 的位置,即备用链表第一位;
  2. 更新 乙 的 cur 为 7 ;
  3. 更新 丙 的cur 为 3,即 丁 所在的位置。

插入成功!!!示意图如下!
静态链表插入,书上截图

3.2.3 删除

核心:使得删除的位置成为第一个优先空位,把它存入第一个元素的cur中

了解了静态链表的插入,静态链表的删除也就方便理解了。

在这里插入图片描述

Q:链表如上图所示,此时,删除 甲 ?如何操作?

Ans:

  1. 首先更新下标为 0 的元素的 cur,更新为 甲 的下标;
  2. 更新 已删除元素甲 的 cur 为 备用链表 的第一个元素的 下标,本图中为8.

删除成功,示意图如下。
在这里插入图片描述

3.2.4 优缺点

在这里插入图片描述


3.3 循环链表


3.3.1 相关概念

  • 解决的问题:如何从当中一个结点(任意一个几点)出发,访问到链表的全部结点
  • 空循环链表 示意图
    空循环链表示意图
  • 非空循环链表 示意图
    非空循环链表示意图

3.3.2 双表合并

Q:合并如图所示 两个 循环链表,如何操作?
Question
Ans:
Ans


3.4 双向链表

3.4.1 相关概念

  • 定义:双向链表就是在单链表的每个结点中,再设置一个指向其前驱节点的指针域。
  • 双向链表中的结点都具有两个指针域,一个指向直接后继,另一个指向直接前驱
  • 双向链表的循环带头结点 的 空链表 示意图
    双向链表 ,空表
  • 非空循环 双向链表 示意图
    非空循环 双向链表

3.4.2 插入

Q:假设存储 s 的结点为 s ,要实现将结点 s 插入到结点p 和 p->next 之间,如何操作?
在这里插入图片描述
Ans:

s - >prior = p ; /*把 p 赋值给 s 的前驱*/
s - >next =p - >next; /*把 p->next复制给s的后继*/
p - >next ->prior = s; /*把 s 赋值给p->next的前驱*/
P - >next = s;/*把 s 赋值给 p 的后继*/

注意顺序:
先搞定 s 的前驱和后继,再搞定后结点的前驱,最后搞定前结点的后继!

3.4.3 删除

Q:删除P结点,如何操作?
在这里插入图片描述
Ans:两步

p->prior->next=p->next;/*把p->next赋值给p->prior 的后继*/
p->next->prior=p->prior;/*把p->prior赋值给p->next的前驱*/

第四章 栈与队列

4.1栈的顺序存储结构

1. 栈的最简单的理解

先进后出

2. 是不是先进栈的元素,只能是最后出栈呢?

当然不是!
书上的例子:假设有3个整型数字元素1、2、3依次进栈,会有哪些出栈次序?

  1. 1、2、3进,然后3、2、1出。出栈次序为321
  2. 1进,1出;2进,2出;3进,3出。出栈次序为123.
  3. 1进,2进,2出,1出,3进,3出。出栈次序为213
  4. 1进,1出;2进,3进,3出,2出。出栈次序为132
  5. 1进,2进,2出,3进,3出,1出。出栈顺序231

可见,只是3个元素,就有五种可能的出栈次序,如果元素数量多,出栈的顺序将更多

3. 栈最大的缺陷?

必须事先确定数组存储空间大小,万一不够用,需要编程手段来扩展数组的容量,比较麻烦

  1. 两栈共享空间

前置条件:

  1. 两个相同类型的栈,
  2. 并为它们开辟了数组空间

可能出现一种情况:栈A满了,栈B还有很多存储空间剩余。

那么,如何解决上述问题呢?

Ans:用一个数组来存储两个栈。但是需要一些技巧。

具体操作:
1. 数组有两个端点,两个栈有两个栈底(bottom)
2. 让栈A的栈底为数组的始端,即下标为0处;
3. 栈B的栈底为数组的末端,即下标为 n-1 处;

这样的话,两个栈如果增加元素,都是像中间延申。

Q:什么时候栈满?
Ans:栈A和栈B的头指针相差1

4.2 栈的链式存储结构

也称:链栈

  1. 结构

在这里插入图片描述

  1. 插入操作

假设元素值为 e 的新结点是 s ,top 为栈顶指针。示意图如下:
在这里插入图片描述

  1. 出栈 - 删除 操作

在这里插入图片描述

  1. 链栈的优点
  1. 基本不存在栈满的情况;
  2. 不需要实现确定 长度;
  3. 存取时定位方便。
  1. 链栈的缺点
  1. 相比于 顺序栈 ,可能存在内存空间浪费的情况;
  2. 链栈 每个元素都有指针域,增加了内存开销。

顺序栈和链栈的选择

  1. 栈的使用过程中,元素变化不可预料,时大时小,最好使用链栈;
  2. 如果变换在可控范围,顺序栈较好。.

4.3 栈的应用

4.3.1 递归

递归的定义

  1. 直接调用自己 或者 通过一系列的调用语句间接的调用自己 的函数 ;
  2. 每个递归定义必须至少有一个条件,满足时 递归不再进行,即不再引用自己而是返回值退出。
  1. 斐波那契数列

特别经典的兔子问题:
在这里插入图片描述

  1. 迭代 和 递归 的区别:
  1. 迭代使用的是 循环结构;
  2. 递归使用的是 选择结构

4.3.2 四则运算表达式求值

加减乘除 - 括号

逆波兰表示(后缀表达式)

9 + (3 - 1) * 3 + 10 ÷ 2
# 变换为
9 3 1 - 3 * + 10 2 / +

####
计算准则:
1.数字进栈
2.符号,则将处于栈顶的两个数字出栈,进行运算,运算结果进栈

####
9
3
1
计算  3-1
9 
2
3
计算 2*3
9 
6
计算 9+6
15
10
2
计算 10/2
15
5
计算 15+5

中缀表达式变为后缀表达式

9 + (3 - 1) * 3 + 10 ÷ 2
# 变换为
9 3 1 - 3 * + 10 2 / +

####
变换准则:
1.遇到数字输出
2.遇到符号,判断其与栈顶符号的优先级,若其是 右括号 或 优先级低于栈顶 ,则栈顶元素依次出栈并输出。并将当前符号进栈。

####
9 + (3 - 1) * 3 + 10 ÷ 2
栈内容:
+ 
(   #输出:9 3
-   #输出:9 3 1
)	#输出:9 3 1 -
--------------------
+   #输出:9 3 1 -
*	#输出:9 3 1 - 3 因为*的优先级高于+,所以+不出栈,*进栈
--------------------
+  	#输出:9 3 1 - 3 * +  10
/	#输出:9 3 1 - 3 * + 10 2 / +

4.4 队列

先进先出

概念:
1.空队列:队首和队尾重合

4.4.1 队列顺序存储

常规存储

在这里插入图片描述

出队列 - 常规

在这里插入图片描述

出队列 - 不全部移动

在这里插入图片描述

容易出现‘假溢出’问题:即队列前面都是空的,后面满了。
在这里插入图片描述

循环队列

在这里插入图片描述
存在问题:rear=front时,不是空队列,而是满队列。(见下图)
在这里插入图片描述

分辨 空队列 和 满队列
解决方式:
1.设置一个标志位,如front=rear,且flag=1时,队列为满。front=rear且flag=0时,队列为空:
2.队列为空,front=rear;队列满,使得front和rear相差1

4.4.2 队列链式存储

此处不做多余介绍,类似 单链表

第五章 串

一些定义:
空串
空格串:只有空格

5.1 朴素模式匹配算法

S="goodgoogle"   T="google"

###朴素匹配
1.从主串S的第一位开始,S和T的前3位都匹配,但是第4位不匹配
2.主串S的第二位 o 和 T的第一位不匹配,失败
....
5.主串S的第5位,和T的第一位匹配,依次匹配。匹配成功。

5.2 KMP模式匹配算法

是对朴素模式匹配的一种改进。(需要单拉出来记一下)待补充!!!

S="abcdefgab"  T="abcdex"
###
朴素匹配:匹配到第6个,发现不一样

第六章 树

定义:
1.根结点
2.叶结点(也称终端结点)
3.分支结点(也称非终端结点)
4.度:结点拥有的子树数
5.深度(也称高度):树中结点的最大层数
6.有序树:树中结点的各子树从左到右是有次序的,不能互换
7.森林:m 棵互不相交的树的集合

在这里插入图片描述

6.1 树的存储结构

存储结构

  1. 顺序存储
  2. 链式存储

6.1.1 双亲表示法

每个结点,附设一个指示器指示其双亲结点到链表中的位置。(结点除了知道自己是谁,还知道它的双亲在哪里)
在这里插入图片描述
其中:data是数据域;parent是指针域,存储改结点的双亲在数组中的下标
约定 根结点 的指针域 为 -1

例子如下:
在这里插入图片描述

6.1.2 孩子表示法

  1. 把每个结点的孩子结点排列起来,以单链表形式存储,n个结点有n个孩子链表
  2. 如果是叶子结点,此单链表为空;
  3. n个头指针又组成一个线性表,采用顺序存储结构,存放进一个一维数组中。
    在这里插入图片描述

6.1.3 孩子兄弟表示法

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值