上一篇博客介绍了通用算法,那么有了这个基础我们可以继续分析通用数据结构了。我们知道在c++里面,既有数据又有函数,所以一个class就能干很多事情。举一个简单的例子来说,我们可以编写一个数据的class计算类。class calculate{ int m; int n;
前面我们写过各种各样的算法,什么排序、查找、二叉树、队列、堆栈等等。但是我们在编写这些代码的时候却都有一个缺点,不知道大家发现了没有?那就是这些算法中使用的数据结构都是简单的int数据。所以,如果排序的是int,那么用起来没有什么问题。关键就是万一是其他的数据类型,那我们应该怎么办呢?在c++中,有一种解决的方法。那就是类函数。
链表重合是一个好玩的问题。原题目是这样的:有两个链表,那么如何判断这两个链表是不是重合的?至于这个链表在什么时候重合的,这不重要,关键是判断这个链表究竟有没有重合。究竟有什么方法呢?最简单的方法就是查看两者有没有共同点。那么依次判断就行了。
假设我们有一个1亿个数据,其中数据的范围是0~1亿,也就是100M的数据。但是这个数组中丢了一些数据,比如说少了5啊,少了10啊,那么有什么办法可以把这些丢失的数据找回来呢?这个题目不难,但是它可以帮助我们拓展思路,不断提高算法的运行效率。对于这个问题,我们一个最简单的思路就是对各个数据进行flag判断,然后依次输出数据。
前两篇博客我们讨论了prim最小生成树的算法,熟悉了基本的流程。基本上来说,我们是按照自上而下的顺序来编写代码的。首先我们搭建一个架构,然后一步一步完成其中的每一个子功能,这样最后构成一个完成prim算法计算过程。f)将DIR_LINE队列中不符合的数据删除,主要是双节点都已经访问过的DIR_LINE数据。
C)编写最小生成树,涉及创建、挑选和添加过程MINI_GENERATE_TREE* get_mini_tree_from_graph(GRAPH* pGraph){ MINI_GENERATE_TREE* pMiniTree; DIR_LINE pDirLine; if(NULL == pGraph || NULL == pGraph->head) return NULL; pMiniTree = (MINI_GENERATE_TREE*)malloc(sizeof(MINI_GENERATE_TREE)); assert(NULL != pMiniTree);
前面我们讨论了图的创建、添加、删除和保存等问题。今天我们将继续讨论图的一些其他问题,比如说如何在图的环境下构建最小生成树。为什么要构建最小生成树呢?其实原理很简单。打个比方,现在某一个乡镇有n个村,那么这n个村肯定是联通的。现在我们打算在各个村之间搭建网线,实现村村通的工程。那么有什么办法可以实现村村互通,同时又使得最后的总距离最小呢?
在继续图的讨论之前,我们今天开个小差,讨论一下函数堆栈的基本原理。有过编程经验的朋友都知道,堆栈调试是我们在程序开发中经常应用的一个功能。那么大家有没有想过,函数堆栈是怎么开始的啊?其实我们可以自己写一个函数堆栈输出函数分析一下。
前面的几篇博客,我们对图进行基本定义,同时介绍了图的创建、图的添加和删除等。今天,我们聊一聊图是怎么在存储在外设中的。这些外接设备可以是各种类型的,比如说,可以是硬盘、sd卡、网络硬盘等等。本质上说,我们今天讨论的主题就是怎么把图的数据永久地保留在本地。并且,如果需要加载这些数据,也可以快速恢复图原来的面貌。
前面我们谈到的图的数据结构、图的创建,今天我们就来说一说如何在图中添加和删除边。边的添加和删除并不复杂,但是关键有一点需要记住,那就是一定要在小函数的基础之上构建大函数,否则很容易出现错误。一、边的创建边的创建一般来说可以分为下面以下几个步骤:1)判断当前图中是否有节点,如果没有,那么在pGraph->
前面我们讨论过图的基本结构是什么样的。它可以是矩阵类型的、数组类型的,当然也可以使指针类型的。当然,就我个人而言,比较习惯使用的结构还是链表指针类型的。本质上,一幅图就是由很多节点构成的,每一个节点上面有很多的分支,仅此而已。为此,我们又对原来的结构做了小的改变:typedef struct _LINE{ int end; int weight; struct _LINE* next;}LINE;
图是数据结构里面的重要一章。通过图,我们可以判断两个点之间是不是具有连通性;通过图,我们还可以计算两个点之间的最小距离是多少;通过图,我们还可以根据不同的要求,寻找不同的合适路径。当然,有的时候为了计算的需要,我们还需要从图中抽象出最小生成树,这样在遍历计算的时候就不需要持续判断是不是遇到了循环节点。当然,这所有的一切都是从图的表示开始的。
学过编程的朋友都知道,当初为了学习编程语言中的各种语法结构,我们要试着解决各种各样奇怪的题目。其中"数星星"就似乎其中的一种。什么是"数星星"呢?就是打印各种形状的"*",正三角、倒三角、菱形等等。本篇博客纯粹为了纪念我们逝去的岁月。a)正三角void star_1(){ int outer; int inner; for(outer = 1; outer <10;
前面我们谈到了KMP算法,但是讲的还不是很详细。今天我们可以把这个问题讲的稍微详细一点。假设在字符串A中寻找字符串B,其中字符串B的长度为n,字符串A的长度远大于n,在此我们先忽略。假设现在开始在字符串A中查找,并且假设双方在第p个字符的时候发现查找出错了,也就是下面的情况:/* * A: A1 A2 A3 A4 ... Ap ............ * B: B1 B2 B3 B4 ... Bp ...
昨天我们编写了简单的字符查找函数。虽然比较简单,但是也算能用。然而,经过我们仔细分析研究一下,这么一个简单的函数还是有改进的空间的。在什么地方改进呢?大家可以慢慢往下看。下面的代码是优化前的代码,现在再贴一次,这样分析起来也方便些:char* strstr(const char* str, char* data) { int index; int len;
字符串运算是我们开发软件的基本功,其中比较常用的功能有字符串长度的求解、字符串的比较、字符串的拷贝、字符串的upper等等。另外一个经常使用但是却被我们忽视的功能就是字符串的查找。
相比较线性表的排序而言,链表排序的内容稍微麻烦一点。一方面,你要考虑数据插入的步骤;另外一方面你也要对指针有所顾虑。要是有一步的内容错了,那么操作系统会马上给你弹出一个exception。就链表的特殊性而言,适合于链表的排序有哪些呢?
用过平衡二叉树的朋友都清楚,平衡二叉树的最大优点就是排序。不管是在数据插入的时候还是在数据删除的时候,我们都要考虑到数据的排序情况。但是和数据的添加、删除一样重要的,还有数据的查询。很不幸,平衡二叉树经常由于节点的添加和删除,数据的查询效率会变得非常低下。
深度遍历是软件开发中经常遇到的遍历方法。常用的遍历方法主要有下面三种:(1)前序遍历;(2)中序遍历;(3)后序遍历。按照递归的方法,这三种遍历的方法其实都不困难,前序遍历就是根-左-右,中序遍历就是左-根-右,后续遍历就是左-右-根。代码实现起来也不复杂。
在二叉树的遍历当中,有一种遍历方法是不常见的,那就是广度遍历。和其他三种遍历方法不同,二叉树的广度遍历需要额外的数据结构来帮助一下?什么数据结构呢?那就是队列。因为队列具有先进先出的特点,这个特点要求我们在遍历新的一层数据之前,必须对上一次的数据全部遍历结束。暂时还没有掌握队列知识的朋友可以看一看我的这一篇博客—[队列][1]。
关注时代Java