
数据结构与算法深入
文章平均质量分 89
这个专栏是可以说是C++学习与基础算法的续栏吧。至于为什么没写在一起,主要是这部分知识也不再局限于C++的基本知识跟语法了。上一个栏目,确实挺多是书上的知识,我也比较少自己的东西,大概一半是书本知识一半的自己总结。这个专栏,我会结合cs106B的ppt来总结
gzhosp_redAnt
互联网+医疗践行者
展开
-
数据结构——排序与查找(4)——常见的内部排序算法大全
这篇博文就让我水一次,这两天量产博客,偷个懒,不过下面的文章都是我自己写的:插入排序算法及其分析简单的冒泡排序及其分析希尔排序及其分析快速排序算法及其分析合并排序算法及其分析堆排序算法及其分析选择排序算法及其分析最后附上一张王道书上的内部排序算法的复杂度分析表好了,内部排序算法暂时告一段落,外部排序算法打算在应用篇的时候再提,因为它跟树的应用还是很密切相关的。...原创 2018-10-08 11:06:34 · 469 阅读 · 0 评论 -
数据结构——排序与查找(3)——冒泡排序(C++实现)
接下来介绍另外一种排序算法原创 2018-10-08 10:33:24 · 611 阅读 · 2 评论 -
数据结构——排序与查找(2)——希尔排序(C++实现)
希尔排序原理希尔排序(Shell’s Sort),也称为“缩小增量排序”,是一种插入排序类的算法。最简单的插入排序,我在上一个专栏的一篇文章C++抽象编程——算法分析(8)——插入排序算法与分析有提到过,这里就不再赘述,这里就只介绍一些我以前没写过的算法。希尔排序是一种改进的插入排序算法。其基本思想如下:将整个待排序列分割成若干个自序列,然后对每个子序列分别进行直接插入排序算法。待整个序列中的...原创 2018-10-07 18:11:44 · 1074 阅读 · 0 评论 -
数据结构——排序与查找(1)——排序与查找简介
为什么要进行排序?原创 2018-10-07 11:20:39 · 1345 阅读 · 0 评论 -
数据结构——图(9)——拓扑排序与DFS
DAG图与AOV网一个无环的有向图称为有向无环图(DAG)。图的顶点可以表示要执行的任务,并且边可以表示一个任务必须在另一个之前执行的约束; 在这个应用程序中,拓扑排序只是任务的有效序列。 当且仅当图形没有有向循环时,即如果它是有向无环图(DAG),则可以进行拓扑排序。 任何DAG都具有至少一个拓扑排序。这种用弧来表示活动之间的优先级关系的有向图,称为顶点表示的活动的网(简称AOV网)。拓扑排...原创 2018-10-06 16:56:42 · 4080 阅读 · 0 评论 -
数据结构——图(8)——最小生成树(MST)
问题的提出如下图,假设这里有一系列的房屋,问如何铺设电线,可以使得连接所有房屋的电线的总成本最低?这是20世纪20年代早期研究最小生长树的最初动机。 (捷克数学家OtakarBorůvka完成的工作)。最短路径树与最小生成树(MST)上次,我们看到了Dijkstra算法如何用于在图中找到最短路径树。请注意,最短路径树可能不是MST,反之亦然。为什么这么说呢?最小生成树(或MST)是总成本...原创 2018-10-05 22:51:34 · 3909 阅读 · 0 评论 -
数据结构——图(7)——最短路径与Dijkstra's Algorithm
虽然原创 2018-10-05 21:17:59 · 682 阅读 · 0 评论 -
数据结构——图(6)——深入分析BFS算法
DFS的不足和BFS算法虽然我们知道根据DFS算法我们可以找到所有的,由起始节点到目标节点的所有路径,但并不代表那条路是最短的或者是最佳的。就像我们上篇文章所说的一样,对于同一幅图,非递归算法找到的路径就明显比递归算法找的要短。回顾我们之前提到的BFS的基本思想:从起始顶点开始,首先探索邻居节点,然后再移动到下一级邻居。假设我们从a走到i,按照BFS算法,应该是a -> d->...原创 2018-10-05 17:20:05 · 977 阅读 · 0 评论 -
数据结构——图(5)——深入分析DFS算法
对DFS的过程分析原创 2018-10-05 16:22:56 · 1989 阅读 · 0 评论 -
数据结构——图(4)——广度优先搜索(BFS)算法思想
广度优先搜索尽管深度优先搜索具有许多重要用途,但该策略也具有不适合某些应用程序的缺点。 深度优先方法的最大问题在于它从其中一个邻居出发,在它返回该节点或者是访问其他邻居之前,它必须访问完从出发节点开始的整个路径。 如果我们尝试在一个大的图中发现两个节点之间的最短路径,则使用深度优先搜索会将我们一直带到图的远端,即使我们的的目的地离我们的出发点仅有一步之遥。广度优先搜索(Breadth-firs...原创 2018-10-05 13:11:18 · 2505 阅读 · 0 评论 -
数据结构——图(3)——深度优先搜索算法(DFS)思想
图的遍历图由顶点及其边组成,图的遍历主要分为两种:遍历所有顶点遍历所有边我们只讨论第一种情况,即不重复的列出所有的顶点,主要有两种策略:深度优先搜索(DFS),广度优先搜索(BFS)为了使深度和广度优先搜索的实现算法的机制更容易理解,假设提供了一个名为visit的函数,它负责处理每个单独节点所需的任何处理。 因此,遍历的目的是按照确定的连接顺序在每个节点上调用且仅调用一次该函数。 因...原创 2018-10-05 11:13:05 · 3400 阅读 · 0 评论 -
数据结构——图(2)——图的存储和表示方式
图的存储方式在实践中,图最常见的策略是:将每个节点的连接存储在邻接列表中。将整个图形的连接存储在邻接矩阵中。用邻接链表来表示图之间的关系在图中表示连接的最简单方法是在每个节点的数据结构中存储与其连接的节点的列表。该结构称为邻接列表。 例如,在航空公司图表中每一个节点连接的相邻节点构成一个邻接表,就像这样:使用邻接矩阵表示节点间的关系虽然临接表提供了一种表示图形中连接的便捷方...原创 2018-10-05 11:14:27 · 1877 阅读 · 0 评论 -
数据结构——图(1)——图的简单介绍
图的简介我们先回顾一下之前介绍的树的概念,在树的定义中,每个节点只能有一个父类,并且树中不能出现有环形。但是你可曾想过,当一棵树没有任何规则的时候,会发生什么吗? 现在,我们给图(graph)下一个定义: 图,是一种用节点和边来表示相互关系的数学模型。(A graph is a mathematical structure for representing relationships us...原创 2018-08-28 16:55:13 · 1947 阅读 · 0 评论 -
数据结构——hash函数——hash函数基础
hash函数的引入在介绍hash函数之前,先说个实际的例子。我是个比较乱的男生,袜子啊,书籍什么的都乱扔。那么哪天如果要找某件东西,在最坏的情况下,你需要找遍你房间的所有角落。但是,如果你是个爱收拾的男生,那么你要找某件东西的话,直接去对应的地方去寻找就好了。如果用算法复杂度表示,那么前者就是O(N)和后者是O(1)。我们现在思考,能不能将这样的结构用于数据结构当中呢?看下图: 图一那么...原创 2018-07-23 16:34:24 · 1724 阅读 · 0 评论 -
数据结构——树(11)——AVL树的实现(1)
重温AVL树我们上篇的文章介绍过什么叫平衡二叉树,以及我们是怎么样实现二叉树的平衡的。其中AVL树就是其中的一种算法。现在回顾一下,我们说过导致树不平衡的插入方式有四种。现在我们用实例来说明,假设你要创建一个BST,其中里面的元素是元素周期表中的元素。 现在按照元素周期表的顺序建立平衡二叉搜索树。我们先插入第一个元素H,这很简单,因为一开始树为空。接下来我们调用之前我们写过的addNod...原创 2018-02-13 23:14:23 · 627 阅读 · 0 评论 -
数据结构——树(10)——平衡二叉树与AVL算法
平衡树介绍前几篇的文章我们介绍了一下二叉树和二叉搜索树。现在假设我们要建立一棵BST,依次插入下列数据: 20, 33, 50, 61, 87, 99 那么按照BST的规则我们可以得到下列的BST: 如果你问我,这是一棵二叉搜索树吗?这肯定的。但是它更像什么?链表!有什么区别呢?数据结构不同,链表只包含一个指向下一个节点的指针,而这个包含的还有指向左节点的指针。这个时候我们看看,我们原创 2018-02-05 00:08:53 · 919 阅读 · 0 评论 -
数据结构——树(9)——二叉搜索树的操作实现C++代码
写了两天的二叉搜索树的操作原理,今天就把操作的C++代码拿出来大家分享。头文件BST.h#include #include using namespace std;/*定义节点结构体的数据结构*/struct Node{ string str; Node *left; Node *right; /*新节点的构造函数*/ Node(s原创 2018-02-02 14:53:21 · 599 阅读 · 0 评论 -
数据结构——树(8)——二叉搜索树的插入和删除操作
二叉搜索树的插入操作我们要在二叉搜索树中执行各种操作的前提就是,我们首先要有一棵二叉搜索树。那么,如何创建一棵二叉搜索树呢?最简单的方法就是我们可以从一棵空树开始,每次调用一个addNode函数,将一个新的值插入二叉搜索树中。但是在每次插入的时候我们都要保持树的一个排序关系,因此我们要做的就是在插入的时候,找到我们要插入的值应该在的位置。 因此和遍历的代码一样,addNode的代码可以从树根原创 2018-02-01 18:15:34 · 839 阅读 · 0 评论 -
数据结构——树(7)——二叉搜索树及其操作原理
二叉树与二叉搜索树在之前的文章中,我们提到过三叉树,n叉树,但是我们实际用的最多却是二叉树,因为这样的结构更适合我们编程和更适合我们使用递归的方式。所以我们可以限制孩子的数量使得生成的树更容易实施。那么怎么定义二叉树呢? - 树中的每个节点至多有两个孩子。 - 除根节点之外的每个节点均被指定为其父项的左侧子项或右侧子项。第二个条件强调了二叉树中的子节点相对于其父母排序。也就是说当子节点原创 2018-01-30 18:00:43 · 706 阅读 · 0 评论 -
数据结构——树(6)——树的遍历C++代码
这篇博文,主要验证上篇的树的遍历。再多的理论解释都不如来一个实例实际。现在就拿一个实例来测试这次的遍历。假设我们有这样的一棵树: 我们要用不同的方式去遍历。那么我们首先要做的就是,先建立一个个节点,然后再进行连接成树。代码如下:#include iostream>#include string>#include "Queue.h"using namespace std;/*原创 2018-01-26 16:15:16 · 1694 阅读 · 0 评论 -
数据结构——树(5)——树的先序,中序,后序,层次遍历
树的存储结构之前我们提到过堆是一棵特殊的树,在堆的存储方式中,我们选择了数组的方式去存储。因为只要知道一个节点的位置我们就能找到其他的节点的位置。但是前提是堆是一棵完全二叉树。树的结构多种多样,没人规定说一个节点只能有一个孩子。 我们先看下图,一个最简单的二叉树: 怎么表达?看到箭头,我们应该立马反应过来一个基本的工具,没错就是指针,应该立马反应过来一个数据结构,那就是链表! 对原创 2018-01-25 23:49:09 · 3669 阅读 · 0 评论 -
数据结构——树(4)——什么是树?
树的递归结构在正式学习树(tree)这个结构之前,我们实际上已经接触过这个结构了,堆(heap)实际上就是一个特殊的树,一棵完全二叉树。现在我们从一幅图中来了解一下什么是树状结构: 这幅图主要说明cart这个单词的所有可能的组合结构,按照常理,我们先考虑三个字母的排列,然后由三个字母的排列中再进行拆分,最后重复拆分直到仅有一个字母。这个套路是不是很像我们之前学过的devide —— co原创 2018-01-23 16:25:21 · 3237 阅读 · 0 评论 -
数据结构——树(3)——堆的建立与排序
二叉堆的建立在继续学下去之前,我们先来看看我们学习堆这个数据结构到底有什么意义,或者说有什么用。 - 排序(堆排序,heap sort) - Google map(即在两个地点之前寻找最短的路径) - 所有的优先队列问题 - 事件的模拟 - Huffman 编码(霍夫曼编码)那么我们在上次提到过一个问题,我们所有的操作都是建立在一个已经建好的堆中,但是现实中,我们怎么可能那么轻松原创 2018-01-22 15:26:52 · 638 阅读 · 0 评论 -
数据结构——树(2)——二叉堆的基本操作原理
###二叉堆的存储 上次我们讨论了什么是二叉堆,以及完全二叉树的定义,这次我们来看看,我们应该如何来存储我们的二叉堆。先来看看下面的这个二叉堆: 我们看到这个,也许我们第一反应是用一个基于节点的方式储存: 是的,这就是一个很正常也是最容易想到的方式。然而,科学家却发现使用基于数组的方式能更好的存储我们的二叉堆。我们把根(root),放在下标为1的位置(而不是0),这是为了我们能从数学的原创 2017-11-04 15:39:22 · 1188 阅读 · 0 评论 -
数据结构——树(1)——二叉堆
优先队列我们回顾之前我们学过的队列,队列中的元素按照特定的顺序进行储存,并只能先进先出。然而,在现实生活中,我们却想把元素按照一定的优先级储存起来。举个现实中的例子: - 我们平时坐高铁,会有所谓的头等舱,二等舱,普通舱。 - 在银行排队,总会有vip客户提前办理业务所谓优先队列(priority queue),就是把元素按照一定的优先级储存起来,而不是根据特定的顺序。因此,它与我们之前接触的基原创 2017-10-27 16:13:37 · 807 阅读 · 0 评论 -
数据结构——线性结构(9)——Vector的实现过程详解
vector的基本操作及其特点在实现vector之前,我们都知道vector是可以储存任意类型的数值的。为了实现更一般的数据操作,我们当然是得要用模板类代替传统的实现。并且我们要实现[ ]的重载。头文件/* *这个文件包含我们Vector类的模板类的声明,vector是一个高效,方便,安全的数组替代品 */#ifndef _Vector_h#define _Vector_htemplate<t原创 2017-10-22 15:56:31 · 1518 阅读 · 0 评论 -
数据结构——线性结构(8)——动态数组与Vector
动态数组与Vector为什么要删除数组占用的内存?我们先来看下面的一段代码:const int INIT_CAPACITY = 1000000;class Demo {public: Demo(); // constructor string at(int i);private: string *bigArray;};Demo::Demo(){ bigArra原创 2017-10-21 14:36:15 · 801 阅读 · 0 评论 -
数据结构——线性结构(7)——链队列的实现
链队列的实现头文件:/* *这部分文件实现我们之前所使用的queue类 *它主要的原理为 后进后出(LILO) */ #ifndef _Queue_h #define _Queue_h /* *类型: Queue<ValueType> *此类建立一个称为队列的线性结构,其中仅从一端添加和删除值。 *这个规定产生了一个(LILO)的行为,它是队列的定义特征。 *基本操作是en原创 2017-10-21 13:00:28 · 506 阅读 · 0 评论 -
数据结构——线性结构(6)——链队列的原理
链队列队列类也使用链表结构进行简单的表示。为了说明基本的方法,队列的元素存储在从队列头部开始并以尾部结尾的列表中。并且为了保证入队和出队持续运行,Queue对象必须含有指向队列两端的指针。 因此,私有实例变量的定义在queuepriv.h的修订版本如下: /* *这个文件保存的是Queue.h的私有部分 *我们这个时候用链队列。也就是用链表来实现我们的队列 *这样的队列我们称为链队列 */原创 2017-09-25 11:48:11 · 1250 阅读 · 0 评论 -
数据结构——线性结构(5)——顺序队列的实现
queue.h文件其实这部分文件跟我们的栈的头文件定义是一样的,就是我们的pop和push换成了enqueue跟dequeue/* *这部分文件实现我们之前所使用的queue类 *它主要的原理为 后进后出(LILO) */ #ifndef _Queue_h #define _Queue_h /* *类型: Queue<ValueType> *此类建立一个称为队列的线性结构,其中仅从一原创 2017-09-21 16:53:42 · 873 阅读 · 0 评论 -
数据结构——线性结构(4)——顺序队列与循环队列的原理
队列的接口从上一个专栏可以看出,栈和队列是非常相似的结构。它们之间的唯一区别是处理元素的顺序。栈使用后进先出(LIFO)的规律,其中对于栈来说push的最后一个元素始终是第一个pop的元素。而队列采用更接近于排队的的先进先出(FIFO)模式。栈和队列的接口也非常相似。两个接口的public部分的唯一变化是定义类的行为的两种方法的名称。 来自Stack类的push方法现在称为入队(enqueue),p原创 2017-09-03 23:55:24 · 3275 阅读 · 0 评论 -
数据结构——线性结构(3)——链栈的实现
链栈的实现基于上一篇的内容,我们就直接上我们的实现文件,对于里面的实现,边画图边理解:Stack.h文件/* *这部分文件实现我们之前所使用的stack类 *它主要的原理为 后进先出(LIFO) */ #ifndef _Stack_h #define _Stack_h /* *类型: Stack<ValueType> *此类建立一个称为堆栈的线性结构,其中仅从一端添加和删除值。原创 2017-09-02 19:16:12 · 1079 阅读 · 0 评论 -
数据结构——线性结构(2)——链栈中的push和pop操作
链栈尽管数组是堆栈最常见的底层表示形式,但也可以使用链表实现Stack类。 如果这样做,空堆栈的概念表示就是NULL指针: 当你将新元素推入堆栈时,该元素只会添加到链表的前端。因此,如果将元素e1 push到空栈上,该元素将存储在一个新单元格中,该单元格将成为链中唯一的链接: 将一个新元素push栈将该元素添加到链的开头。所涉及的步骤与将字符插入链表列表缓冲区所需的步骤相同。 首先分配一原创 2017-08-26 20:46:33 · 27523 阅读 · 2 评论 -
数据结构——线性结构(1)——顺序栈的实现
我们前面介绍的Stack,Queue和Vector类是抽象数据类型的一般类别的例子,称为线性结构(linear structures),其中元素以线性顺序排列。这个系列讨论了这些类型的几种可能的表示方式,并考虑了表示形式如何影响效率。 因为线性结构中的元素以类似数组的顺序排列,使用数组来表示它们似乎是一个明显的选择。实际上,我们之前中提到的CharStack类是使用数组作为底层表示来实现的。然而,原创 2017-08-25 19:36:04 · 1175 阅读 · 0 评论 -
数据结构——链表(3)
链表是什么现在我们可以回头总结一下我们的链表: - 链表是一个由节点组成的一条链。 - 每个节点包含两条信息: - 序列中存储的是一些数据 - 节点中有指向列表中下一个节点的链接。 - 我们可以从第一个单元格开始跟随着link指针,遍历整个链表。 如同下图所示(左边是一个节点,右边是由节点组成的链表) - 链表是用于存储元素序列的数据结构。 - 每个元素与其他元素分开存储原创 2017-08-24 22:13:35 · 535 阅读 · 0 评论 -
C++算法学习——数据结构——链表(2)
链表中的插入无论光标位于何处,链表的插入操作都包括以下步骤: 1. 为新单元格分配空间,并将指针存储在此单元格中的临时变量cp中的。 2. 将要插入的字符复制到新单元格的 ch 成员中。 3. 转到缓冲区光标字段指示的单元格,并将其link成员复制到新单元格的link成员。 此操作确保不会丢失超出当前光标位置的字符。 4. 更改光标所在单元格中的link成员,使其指向新单元格。 5. 更改原创 2017-06-14 21:19:39 · 1118 阅读 · 0 评论 -
C++算法学习——数据结构——链表(1)
下表显示了基于数组和基于栈的编辑器实现的编辑器操作的计算复杂度。 哪个实现更好呢? 没有一些usage pattern的知识,就不可能回答这个问题。 然而,通过了解一些人们使用编辑器的方式,表明基于堆栈的策略可能会更有效率,因为实现(插入和删除)的操作比使用编辑器的其他操作更频繁。 鉴于相关操作的相对频率,这种权衡似乎是合理的,所以栈实现有可能做得更好。毕竟,现在六个基本编辑操作中的每一个在两个原创 2017-06-14 20:02:33 · 1141 阅读 · 0 评论 -
C++算法学习——经典的抽象设计——基于栈实现的buffer
基于数组实现的buffer算法复杂度在提这部分内容的时候,我们先回顾一下我们前面的基于数组实现的文件:C++算法学习——经典的抽象设计——buffer(3) 为了建立与其他表示法进行比较的基准,最重要的是确定基于数组的实现的编辑器的计算复杂度。和以前一样,复杂性分析的目标是了解编辑操作所需的执行时间如何随着问题大小的不同而变化。 在编辑器示例中,缓冲区中的字符数是衡量问题大小的最佳方法。 因此,对原创 2017-06-13 17:18:58 · 1060 阅读 · 0 评论 -
C++算法学习——经典的抽象设计——charstack的深层复制
就目前而言CharStack类的实现尚未完成。只要你通过引用传递每个CharStack对象,并且不将一个CharStack值分配给另一个,一切都将正常工作。 但是,如果你的代码最终通过值传递CharStack,或者尝试创建现有CharStack的副本,则你的程序可能会以某种不可预测的方式崩溃。浅层和深层复制的区别CharStack类当前实现中的问题的症结在于C ++常常以一种有意义的方式解释一个对象原创 2017-06-13 15:31:18 · 704 阅读 · 0 评论 -
C++算法学习——经典的抽象设计——堆—栈模式
如果不绘制大量图片,我们是难以理解内存分配的工作原理。 用于可视化分配过程的最佳工具是 堆—栈 图,其中列出了堆和堆栈上的内存状态。 使用new操作符创建的动态分配的内存显示在图的左侧,表示堆。 每个函数调用的栈都显示在右侧。 虽然生成堆堆栈图比起原来所期望的会更麻烦。与编写代码的过程不同,它总是需要创造力,绘制堆-栈图本质上是一种机械活动。 然而,这并不意味着这个过程是微不足道的,或者你从制作这原创 2017-06-11 21:35:34 · 1051 阅读 · 0 评论