
C/C++
文章平均质量分 78
大力海棠
蓝桥杯Java组个人赛省二,麻瓜ACMer的北京尚学堂·百战程序员( ̄y▽ ̄)~*
展开
专栏收录文章
- 默认排序
- 最新发布
- 最早发布
- 最多阅读
- 最少阅读
-
创建查找删除功能的单向链表
数组一旦确立以后,在运行时我们无法改变它的大小(C99中可以用变量来确定数组大小),假如我们的程序一开始不知道要存放多少数据,一种很无奈的办法就是一开始把数组定义的很大,但是这样有可能会浪费内存,还有可能在程序运行时才发现,数组定义的还不够大,不足以容纳数据,这就很麻烦。解决的方法我们可以用链表。什么是链表?链表是由有多个带着数据的结点离散分配而成,结点由两部分组成,一部分数据域,用来存数原创 2018-02-01 09:34:39 · 321 阅读 · 0 评论 -
多源最短路:每一对顶点之间的最短路径
在一个图中用求单源最短路的方法对每一个顶点执行一次,即可得到每一对顶点的最短路径。由弗洛伊德提出的一个算法,和Dijkstra类似,它们得出的最短路径都是一步一步组合得到的。Floyd算法适合在稠密的矩阵图中使用,所以下面的例子我也用邻接矩阵表示法的方式来理解Floyd算法的运用。看这样一个例子:这是一个有向网图。表示这个图的邻接矩阵为:首先看V0这个结点,从该图的邻接矩阵中,...原创 2018-08-27 17:08:40 · 2690 阅读 · 0 评论 -
有权图的单源最短路径
和无权图不同,因为有权图的边上带权值,所以在计算最短路径时会出现和无权图不同的情况,无权图边的权值默认是1,有权图则不是,所以有权图的单源最短路径上,顶点的个数不一定是最少的。我们来看一个例子:假设以V1为源点,V6为终点,那么V1到V6的单源最短路径是哪一条?是V1->V2->V5->V8->V6。和无权图不同,有权图在找最短路时要考虑路径边上权值的问题。乍一看V1到...原创 2018-08-20 19:29:12 · 4151 阅读 · 0 评论 -
你的月亮我的C(六):指针和数组的那些事
先来看几个问题,一边从问题中入手,一边看看指针和数组之间的那些事:1、char arr[ ]和char *arr是等价的吗?答:不是。看下指针和数组的定义:数组是一个用同一类型的多个连续元素组成的事先分配好的内存块。指针是一个可以对任何数据元素的引用。所以数组的定义char arr[ n ]表示申请n个字符内存的位置,这块内存的名字为arr,也就是说有一块名为“arr”的内存“块”,里面有...原创 2018-09-24 19:31:26 · 247 阅读 · 0 评论 -
拓扑排序的实现
什么是拓扑排序呢?首先我们来了解一下另一个词:什么是“拓扑序”?拓扑序:在图中从顶点A到顶点B有一条有向路径,则顶点A一定排在顶点B之前。满足这样的条件的顶点序列称为一个拓扑序。而获得一个拓扑序列的过程就称为拓扑排序。我们来看个例子:通常大学的课程安排不是盲目的,例如,如果你想学习离散数学,前提你必须要预修高等数学这门课。如果你想学习数据结构这门课,那么你要先学了程序设计这门课,等...原创 2018-10-01 08:22:48 · 8089 阅读 · 1 评论 -
静态链表与循环链表的实现
一、静态链表用指针操作链表的实现固然方便,有时候我们也可以用一维数组来实现链表的存储与操作,这种方法不用设立指针,对于在没有指针类型的高级程序设计语言中使用链表结构,可以用到。那么如何用数组来实现链表的存储?先来看它的存储结构:#include <stdio.h>#define MaxSize 100 /*链表的最大长度*/#define ElemType int/...原创 2018-10-08 20:54:09 · 567 阅读 · 0 评论 -
AOE网络-关键路径
拓扑排序的另一个应用就是关键路径的问题,关键路径对应的是另一种网络:AOE网络。先回顾下拓扑排序中讲到的AOV网络,AOV网络即“Activity On Vertex”,即图上每一个顶点表示的是一个事件或者说一个活动,而顶点之间的有向边则表示这两个活动发生的先后顺序。在关键路径这个问题中,AOE网络指的是“Activity On Edge”,即图上的每一条边表示的是一个活动,顶点作为各个“入度...原创 2018-10-15 18:25:32 · 16804 阅读 · 1 评论 -
内部排序(一)直接插入排序和二分插入排序
我们都知道,程序=数据结构+算法。数据结构和算法是密切相关的,因为不同的数据结构配合不同的算法,会有不同的效率。排序是最常见的算法之一,功能顾名思义是将一个数据对象(即数据元素的集合)重新排列成遵循某种规则的序列。例如在构建二叉搜索树的过程中也有排序的过(插入节点过程中左子树小于其父节点,右子树大于其父结点 )程。排序是程序设计中的一种重要操作,因为对于无序的序列,进行查找操作时,我们只能用顺序查...原创 2018-10-22 18:25:46 · 1383 阅读 · 1 评论 -
内部排序(二)希尔排序的两种实现
上一篇日志讲到,对于直接插入排序法,如果要做改良,可以从两个方面入手,减少元素之间的比较次数和减少元素之间的移动次数。从减少元素之间的比较次数方面,我们可以用二分查找的思想,因为在直接插入排序的“寻找插入位置”这一过程,是一个查找过程,所以可以嵌入二分查找的方法来寻找插入位置,把直接插入排序改良成二分插入排序,这是减少了序列中元素之间比较的次数。那么如果想要减少元素之间移动的次数,怎么做?希尔...原创 2018-10-29 20:24:05 · 1685 阅读 · 0 评论 -
内部排序(三)堆排序的两种实现
堆排序是一种选择排序算法,堆排序顾名思义要用到堆,首先来回顾下有关数据结构“堆”有哪些特点。堆常用二叉树来表示,而且如果不是特殊情况的话,通常用一棵完全二叉树来表示堆。因为完全二叉树的结点分布均匀,所以通常可以用数组来实现堆的存储。 根据堆中任一结点和其他结点的值的关系,堆分成两种,最大堆和最小堆。最大堆指堆中任一结点的值都大于其子结点的值;最小堆则相反,堆中任一结点的值都小于其子结点的值。...原创 2018-11-05 18:19:22 · 323 阅读 · 0 评论 -
《健指算法》(一)反转牌面
有100张按顺序写着1-100数字的牌,一开始所有牌都是背面朝上。接下来,从第3张牌开始,隔2张牌翻牌(原本正面的变反面,反面的变正面)。然后又从第4张开始,隔三张牌翻牌。一直做下去,从第n张牌开始,每隔n-1张牌翻牌,直到没有可翻动的牌为止,求所有背面朝上的牌的数字? ...原创 2018-11-12 20:31:59 · 728 阅读 · 0 评论 -
内部排序(五)快速排序(上)- 概述与选择枢轴
快速排序终于要来了,快速排序也是交换排序的一种,其实讲快速排序前应该先讲讲冒泡排序,因为快速排序是对冒泡排序的一种改进,那就先来用最快速度复习一下冒泡排序:冒泡排序:假设要对待排序了做升序排序,那么首先从待排序列第一个元素开始,和第二个元素作比较,如果第一个元素大于第二个元素,就把它们的位置交换,接着再对序列第二个元素和第三个元素作比较,如果第二个元素比第三个元素大,就交换位置,一直重复直到长...原创 2018-11-26 20:52:47 · 4555 阅读 · 1 评论 -
内部排序(六)快速排序(下)子集划分与快排实现
集划分在上一篇日志中讲快速排序的实现思路时已经讲到,这里先再用一个简单的例子来回顾一下子集划分,假设我们的待排序列是这样:假设我们已经做好了选枢轴的操作,并且把枢轴放到了Right-1的位置了,也就是图中的49。接着设置两个指针,指向待排序列的第一个位置和最后一个位置,然后就可以开始子集划分了。第一步首先从Low指针开始往右遍历,如果遇到比枢轴大的元素,Low指针就停止。这时发现Low...原创 2018-12-03 20:24:59 · 718 阅读 · 0 评论 -
内部排序(七)桶排序与次位优先基数排序
排序算法算是学了一大半了- -、,在弄基数排序时了解到,前面所学的那些(选择、插入、希尔…堆排,快排)排序算法都是要通过比较序列元素之间的关系然后做移动这两步操作。的确,排序嘛,序列从无序到有序一定是比较元素之间的关系然后调整成正确的对应位置。不过基数排序不同,基数排序不需要进行元素之间的比较,而是借助“分配”和“收集”两个操作完成排序的。分配和收集具体是怎么样?我们通过桶排序来说明。没错是桶排序...原创 2018-12-10 20:32:25 · 978 阅读 · 0 评论 -
内部排序(八)主位优先基数排序
上一篇日志搞定了次位优先基数排序,就是把待排序列先按照最低位次位开始插入对应的桶中,然后收集所有的桶,完成一遍排序;接着继续获得次位,继续排序,直到数位达到最大关键字后完成排序。次位优先就是这样,先根据基数创建基数个桶,然后做MaxDigit(关键字)次的桶排序和收集桶操作。 有次位优先,也有主位优先。主位优先,就是把待排序列先按其主位排好序,然后对每一个主位桶再进行内...原创 2018-12-17 19:28:56 · 928 阅读 · 0 评论 -
散列表的构建与冲突处理 – 线性探测
散列表的构建是散列查找的前提,说起查找,我第一时间想起二分查找,可是二分查找要求序列是有序排列的并且元素的存储地址是连续的。对于数据查找还好,但是如果做插入或删除操作的话,就要移动大量的元素,当数据量很大时,这样明显不划算。二分查找不行(要求序列为有序序列),那么可以用二叉搜索树啊!二叉搜索树的查找、插入和删除时间复杂度可以从O(logN)到O(N)。N为二叉搜索树的高度。 ...原创 2018-12-24 16:41:38 · 2134 阅读 · 0 评论 -
无权图的单源最短路径
就像日常生活中的搭地铁问题,有的人会选择到达目的地最短距离的路线,有的人会选择地铁换乘次数最少的路线,其目的都是为了尽快到达目的地。选择到达目的地距离最短的路线,可以把两结点边的权值看成距离,而选择换乘次数最少的路线,可以把边的权值看作时间(换成次数少不代表路线就短嘛)。图论中的最短路径问题,一般指一个无向图(或有向图),边的权值理解为两结点的距离,最短路径就是在求两个不同顶点的所有路径中,边...原创 2018-08-13 16:12:18 · 3801 阅读 · 0 评论 -
完全二叉搜索树
完全二叉搜索树是两个概念的包含,即完全二叉树+二叉搜索树。二叉搜索树是一棵二叉树,以根结点为中心,根结点左子树的所有结点权值均小于根结点的权值,根结点右子树的所有结点权值均大于根结点的权值。而完全二叉树指从根结点到倒数第二层满足完美二叉树,最后一层可以不完全填充,其叶子结点都靠左对齐。(完美二叉树:又叫满二叉树,指一个深度为k(>=-1)且有2^(k+1) - 1个结点的二叉树称...原创 2018-08-06 19:02:17 · 5367 阅读 · 1 评论 -
《你的月亮我的C》(四):释放内存,free的那些事
为什么要释放内存?因为用malloc分配的内存(格式:int*a=(int*)malloc(n*sizeof(int));)会一直存在在那里,它不会自动释放,内存会在程序退出时被回收,也可以用free来显式地释放所有分配的内存。今天我们就来聊聊free的那些事。用malloc动态分配的内存被释放后就不能再使用了?是的,否则很容易出现问题,因为不小心使用了已释放的内存是很经常出现的事,比如这个:...原创 2018-07-30 17:13:30 · 921 阅读 · 0 评论 -
函数指针与回调函数
函数有它的地址,程序运行起来了,程序里肯定有地方要放这个函数。我们知道可以用printf %p来输出一个变量的地址,数组的地址,同样我们定义了一个函数后,用这个函数的名字做输出,就可以得到这个函数的地址。那么我们得到一个函数的地址,有什么用呢? 我们可以想一下,在程序里我们定义一个变量i,然后定义一个指针p,让指针p指向i得到i的地址,然后通过*p我们就可以对i进行赋值等操作。那么...原创 2018-03-10 19:07:46 · 2695 阅读 · 4 评论 -
二叉树的存储结构与递归遍历方式
二叉树可以看成是一个有穷结点的集合,由根节点和其互不相交的左子树和右子树组成,所以二叉树的度等于2。(但是注意不是所有度为2的树都是二叉树。)二叉树有斜二叉树:也就是只有左子树或者右子树,它的另一个指针域为空,这样的二叉树其实就是一个链表。如果既有左子树又有右子树,像这样的情况,成为完美二叉树:也就是除了叶结点外,每一个结点都有左子树和右子树,叶节点是比较齐的,处于同一层。对于二叉树的操作,这里讲...原创 2018-04-16 20:57:25 · 497 阅读 · 0 评论 -
堆栈的顺序存储
堆栈是一种特殊的线性表,是一种线性结构,只能对栈的顶端做操作,操作有入栈和出栈两种,就是插入和删除。堆栈一定要遵循先进后出(或叫后入先出)原则,就是最后一个进去的元素一定是第一个出来的。那么堆栈要怎么实现?第一个很简单的方法就是用一个一维数组,因为栈是一种按顺序存储的结构,所以可以用一维数组来存储栈的数据。因为栈有一个特点是后入先出,最后进入的元素最先出来,所以还要有一个数据来存储栈中最后一个元素...原创 2018-03-28 20:10:45 · 5520 阅读 · 0 评论 -
二叉树的层序遍历:栈与队列方式
二叉树有先序、中序和后序三种遍历方式外,还有第四种遍历方式:层序遍历。在说二叉树层序遍历前,我们先来了解以下对于二叉树的遍历的一些东西。对二叉树的遍历,二叉树每个结点都要有左子树和右子树(无论有无左右子树,遍历时都要会去检查),就像一个二维数组一样,二维数组每个数组元素都有两个数据。对于这些二位结构的数据结构遍历,最终遍历出来都会按照一条一维的线性序列。根据遍历方法的不同,产生的一维线性序列也就不...原创 2018-04-30 20:05:47 · 8697 阅读 · 0 评论 -
栈方式实现二叉树的遍历
递归方式就是函数自身调用自身,当递归每次调用自身时,可以看作是入栈的过程,当递归条件满足后,结束时递归再一级一级的返回,返回过程可以看作是出栈的过程。递归和栈的实现过程可以看出都是符合“先进后出,后入先出”的原则,所以递归方式其实可以转化为栈的方式来实现。对于二叉树的遍历,先序、中序、后序遍历都可以用到递归方法实现,既然递归可以转化为栈,那么如何把对二叉树的遍历也改为用栈的思想来实现?对于下面这个...原创 2018-04-23 20:50:24 · 13689 阅读 · 12 评论 -
遍历二叉树的应用:输出二叉树所有叶结点和求高度
利用二叉树的遍历方法,我们可以求得一棵二叉树的很多东西,例如我们可以遍历求得一棵二叉树的所有叶结点,到我们找到一个结点的左右子树都为空了,它就是其中一个叶结点,我们把它保存起来,在遍历完一棵二叉树后,我们就可以找到所有的叶结点。同理,我们也可以通过遍历一棵二叉树的所有节点后,求出一棵二叉树的高度。首先我们来看如何用先序遍历的方式求得一棵二叉树的所有叶结点。我们可以用递归思想,就像遍历一样的递归方法...原创 2018-05-07 20:39:41 · 9656 阅读 · 0 评论 -
二叉搜索树的查找、最值查找、插入和删除
对于一棵二叉搜索树,如果不为空,它应该满足以下三个特点:1、树上的任一结点,该结点的值都大于它的非空左子树的值。2、树上的任一结点,该结点的值都小于它的非空右子树的值。3、任一结点的左右子树都是二叉搜索树。对于二叉搜索树的查找,思路方法是:1、从根结点开始查找,如果树为空,就返回NULL。2、如果树不空,就让数据X和根结点的数据Data作比较。3、如果X的值大于根结点的Data,就往右子树中进行搜...原创 2018-05-14 20:49:58 · 9842 阅读 · 6 评论 -
如何判别是否同一棵二叉搜索树?
对于一个确定的线性序列,按顺序插入序列可以确定一棵唯一的二叉搜索树,但是。一棵二叉搜索树却可以有多种插入序列得到。例如序列1:{5,9,2} 和序列2:{5,2,9}两个序列插入初始为空的二叉搜索树中,得到的两棵二叉搜索树是一样的。所以,如何判断两棵或多棵二叉搜索树是否相同?第一种方法很自然的我们就想到是两棵树做遍历,比较每一个结点,也就是用递归,一开始看根结点同不同,然后递归比较左子树同不同,右...原创 2018-05-21 20:50:39 · 4848 阅读 · 0 评论 -
二叉搜索树:堆:最大堆的建立,插入和删除
前面我们讲到栈和队列的时候,这两种数据结构都是按时间的先后顺序来排列,如栈是按先进后出(FILO),后入先出的原则排列。而队列是按先进先出(FIFO)的原则排序。但有时候按这种时间原则的数据结构不能满足用户的一些需求,例如CPU需要执行程序的优先级别,很多时候不能靠时间顺序,有些程序重要性更高的时候,应该优先被调用,所以应该用一种按优先级高低来排列的数据结构,数据结构中的每一个对象都有各自的优先级...原创 2018-06-04 20:41:52 · 2361 阅读 · 0 评论 -
线性结构:单向链表的逆转
逆转单向链表的意思就是,给定你一个单向链表,和一个整数N,N为要逆转的结点数,要求你把链表从头结点到第N个结点给逆转过来。意思是这样的,如下图所示:(逆转1)给出一个单向链表,和给定整数N=4,也就是要求把该链表从头结点(Head->Next)开始到第四个结点,把他们逆转过来,像下面逆转后头结点由1变成了4,然后1后来链接5。那么如何去实现这样的逆转链表?既然要改变结点的序列,我们自然而然想...原创 2018-05-28 20:52:07 · 10571 阅读 · 5 评论 -
并查集:按秩归并&路径压缩
集合可以怎么表示?可以用一棵树来表示,结点表示集合的元素,而树根则用来代表这个集合。所以用树来做集合的并查集的话,对于查找某个元素属于哪个集合,我们就从这个结点开始往上找,找到它所在的这棵树的根结点。对于并集操作,只要把两棵树的根结点并在一起就可以了。所以为了满足这样的操作,我们的树结构有点小改变,变为双亲表示法:“由孩子指向双亲。每个结点都向上指向它的父结点,而不是由父结点向下指向左右子树。”这...原创 2018-06-18 20:07:07 · 1217 阅读 · 0 评论 -
图的邻接矩阵表示法&邻接表表示法
图表示是一种多对多的关系的数据结构。因为线性表表示的是一种一对一的关系的数据结构,树表示的是一种一对多的数据结构,所以图把线性表和树都包含在内。图由一个非空的有限顶点集合和一个有限边集合组成。当我们描述图的时候,一定要包含以下两个元素:1、一组顶点:例如用Vertex表示顶点的集合。2、一组边:用Edge表示边的集合,一条边是一组顶点对。 •无向边 :(i,j)∈Edge,i,j∈Ver...原创 2018-06-25 20:28:23 · 9401 阅读 · 0 评论 -
《你的月亮我的C》(二):代码风格:选择更好的条件和结构
评判代码风格良好的标准很多且不统一,从客观的角度来看,好的代码风格应该是清晰明了的,将代码用一种适当的结构配合简明的语句来表达出你的思路,这很大程度上取决于程序员的逻辑思维能力。良好的代码风格这里分成两大部分:更好的条件语句和更好的代码结构。一、选择更好的判断条件1、continue语句可以通过改变if条件来省略。具体看个例子:#include <stdio.h>int main(...原创 2018-07-09 20:39:14 · 235 阅读 · 0 评论 -
《你的月亮我的C》(一):类型定义(typedef)
“typedef关键字尽管在语法上是一种存储类型,但正如其名所示,它用来定义新的类型名称,而不是定义新的变量或函数” ...原创 2018-07-02 20:45:08 · 254 阅读 · 0 评论 -
《你的月亮我的C》(三):scanf 的那些事
1、用scanf("%d\n", &i);来输入数字,要多输入一行才返回,为什么?输入4之后,要多输入一个换行和1,才能输出4。这是因为,在scanf语句中“\n”不是表示换行符,而是表示读取并放弃连续的空白字符。scanf语句中任何的空白字符都表示读并放弃空白字符。例如在%d前的空白也会被放弃掉,所以在scanf格式串中不需要手动输入显式的空白字符。所以,在scanf...原创 2018-07-16 18:05:31 · 356 阅读 · 0 评论 -
你的月亮我的C(七):指针的那些事
最近看了一本C教材,里面指针部分讲了74页,讲的很好,指针是C的精华,熟练使用指针,等以后用到结构体指针的时候你会发现很方便,而结构体又是C中类似于面向对象的思想。一、什么是指针内存中每一个字节都有一个编号,称为地址,指针是用来存放地址的,地址标识内存中的某一个单元,所以可以用指针找到该地址的内存单元。我们知道数据是分类型的,int和float类型4个字节,double类型8个字节,不...原创 2019-02-25 20:26:45 · 198 阅读 · 0 评论