齐鲁工业大学872数据结构考研笔记

笔者水平有限,错误之处请指出。

官网考纲https://yjszs.qlu.edu.cn/_upload/article/files/d6/51/76dd4bc8494eb8dbf1327a9fdeaa/3d1521b3-ce94-4de3-adc6-56a2f87aa7ef.pdf

第一章 绪论

1. 数据:是客观事物的符号表示,是所有能输入到计算机中并被计算机程序处理的符号的总称。

2. 数据元素:是数据的基本单位,通常作为一个整体考虑和处理,也称为元素、记录。由若干个数据项组成。

3. 数据项:是组成数据元素的、有独立含义的、不可分割的最小单位。

4. 数据对象:是性质相同的数据元素的集合,是数据的一个子集。

5. 数据结构:是相互之间存在一种或多种特定关系的数据元素的集合。

6. 逻辑结构:从逻辑关系上对数据的描述,与数据的存储无关,是独立于计算机的。逻辑结构有两个要素:①数据元素 ②关系。有四种基本结构:①集合结构 ②线性结构 ③树结构 ④图结构或网状结构。

7. 存储结构:是数据对象在计算机中的存储,也成为物理结构。一般有四种结构:①顺序结构    ②链式结构 ③索引结构 ④散列结构。

8. 数据类型:是一个值的集合和定义在这个集合上的一组操作的总称。有三种类型:①原子类型    ②结构类型 ③抽象数据类型。

9. 抽象数据类型:一般指由用户定义的、表示应用问题的数学模型以及在这个模型上的一组操作的总称。包括三部分:①数据对象 ②数据对象上关系的集合 ③数据对象的基本操作的集合。

10. 问题规模:是算法求解问题输入量的多少,是问题大小的本质表示,一般用整数n表示。

11. 语句频度:一条语句的重复执行次数。

12. 时间复杂度

13. 空间复杂度

14. 运算:运算的定义是针对逻辑结构的,运算的实现是针对存储结构的。

15. 算法:为了解决某类问题而规定的一个有限长的操作序列。算法有五个特性:①有穷性 ②确定性 ③可行性 ④输入 ⑤输出

16. 线性结构:元素之间存在一对一的关系。

17. 非线性结构:元素之间存在一对多或多对多的关系。

18. 算法评价的标准:①正确性 ②可读性 ③健壮性 ④高效性

19. 结构化算法:由一些基本结构顺序组成,把一个大功能的实现分割成许多小功能的实现,流程的转移只在一个基本的结构范围内。

逻辑结构

1. 集合结构

2. 线性结构

3. 树结构

4. 图结构

存储结构

1. 顺序存储结构:借助元素在存储器中的相对位置来表示数据元素之间的逻辑关系,通常借助程序设计语言中的数组类型来描述。

优点:存储密度大、空间利用率高。

缺点:插入、删除元素时不方便。

2. 链式存储结构:无需占用一整块存储空间,通常用指针描述。

优点:插入、删除方便,使用灵活。

缺点:存储密度小、空间利用率低。

 第二章 线性表

1. 线性表:具有相同数据类型的n(n≥0)个数据元素的有限序列。

2. 顺序表:用顺序存储的方式实现线性表的存储。

3. 单链表:每个结点只包含一个指针域的链表。

4. 循环链表:表中最后一个结点的指针域指向头节点。

5. 双向链表:结点中有两个指针域,一个指向后驱,一个指向后继。

6. 头指针:指向链表中第一个结点的指针。

7. 头结点:在首结点前附设的一个结点,其指针域指向首结点。

8. 首结点:存放第一个元素的结点。

9. 设置头结点的好处:便于首结点的处理,便于空表和非空表的统一处理。

10. 广义表的表头是指第一个元素,表尾是指除第一个元素之外的其他元素。

第三章 栈和队列

1. :限定仅在表尾进行插入或删除操作的线性表。元素后进先出。栈应用于括号匹配、进制转换、表达式求值,递归等。

2. 队列:仅在表的一端进行插入,在另一端删除的线性表。元素先进先出。应用于层次遍历、广度优先遍历等。

3. 递归:在一个函数、过程或数据结构的定义中又应用了它自身,那么这个函数、过程或数据结构称为递归定义的。

第四章 数组和广义表

1. 数组:由相同类型的数据元素构成的有限序列。

2. 广义表:也称列表,是线性表的推广。

第五章 树和二叉树

1. :是n(n≥0)个结点的有限集,或为空树(n=0),或为非空树。n个结点的树有1个根节点,有n-1条边,有分支的叫分支结点,无分支的叫叶子结点。高为h的m叉树有\left ( m^{h}-1 \right )\left ( m-1 \right )个结点。

2. 二叉树:n(n≥0)个结点的有限集,满足:

①或为空二叉树(n=0);

②由一个根结点和左右子树组成,左右子树分别是二叉树。

3. 满二叉树:高度为h,有2^{h}-1个结点的二叉树。

4. 完全二叉树:高度为h,有n个结点的二叉树,当且仅当其每一个结点都与深度为h的满二叉树的1~n编号一一对应时,称为完全二叉树。

5. 二叉排序树:或为空树,或满足:

①左子树上所有结点的关键字小于根结点的关键字;

②右子树上所有结点的关键字大于根结点的关键字;

③左右子树各是二叉排序树。

6. :树中一个结点的孩子数称为该结点的度。

7. 线索二叉树:指向结点前驱和后继的指针称为线索,加上线索的二叉树称为线索二叉树。

8. 平衡二叉树:树上任一结点的左右子树高度之差不超过1。平衡二叉树具有更高的搜索效率。

9. 哈夫曼树:也叫最优二叉树。在有n个带权叶子的二叉树中,带权路径长度最小的二叉树叫哈夫曼树。

10. 前缀编码:在一个编码方案中任何一个编码都不是其它编码的前缀,这种编码方案叫做前缀编码。

先序、中序、后序遍历

 先序遍历:根左右(先写根结点,再写左孩子,再写右孩子)

1 2         3
1 2 4 5     3 6
1 2 4 5 7 8 3 6

中序遍历:左根右(先写左孩子,再写根结点,再写右孩子)

  2       1 3
4 2   5   1 3 6
4 2 7 5 8 1 3 6

后序遍历:左右根(先写左孩子,再写右孩子,再写根结点)

        2   3 1
4     5 2 6 3 1
4 7 8 5 2 6 3 1

线索二叉树(以中序为例)

没有左或右孩子的结点,其空的一边指向遍历序列中其前或后的元素,若没有则指向null。

中序序列为:42758136

树转换成二叉树

1. 加线。某结点的所有孩子用横线连接。

2. 减线。只保留和第一个孩子的连线。

3. 旋转。兄弟结点绕最左侧结点顺时针旋转45度。

原来的树      

加线             

减线             

旋转             

 森林转换成二叉树

1. 把每个树转换成二叉树。

2. 每个树的根结点按照位置看作双亲或孩子。

3. 合并。

森林                         

分别转换为二叉树

处理根结点                 

合并            

 二叉树转换为森林(孩子兄弟法)

1. 左子树看作孩子,右子树看作兄弟。

2. 每层最右边的结点成为独立的根结点。

 对树、森林的遍历

森林二叉树
先序遍历先序遍历先序遍历
后序遍历中序遍历中序遍历

 通过给定序列画出二叉树

1. 从先序或后序着手,以中序为辅助。

例:中序 D C B G E A H F I J K

       后序 D C E G B F H K J I A

由后序序列可知A为根结点,再由中序序列分左右

推得二叉树为

2. 由层次遍历知根结点,由中序遍历分左右子树。

例:中序:E A F D H C B G I

       层次:D A B E F C G H I

由层次遍历可知D为根结点,此树为

构造哈夫曼树(最优二叉树),制定哈夫曼编码

方法:每次使最小的两个权值相加。

例:假设字符a、b、c、d、e、f的使用频度是0.07、0.09、0.12、0.22、0.23、0.27,设计哈夫曼编码。

①先将概率放大100倍,以便构造哈夫曼树

a   b   c   d   e   f
7   9   12  22  23  27

②构造哈夫曼树

选择7和9,得16

选择12和16,得28

 选择22和23,得45

 选择27和28,得55

选择45和55

③每个非叶结点的左子树标0,右子树标1

 

④从根结点出发,所经路径即为哈夫曼编码 

字符哈夫曼编码
a1110
b1111
c110
d00
e01
f10

创建二叉排序树

以第一个元素为根结点,依次插入,比它小的放入左子树,比它大的放入右子树

例:56  18  65  29  78  13  87  23  97  54

二叉排序树为

对于每个非叶子结点,其左子树关键字小于它,右子树关键字大于它。

第六章 图

1. :图G由两个集合V和E组成,既为G=(V,E),其中V是顶点的有穷非空集合,E是V中顶点偶对的有穷集合,这些顶点偶对称为边。

2. 有向图:边是有向边的图,n个顶点最多n(n-1)条有向边。

3. 无向图:边是无向边的图,n个顶点最多n(n-1)/2条无向边。

4. 关键路径:从源点到汇点的有向路径中,具有最大路径长度的路径。关键路径上的活动叫关键活动。

5. :带权的图。

6. 连通图:若图中任意两个顶点都是连通的,则称此图为连通图,否则称为非连通图。

7. 连通分量:无向图中的极大连通子图。

8. 邻接矩阵:表示顶点之间相邻关系的矩阵。

9. 生成树:包含图中全部顶点的一个极小连通子图,有n-1条边。

10. 最小生成树:所有生成树中各边权值之和最小的树。

11. 强连通分量:在有向图中,如果两个顶点可以相互到达,则称这两个顶点是强连通的。若图中任何一对顶点都是强连通的,则称此图为强连通图。极大强连通子图即为强连通分量。

12. AOV网:用顶点表示活动,用弧活动间优先关系的有向图。

事件的最早发生时间ve(i):起点到它的最长路径;

时间的最迟发生时间vl(i):从终点开始,后一个时间的vl(i)减边,取最小的一个;

活动的最早发生时间e(i):该边起点的ve(i);

活动的最迟发生时间l(i):该边终点的vl(i)减该边。

13. 拓扑排序:将AOV网中所有顶点排成一个线性序列,该序列满足:若在AOV网中由顶点i到顶点j有一条路径,则在该线性序列中的顶点i必定在j之前。

14. 拓扑排序的过程:① 在有向图中选择一个没有前驱的顶点并输出它;

② 从图中删除该顶点以及所有以它为起点的弧;

③ 重复①②直到不存在没有前驱的顶点。

注意,拓扑排序不是唯一的。

邻接矩阵和邻接表

在无权图上用0和1表示,在有权图上用∞和权值表示,例如:

有向无权图

图 6.1

邻接矩阵如下

   v1  v2  v3  v4  v5  v6

v1  0   0   0   0   1   1
    
v2  1   0   1   1   0   0

v3  0   0   0   0   1   1

v4  0   0   1   0   0   1

v5  0   0   0   0   0   0

v6  0   1   0   0   1   0

邻接表为
 

注意,邻接矩阵不唯一

无向带权图

图6.2

其邻接矩阵为

     v1   v2   v3   v4   v5   v6   v7  

v1   ∞    3    2    7    ∞    ∞    ∞

v2   3    ∞    4    ∞    3    ∞    ∞

v3   2    4    ∞    5    4    ∞    ∞

v4   7    ∞    5    ∞    1    3    ∞

v5   ∞    3    4    1    ∞    ∞    7

v6   ∞    ∞    ∞    3    ∞    ∞    4

v7   ∞    ∞    ∞    ∞    7    4    ∞

广度优先遍历和广度优先生成树

根据邻接矩阵或邻接表得出,由于邻接表不唯一,故一般以邻接矩阵为依据。广度优先是指从某一点开始,优先找到该结点可以到达的所有节点作为该结点的孩子,然后对下一层结点做此动作。

以图6.1的邻接矩阵为例,其广度优先遍历序列为 v1 v5 v6 v2 v3 v4,广度优先生成树如下:

深度优先遍历和深度优先生成树

从某一点出发,找到一个可以到达的点,从该点继续向后找。体现在邻接矩阵上,就是碰到不为0和∞的点时以该点为基准继续向后找,如果碰到已经见过的点,不需要返回,直接跳过此点向后找。以图6.2的邻接矩阵为例,其深度优先遍历序列为 v1 v2 v3 v4 v5 v7 v6,生成树如下:

 注:考试时可以观察出最合适的生成树,倒推出邻接矩阵和邻接表。

最小生成树

例题:

①Prim算法,适用于稠密图。从某一点开始,每次连接一个权值最小的边,一直保持是连通图的状态,不能有环。

 ②Kruskal算法,适用于稀疏图。每次选取权值最小的边,注意不要出现环。

 拓扑排序

① 在有向图中选择一个没有前驱的顶点并输出它;

② 从图中删除该顶点以及所有以它为起点的弧;

③ 重复①②直到不存在没有前驱的顶点。

具体如下:

拓扑序列为:A E B F G C D

注意,拓扑序列不唯一,若无法输出所有结点,则说明AOV网中有环。

带权路径长度

又叫WPL,是每个带权叶子与到根结点边数的乘积之和。例如:

WPL = 5*2+7*2+2*2+12*2 = 54

WPL = 13*1+7*2+2*3+5*3 = 48

Dijkstra算法

本人能力有限,难以书面描述,推荐计算机王道考研

第七章 查找

1. 查找:在数据集合中寻找满足某种条件的数据元素的过程。

2. 查找表:也叫查找结构,是用于查找的数据集合,由同一类型的数据元素组成。

3. 关键字:数据元素中唯一标识该元素的某个数据项的值,基于关键字的查找结果是唯一的。

4. B树:又称多路平衡查找树,广泛应用于文件存储系统以及数据库系统。B树中所有结点的孩子个数的最大值称为B树的阶,通常通用m表示。一颗m阶B树或为空,或满足:

①每个结点至多m颗子树,至多m-1个关键字。

②若根结点不是终端结点,则至少有两颗子树。

③除根结点外的所有非叶结点至多有⌈m/2⌉颗子树,即至少含有⌈m/2⌉-1个关键字。

④所有的叶结点都出现在同一层次上,并且不带信息。

一颗5阶B树示意:

5. 哈希表:又称散列表。是一种数据结构,其数据元素的关键字与其存储地址直接相关。

6. 同义词:在哈希函数中,具有相同函数值的关键字称为同义词。

7. 顺序查找:从头到尾依次查找。ASL(成功)=(n+1)/2,ASL(失败)=n+1,时间复杂度O(n)。

8. 折半查找:又称二分查找,仅适用于有序的顺序表。按序号向下取整从中间开始查找,low>high时查找失败。ASL=\frac{1}{n}\sum(每层结点数×层序数),时间复杂度O(log2(n))。

9. 分块查找:块内无序,块间有序。

构造哈希函数

①除留余数法:若哈希表表长为m,则H(key)=key/p,其中p为不大于m但最接近m的素数。

②直接定址法:H(key)=key或H(key)=a*key+b,适合关键字分布基本连续的情况。

③数字分析法:选取数码分布较为均匀的若干位作为散列地址,例如手机号码后四位。

④平方取中法:取关键字平方值的中间几位。

处理冲突的方法

(一)拉链法(链接法、链地址法):直接放到哈希函数得到的地址下面,多个元素就串起来。例如:

{19,14,23,1,68,20,84,27,55,11,10,79},除留余数法选取p为11,

得到的哈希表:

平均查找长度:

ASL成功 = (∑(层数×每层个数))/关键字个数 = (9×1+3×2)/12 = 1.25

ASL失败 = 关键字个数 / 地址数 = 12/13 = 0.92

 (二)开放定址法:可存放新表项的空闲地址既向它的同义词表项开放,又向它的非同义词表项开放。例如{19,14,23,1,68,20,84,27,55,11,10,79},选取p为11。

①线性探测法:遇到冲突向后寻找空闲地址放入。

②平方探测法:遇到冲突时,地址±1,±4,±9,±16,……

 ③伪随机数法:遇到冲突时,下一个散列地址 = (当前地址+随机数)% p。

(三)再散列法:准备多个哈希函数,有冲突时使用其他函数。

各查找的时间复杂度

二分查找O(log_{2}n)
二叉排序树查找O(log_{2}n)
哈希表法O(1)
分块查找O(log_{2}n)
顺序查找O(n)

第八章 内部排序

1. 排序:重新排列元素的顺序,使元素按照关键字有序。

2. 排序的稳定性:若有两个元素i和j,两者的关键字相同,若排序前后两者的前后相对位置不变,则称这种排序方法是稳定的。

3. 堆:若n个关键字序列L[1,...,n]满足下列任一条性质,则称为堆:

①L[i]≥L[2i]且L[i]≥L[2i+1](1≤i≤n/2),称为大根堆;

②L[i]≤L[2i]且L[i]≤L[2i+1](1≤i≤n/2),称为小根堆。

直接插入排序

每次将一个待排序的记录按照其关键字大小插入到已经排好的序列中,直到全部记录插入完成。

例如:待排序序列:49 38 65 97 76 13 27 (49),先将49看作已排好的序列(仅有49一个元素的序列),然后依次插入。

38 49
38 49 65
38 49 65 97
38 49 65 76  97
13 38 49 65  76  97
13 27 38 49  65  76 97
13 27 38 49 (49) 65 76 97

简单选择排序

每一次在待排序元素中选取关键字最小(最大)的元素加入子序列,使用位置交换的方式。

例如:待排序序列:49 38 65 97 76 13 27 (49)

冒泡排序

从序列尾部开始两两比较,若为逆序(顺序),则交换位置。 

例如:待排序序列:49 38 65 97 76 13 27 (49)

 第五趟排序没有发生位置交换,说明顺序表已经有序,排序结束。

快速排序

两个指针low和high分别指向表头和表尾,把表头元素当作枢轴(基准)元素,表头位置置空。

若high<枢轴,把high值放到空位,否则不动,指针前移;若low>枢轴,把low值放到空位,否则不动,指针后移。

当甲指针的值置空了,再比较乙指针,此时乙指针指向的空位赋值了,乙指针移动。

当前指针指向的空位有值来了,或者比较后不用移动的值,才移动指针。

 以49为分界线,对其左右两边的子序列重复执行快速排序,即可得到结果。

枢轴元素进入空位,是一趟排序结束的标志

 归并

把两个或多个已经有序的序列合并成一个,每次从各序列的首位开始比较,最小的放入有序序列。

二路归并排序

将两个已经有序的序列合并成一个。做题时一般只给一个序列,此时应分成若干组,最开始每个元素作为一个序列(归并排序中,有序才能看作一个序列),然后两两归并,第二步组数减半,以此类推得到最终结果。

 希尔排序

取增量d=n/2(不强制规定,题目可能给出,向下取整即可),相距为d的元素组成一个序列进行排序,然后取d/2,以此类推直到d=1,做最后一次排序。

基于大根堆排序

第一步建堆,先把序列变成大根堆。从编号i = ⌊n/2⌋位置开始,若不满足堆的定义,则根和较大的孩子互换,然后指针前移,看前一个元素。若元素交换破坏了下一级堆,则用相同的方法调整。

例如:53 17 78 09 45 65 87 32,i = ⌊8/2⌋ = 4。

 第二步排序,将堆顶元素与待排序序列中最后一个元素交换,之后便不再参与排序,只对前n-1个元素组成的序列进行排序。注意前n-1个元素组成的序列依然要先转换成大根堆再进行排序,以此类推直到排序结束。

第一趟结果09  45  78  32  17  65  53  87
把前7个元素变成大根堆78  45  65  32  17  09  53  87
第二趟结果53  45  65  32  17  09  78  87 
把前6个元素变成大根堆65  45  53  32  17  09  78  87
第三趟结果09  45  53  32  17  65  78  87
把前5个元素变成大根堆53  45  09  32  17  65  78  87
第四趟结果17  45  09  32  53  65  78  87
把前4个元素变成大根堆45  32  09  17  53  65  78  87
第五趟结果17  32  09  45  53  65  78  87
把前3个元素变成大根堆32  17  09  45  53  65  78  87
第六趟结果09  17  32  45  53  65  78  87
把前2个元素变成大根堆17  09  32  45  53  65  78  87

第七趟结果

09  17  32  45  53  65  78  87

基于小根堆排序

类比大根堆,得到的是递减序列。

基数排序

从最低位或最高位开始排列,一般从最低位开始。

例如:520 211 438 888 007 111 985 666 996 233 168

先按个位

第一次收集:438 888 168 007 666 996 985 233 211 111 520

再按十位

第二次收集:996 888 985 168 666 438 233 520 211 111 007

再按百位

第三次收集:996 985 888 666 520 438 233 211 168 111 007

若需要递增排列,每次收集从右边开始即可。

各排序方法比较

平均时间复杂度最好时间复杂度最坏时间复杂度空间复杂度
稳定直接插入排序O(n²)O(n)O(n²)O(1)
冒泡排序O(n²)O(n)O(n²)O(1)
归并排序O(nlog_{2}n)O(nlog_{2}n)O(nlog_{2}n)O(1)
基数排序
不稳定希尔排序O(n²)O(1)
简单选择排序O(n²)O(n²)O(n²)O(1)
堆排序O(nlog_{2}n)O(nlog_{2}n)O(nlog_{2}n)O(1)
快速排序O(nlog_{2}n)O(nlog_{2}n)O(n²)O(nlog_{2}n)

一些算法

顺序表的折半查找(二分查找)

int Binary_search(SeqList L,ElemType key){
	//查找关键字为key的元素,失败返回-1
	int low = 0,high = L.length-1,mid;
	while( low <= high){
		mid = ( low + high)/2;  //选中间位置折半
		if(L.elem[mid] == key)  //查找成功
			return mid;
		else if(L.elem[mid] > key) //key在前半部分
			high = mid-1;
		else  //key在后半部分
			low = mid+1;
	}
	return -1;  //查找失败
}

顺序表递归折半查找

int Binary_search(SeqList L,int key,int low,int high){
	//参数依次为顺序表、查找的值、最小值、最大值
	int mid;
	if(low > high)  //不合法
		return -1;
	else{
		mid = (low + high)/2; //设定中间值
		if(L.elem[mid] == key) //查找成功
			return mid;
		if(L.elem[mid] > key) //在前半部分
			return Binary_search(L,key,low,mid-1);
		if(L.elem[mid] < key) //在后半部分
			return Binary_search(L,key,mid+1,high); 
	} 
}

顺序表原地逆置

void reverse(Seqlist &L){
	int i,temp;
	for(i = 0; i < L.length/2; i++){
		//对称位置交换
		temp = L.data[i];
		L.data[i] = L.data[L.length-1-i];
		L.data[L.length-1-i] = temp;
	}
}

顺序表递归逆置

void reverse(int *A,int low,int high){
	int temp;
	if(low < high){
		temp = A[low];
		A[low] = A[high];
		A[high] = temp;
		reverse(A,low+1,high-1);
	}
}

单链表选择排序

LinkList selectsort(LinkList &L){
	LNode *p = L->next,*q,*min;
	while(p){
		q = p->next;
		min = p;
		while(q){
			if(q->data < min->data)
				min = q;
			q = q->next;
		}
	if(min != p)
		swap(min->data,p->data);
	p = p->next;
	}
	return L;
}

入队

bool EnQueue(SqQueue &Q, ElenType x){
	if((Q.rear+1) % MaxSize == Q.front)
		return false;  //队满报错
	Q.data[Q.rear] = x;
	Q.rear = (Q.rear+1) % MaxSize; //队尾指针加1取模
	return true;
}

出队

bool DeQueue(SqQueue &Q, Elem
Type &x){
	if(Q.rear == Q.front)
		return false;  //队空报错
	x = Q.data[Q.front];
	Q.front = (Q.front+1) % MaxSize; //队头指针加1取模
	return true;
}

求二叉树深度

int depth(BiTree T){
	if(T == null)
		return 0;
	else{
		int lchild = depth(T -> lchild);
		int rchild = depth(T -> rchild):
		return(lchild>rchild?lchild:rchild)
		}
}

求二叉树叶子结点数

int leaf_number(BiTree T){
	if(!T) //结束条件
		return 0;
	else{
		if(T -> lchild || T -> rchild)
			return leaf_number(T -> lchild)+leaf_number(T -> rchild);
			//继续递归查找
		if(T -> lchild == null && T -> rchild == null) //找到叶子结点位置
			return 1;
	}
}

冒泡排序

void BubbleSort(int A[],int n){
	int i,j,temp, flag=1;
	for(i = n-1; i>O&&flag == 1; i--){
		flag=0;  //标签修改
		for(j=0; j<i; j++){
			if(A[j]>A[j+1]){  //若满足逆序
				temp=A[j];
				A[j]=A[j+1];
				A[j+1]=temp;//交换位置
				flag=1;//更改标签
			}
		}
	}
}

有哨兵的直接插入排序

void InsertSort(int A[],int n){
	int i,j;
	for(i=2; i<=n; i++){ //第二个元素编号为2,哨兵为0
		if(A[i]<A[i-1]){ //比前一个小
			A[0] = A[i]; //存放入哨兵位置
			for(j=i-1; A[O]<A[j]; --j)
				A[j+1] = A[j];
			ALj+1] = A[0];
		}
	}
}

无哨兵的直接插入排序

void InsertSort(int A[],int n){
	int i, j, temp;
	for(i=1 ; i<n ;i++){ //从第二个元素开始
		if(A[i] < A[i-1]){ //此元素小于前一个元素
			temp=A[i]; //暂时存放
			for(j=i-l; j>=0&&temp<A[j]; --j){//判断是否比已有序的元素小
				A[j+1]=A[j]; //比temp小的元素后移一位
				A[j]=temp;
			}
		}
	}
}

计算阶乘

void jiecheng(int n){//计算阶乘
	int i,k = 1;
	for(i = n;i>0 ; i--)
		k *= i; //循环计算n*n-1
	printf("%d", k);
}

递归计算阶乘

int fun(int n){ //递归求阶乘
	if(n == 0)
		return 0;
	if(n== 1||n == 2)
		return n;
	if(n > 2)
		return(n*fun(n-1));
}
int main(){
	int n = 5;
	printf("%d", fun(n));
}

递归计算斐波那契数列第n项

int fbnq(int n){  //递归计算斐波那契第n项
	if(n <= 0) //从第一项开始,没有第0项
		return 0;
	if(n == 1||n == 2) //前两项都是1
		return 1;
	if(n > 2) //第三项及以后
		return fbnq(n-2)+fbnq(n-1);
)
int main(){
	int n = 7;
	printf("%d",fbnq(n));
}

非递归计算斐波那契数列第n项

int fbnq(int n){  //非递归计算斐波那契第n项
	if(n <= 0)		//从第一项开始,没有第0项
		return 0;
	if(n == 1||n == 2)   //前两项都是1
		return 1;
	if(n > 2){  //第三项及以后
		int a = 1,i = 1,c = 0;
		for(int i = 3; i <= n; i++){
			c = a+b;  //前两项相加
			a = b;	//重置第一项
			b = c;  //重置第二项
		}
		printf("%d", a) ;
	}
}

  • 17
    点赞
  • 75
    收藏
    觉得还不错? 一键收藏
  • 9
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值