
啊哈!算法
文章平均质量分 66
读书笔记
Fiona-Dong
这个作者很懒,什么都没留下…
展开
-
(七)神奇的树 —— 2. 二叉树
2. 二叉树二叉树要么为空,要么由根结点、左子树和右子树组成,而左子树和右子树分别是一棵二叉树。二叉树中还有两种特殊的二叉树,叫做满二叉树和完全二叉树。如果二叉树中每个内部结点都有两个儿子,这样的二叉树叫做满二叉树。或者说满二叉树所有的叶结点都有同样的深度。满二叉树的严格的定义是,一棵深度为h且有 2h2^h2h-1 个结点的二叉树。完全二叉树严格的定义是:若设二叉树的高度为h,除第h层外,其他各层(1~h-1)的结点数都达到最大个数,第h层从右向左连续缺若干结点,则这个二叉树就是完全二转载 2021-09-12 15:34:47 · 220 阅读 · 0 评论 -
(七)神奇的树 —— 1. 开启“树”之旅
1. 开启“树”之旅树其实就是不包含回路的连通无向图。上面这个例子中左边的是一棵树,而右边的是一个图。因为左边的没有回路,而右边的 存在1→2→5→3→1这样的回路。正是因为树有着“不包含回路”这个特点,所以树就被赋予了很多特性:一棵树中的任意两个结点有且仅有唯一的一条路径连通。一棵树如果有n个结点,那么它一定恰好有n-1条边。在一棵树中加一条边将会构成一个回路。首先,树是指任意两个结点间有且只有一条路径的无向图。或者说,只要是没有回路的连通无向图就是树。同一棵树可以有多种转载 2021-09-12 15:34:35 · 191 阅读 · 0 评论 -
(五)图的遍历 —— 2. 图的深度优先遍历
2. 图的深度优先遍历问题:计算出最短行车方案。下面是城市的地图:数据是这样给出的,如下:第一行的5表示有5个城市(城市编号为1~5),8表示有8条公路。接下来8行每行是-条类似“abc”这样的数据,表示有一条路可以从城市a到城市b,并且路程为c公里。需要注意的是这里的公路都是单行的。小哼家在1号城市,小哈家在5号城市。现在请求出1号城市到5号城市的最短路程(也叫做最短路径)。已知有5个城市和8条公路,可以用一个5*5的矩阵(二维数组e)来存储这些信息,如下:上转载 2021-09-08 19:48:09 · 487 阅读 · 0 评论 -
(五)图的遍历 —— 3. 图的广度优先遍历
3. 图的广度优先遍历问题:小哼和小哈一同坐飞机去旅游,他们现在位于1号城市,目标是5号城市,可是1号城市并没有到5号城市的直航。不过小哼已经收集了很多航班的信息,现在小哼希望找到一种乘坐方式,使得转机的次数最少,如何解决呢?验证数据:5 7 1 51 21 32 32 43 43 54 5第一行的5表示有5个城市(城市编号为1~5),7表示有7条航线,1表示起点城市,5表示目标城市。接下来7行,每行是一条类似“ab”这样的数据表示城市a和城市b之间有航线,也就是说城市转载 2021-09-08 19:47:54 · 390 阅读 · 0 评论 -
(五)图的遍历 —— 1. 深度和广度优先
1. 深度和广度优先1.1 深度优先前面已经学习过深度和广度优先搜索。为什么叫做深度和广度呢? 其实是针对图的遍历而言的,请看下面这个图:什么是图?简单地说,图就是由一些小圆点(称为顶点)和连接这些小圆点的直线(称为边)组成的。例如上图是由五个顶点(编号为1、2、3、4、5)和5条边(1-2、1-3、1-5、2-4、3-5)组成。现在从1号顶点开始遍历这个图,遍历就是指把图的每一个顶点都访问一次。这五个顶点的被访问顺序如下图。图中每个顶点右上方的数就表示这个顶点是第几个被访问到的。这个转载 2021-09-05 09:23:30 · 211 阅读 · 0 评论 -
(四)万能的搜索 —— 3. 广度优先搜索
3. 广度优先搜索广度优先搜索(Breadth First Search,BFS),也称为宽度优先搜索。还是用一个二维数组来存储上一小节的迷宫。最开始的时候小哼在迷宫(1,1)处,他可以往右走或者往下走。在上一节中我们的方法是,先让小哼往右边走,然后一直尝试下去,直到走不通的时候再回到这里。这样是深度优先,可以通过函数的递归实现。现在介绍另外一种方法:通过“一层一层”扩展的方法来找到小哈。扩展时每发现一个点就将这个点加入到队列中,直至走到小哈的位置(p.q)时为止,具体如下:最开始小哼在入口(转载 2021-09-05 09:21:11 · 220 阅读 · 0 评论 -
(四)万能的搜索 —— 2. 解救小哈
2. 解救小哈任务:迷宫由n行m列的单元格组成(n和m都小于等于50),每个单元格要么是空地,要么是障碍物。任务是帮助小哼找到一条从迷宫的起点通往小哈所在位置的最短路径。注意障碍物是不能走的,当然小哼也不能走到迷宫之外。解答:首先可以用一个二维数组来存储这个迷宫。只能一个一个地去尝试。可以先让小哼往右边走,直到走不通的时候再回到这里,再去试另外一个方向。这里规定一个顺序,按照顺时针的方向来尝试(即按照右、下、左、上的顺序去尝试)。例如下图就是一种可行的搜索路径:现在尝试转载 2021-08-29 17:23:17 · 330 阅读 · 0 评论 -
(四)万能的搜索 —— 1. 深度优先搜索
1. 深度优先搜索问题:输入一个数n,输出1~n的全排列。举个例子,假如有编号为1、2、3的3张扑克牌和编号为1、2、3的3个盒子。现在需要将这3张扑克牌分别放到3个盒子里面,并且每个盒子有且只能放一张扑克牌。那么一共有多少种不同的放法呢?解决最基本的问题:如何往小盒子中放扑克牌。每一个小盒子都可能放1号、2号或者3号扑克牌,这需要一一去尝试,这里一个for循环就可以解决:for (i=0; i<=n; i++) { a[step] = i;//将i号扑克牌放入到第step个盒子中转载 2021-08-29 10:08:49 · 349 阅读 · 0 评论 -
(二)栈、队列、链表 —— 4. 模拟链表
4. 模拟链表链表中的每一个结点只有两个部分。可以用一个数组 data 来存储每序列中的每一个 数。那每一个数右边的数是谁,上一节中是使用指针来解决的,这里只需再用一个数组 right 来存放序列中每一个数右边的数是谁就可以了。上图的两个数组中,第一个整型数组 data 是用来存放序列中具体数字的,另外一个整型 数组 right 是用来存放当前序列中每一个元素右边的元素在数组 data 中位置的。上图的两个数组中,第一个整型数组 data 是用来存放序列中具体数字的,另外一个整型 数组 ri转载 2021-08-24 19:38:39 · 72 阅读 · 0 评论 -
(二)栈、队列、链表 —— 3. 链表
3. 链表3.1 基本概念数组的局限性:插入数值时,需要数字依次往后挪一位。操作耽误时间。链表的优势:插入数值,时间快很多。3.2 链表的实现如何实现链表呢?在 C 语言中可以使用指针和动态分配内存函数 malloc 来实现。3.2.1 回顾指针指针的定义int a;int *p;第一行是定义一个整型变量 a。第二行定义了一个整型指针变量 p。指针的作用存储一个地址。确切地说是存储一个内存空间的地址。严格地说这里的指针 p 只能存储“一个存转载 2021-08-24 19:38:24 · 110 阅读 · 0 评论 -
(二)栈、队列、链表—— 2. 栈
2. 栈2.1 基本概念后进先出的数据结构,它叫做栈。栈限定为只能在一端进行插入和删除操作。2.2 编程思想栈究竟有哪些作用呢?来看一个例子。“xyzyx”是一个回文字符串,所谓回文字符 串就是指正读反读均相同的字符序列。通过栈这个数据结构很容易判断一个字符串是否为回文。首先我们读取这行字符串,并求出这个字符串的长度。如果一个字符串是回文的话,那么它必须是中间对称的,需要求中点,即:mid = len/2-1先将 mid 之前的字符全部入栈。因为这里的栈是用来存储字符的,所以用来实现栈转载 2021-08-22 17:05:50 · 120 阅读 · 0 评论 -
(二)栈、队列、链表—— 1. 队列
1. 解密QQ号——队列给出一串加密过的数字,解密规则如下:首先将第 1 个数删除,紧接着将第 2 个数放到这串数的末尾,再将第 3 个数删除并将第 4 个数放到这串数的末尾,以此类推… 直到剩下最后一个数,将最后一个数也删除。按照刚才删除的顺序,把这些删除的数连在一 起就是最终结果。例如,加密过的一串数是“6 3 1 7 5 8 9 2 4”。那么,结果为:6 1 5 9 4 7 2 8 3。1.1 编程思想首先需要一个数组来存储这一串数即 int q[101],并初始化这个数组即 int转载 2021-08-22 17:05:35 · 463 阅读 · 0 评论 -
(一)排序 —— 4. 小哼买书
4. 小哼买书请协助小哼完成“去重”与“排序” 的工作。输入有 2 行,第 1 行为一个正整数,表示有 n 个同学参与调查(n≤100)。第 2 行有 n 个用空格隔开的正整数,为每本图书的 ISBN 号(假设图书的 ISBN 号在 1~1000 之间)。输出也是 2 行,第 1 行为一个正整数 k,表示需要买多少本书。第 2 行为 k 个用空格隔 开的正整数,为从小到大已排好序的需要购买的图书的 ISBN 号。最后,程序运行的时间限制为 1 秒。解决这个问题的方法大致有两种。第一种方转载 2021-08-18 19:58:59 · 209 阅读 · 0 评论 -
(一)排序 —— 3. 快速排序
3. 最常用的排序——快速排序出发点:既不浪费空间又可以快一点的排序算法。3.1 基本思想假设现在对“6 1 2 7 9 3 4 5 10 8”这10个数进行排序。首先在这个序列中随 便找一个数作为基准数,比如第一个数 6。接下来,需要将这个序列中 所有比基准数大的数放在 6 的右边,比基准数小的数放在 6 的左边,类似下面这种排列:3 1 2 5 4 6 9 7 10 8在初始状态下,数字 6 在序列的第 1 位。目标是将 6 挪到序列中间的某个位置, 假设这个位置是 k。现在就需要寻找转载 2021-08-18 19:58:20 · 141 阅读 · 0 评论 -
(一)排序 —— 2. 冒泡排序
2. 邻居好说话——冒泡排序2.1 简化版桶排序的缺点现在分别有 5 个人的名字和分数:huhu 5 分、haha 3 分、xixi 5 分、hengheng 2 分和 gaoshou 8 分。请按照分数从高到低,输出他们的名字。即,应该输出 gaoshou、huhu、xixi、haha、hengheng。如果使用前一小节简化版的桶排序算法仅仅是把分数进行了排序。最终输出的也仅仅是分数,但没有对人本身进行排序。也就是说,现在并不知道排序后的分数原本对应着哪一个人!桶排序不仅有上述问题,更要命的转载 2021-08-17 20:03:43 · 166 阅读 · 0 评论 -
(一)排序 —— 1. 桶排序
1. 最快最简单的排序——桶排序1.1 思路首先需要申请一个大小为11的数组int a[11]。将 a[0]~a[10]都初始化为0。下面开始处理每一个人的分数,第一个人的分数是5分,就将相对应的 a[5]的值在原来的基础增加1,即,将 a[5]的值从0改为1,表示5分出现过了一次。a[0]~a[10]中的数值就是0分到10分每个分数出现的次数。接下来,只需要将出现过的分数打印出来就可以了,出现几次就打印几次。1.2 代码实现#include <stdio.h>int mai转载 2021-08-17 20:03:25 · 127 阅读 · 0 评论