数据结构
文章平均质量分 69
peiyao456
这个作者很懒,什么都没留下…
展开
-
LZW压缩算法
1.LZW压缩适用的场景: 对于有大量重复出现的字符或者字符串,可以将重复出现的多个串用一个字符表示,并写进文件。比如可以压缩这个字符串:“TOBEORNOTTOBEORTOBEORNOT”,这个字符串中出现了大量的TO,BE,OR,NOT等等字符,我们就可以将这些重复出现的字符压缩写进文件。这里只是说明算法,并没有涉及写进文件的操作。2.压缩和解压缩的原理:(1)压缩:这原创 2017-03-07 14:46:05 · 1263 阅读 · 0 评论 -
map和set
map和set是两个主要的关联容器。关联容器究竟是什么?它和顺序容器有什么区别? 关联容器中的元素是按照关键字来保存和访问的;顺序容器中的元素是按照它们在容器中的位置来顺序保存和访问的。 map和set的底层都是通过红黑树来实现的,即中序遍历得到的序列是关键字的升序排列。然而关联容器还会由map和set衍生出一些类型。 multimap:关键字可以重复的map; multiset:关键字可以原创 2016-11-15 13:09:44 · 869 阅读 · 0 评论 -
二叉树面试题
1.求二叉树中最远的两个结点的距离:思路:对于某个结点,求出其左边的高度和右边的高度,然后加起来,最后选择最大的距离就行。核心代码如下: size_t _GetMaxDistance(Node* root,size_t& distance) { if(root == NULL) return 0; int left = _GetMa原创 2016-11-30 20:32:53 · 694 阅读 · 0 评论 -
浅析红黑树
红黑树是一棵二叉搜索树,只是它在以前的二叉树的基础上对每个结点增加了一个特性:颜色特性,或为红色或为黑色。红黑树通过保证最长路径不超过最短路径的两倍来保证近似平衡。 红黑树是满足以下特点: 1)每个节点不是红色就是黑色; 2)根节点是黑色的; 3)如果一个结点是红色,它要么没有子节点,要么子节点是黑色。(不能由连续 的红色结点) 4)对于每一个结点,从该节点原创 2016-11-02 19:52:22 · 820 阅读 · 0 评论 -
排序算法(三)从直接插入排序到希尔排序
在前边的文章(排序算法系列)中,我们已经介绍过几种排序 算法:冒泡排序、选择排序、直接插入排序、堆排序。直接插入排序 和希尔排序 都是插入排序系列。下边,我们再次以图片的形式解读直接插入排序,以便更好地学习希尔排序。 这样,我们就可以理解直接插入排序了,通过图示分析,我们知道直接插入排序最好的情况,就是接近有序(比如我们要求升序,刚好序列接近升序),这时直接插入排序就是相当快 的;最坏的情况就原创 2016-11-17 17:07:09 · 754 阅读 · 0 评论 -
如何判断一棵二叉树是否是完全二叉树
初次学习二叉树这种数据结构的时候,我们知道,假如一棵二叉树的高度是h,对于一棵完全二叉树,它的前h-1行一定是满的,第h行可以满也可以不满(结点必须集中于最后一行的左边),如果满则是满二叉树,不满的就是完全二叉树。概念描述不是很清晰~下边画图说明吧。 那么知道这些概念之后,我们要如何判断一棵二叉树是否是完全二叉树??? 1)如果一个结点有右孩子而没有左孩子,那么这棵树一定不是完全二叉原创 2016-11-13 21:00:42 · 15046 阅读 · 0 评论 -
如何将搜索二叉树转换成有序双向链表
在前边学习了搜索二叉树之后,我们知道,搜索二叉树的中序遍历结果是一个升序序列,如果我们可以利用二叉树的中序线索化的方法将搜索二叉树进行转换。 每一次转换时,我们需要记住当前结点的上一个结点prev,让prev的right指向当前结点cur,让cur的left指向prev,然后改变prev即可。线索化完成之后,我们需要找原来搜索二叉树的最左结点,即就是转换后的双向链表的头~ 下边给原创 2016-11-13 16:51:26 · 905 阅读 · 0 评论 -
只能在堆(或栈)上生成对象的类
看到这样的题目,我们首先必须明白的是,哪些变量或者说是对象是在堆上,哪些不是在堆上,这个问题,在前边的文章中已经分享过,这里,再次分享~请看图~ 知道了这些之后,我们开始分析这次分享的主题~ 1.写出一个只能在堆上生成对象的类。 方法一:要想只能在堆上生成对象,也就是说,局部对象,静态对象,全局对象都不能生成,那么我们可以将构造函数写成私有或者保护(类外不可以直接访问的),通过new来构原创 2016-11-11 19:14:04 · 797 阅读 · 0 评论 -
大数据问题
在学习c语言阶段,大家肯定都写过这样的一个程序:求一个数的阶乘。细心的同学,可能在编码的时候,会注意这个数的情况~如果给定数据过大,阶乘的结果可能会溢出~关于比较大的数的阶乘,我们就会采取别的办法~关于具体的代码,之后的文章将会为大家分享~ 再如,学习堆的时候,我们遇到这样的问题:N个数据中求取最大的前K个数,如果N不是很大,我们可以采取快排,然后选取的办法来解决~如果N很大,可以选择分组或者建堆原创 2016-11-10 12:58:35 · 651 阅读 · 0 评论 -
【数据结构】栈面试题---以O(1)时间复杂度求最小值
假设给出一组数字,我们需要在O(1)时间复杂度内完成对这组数字最小值的求解。题目具体描述:定义栈的数据结构,请在该类型中实现一个能够得到栈的最小值元素的min函数。在该栈中,调用min,push和push的时间复杂度都是O(1).下边给出两种方法:方法一:采用辅助栈实现实现过程描述:辅助栈专门用来存储当前数据栈中的元素的最小值。当数据栈中push进第一个元素,该元素也得进辅原创 2016-10-06 14:38:19 · 1956 阅读 · 1 评论 -
排序算法(八)归并排序
归并排序是利用归并的思想将一组数据进行排序。它是一种外部排序(可以对那些在磁盘上的大数据进行排序)。下边进行图解。【代码实现】//归并排序void Merge(int* a,int begin,int mid,int end,int tmp[]){ int begin1 = begin; int end1 = mid; int begin2 =原创 2016-12-01 12:17:38 · 590 阅读 · 0 评论 -
图的存储以及遍历
图中的容易混淆的几个重要的概念:完全图:有n(n-1)/2条边的无向图 称为完全图。有向完全图:具有n(n-1)条边的有向图称为有向完全图。稀疏图:边数比较少的图。稠密图:边数比较多的图。连通图:在无向图中,任意的两个顶点都是有路径的。强连通图:在有向图中,任意的两个顶点都是有路径的。(即就是vi到vj有路径,vj到vi也有路径)完全图一定是连通图,但是连通图却原创 2016-12-01 17:12:01 · 1439 阅读 · 0 评论 -
【leetcode】单链表的插入排序
单链表的直接插入排序排序思想跟数组的插入排序的思想是一样的。但是这里涉及到链表的插入删除等等,一些操作,实现起来还是稍微麻烦的。链表的直接插入:情况1:当前结点的值大于上一个结点的值,不用处理,直接去处理下一个结点;情况2:当前结点的值小于第一个结点的值,将当前结点插入到链表的开始。情况3:不满足上述两种情况的情况。也就是当前结点的值大于第一个结点的值,小于上一个结点的值时原创 2017-01-04 19:43:10 · 881 阅读 · 0 评论 -
排序算法(七)海量数据的排序问题
前边几篇文章,整理过各种各样的排序,但是那些排序都是只能在内存中进行排序,而如果给大量的数据(内存中无法容纳),要给这些数据进行排序,我们就需要借助于一种外排序----归并排序(之后的文章详细介绍)。 对于大数据的排序,我们只能讲数据存储在磁盘上,然后将存储数据的文件进行分割,将小文件中的数据拿到内存中去借助快排进行排序,最后将小文件合并为一个大文件。在这中间,小文件比较多,我将小文件原创 2016-11-27 22:19:53 · 2026 阅读 · 0 评论 -
求一棵二叉树的镜像
求一棵二叉树的镜像 二叉树的镜像就是将二叉树的左右子树都交换位置得到的一棵二叉树。所以我们可以通过递归来解决。下边给出代码实现: void _Mirror(Node* root) { if(root == NULL) return; if(root->_left == NULL && root->_right原创 2016-11-26 11:24:56 · 668 阅读 · 0 评论 -
排序算法(六)非比较排序----计数排序和基数排序
前边的几篇文章介绍的几种排序算法都是比较排序,接下来的文章将会介绍两种非比较排序。计数排序:计数排序通过哈希的方法将一组数据映射到一个数组里,最后将数组中的数依次读取,并写进原来的数组,读出的数据就是有序的。综合以上图片的分析,我们知道,保存数据信息的数组(即就是计数的count数组)的大小应该是最大数与最小数之差再加1.下边请看代码实现://计数排序void Count原创 2016-11-25 19:06:35 · 627 阅读 · 0 评论 -
简易内存池的实现
1.内存池的引入 实际运用当中,如果我们需要申请一块空间,我们一般都会new一块空间(在c语言里会用到malloc),我们知道他们两个的共同点就是在堆上申请空间,堆上的空间会比栈上的大一些(在windows的vs环境下,栈的默认大小是1MB,但是可以自己调整),所以我们可以自己去申请自己需要的大小(当然也是有一定的限制)。如果我们频繁的去申请释放空间,就会形成各种各样的内存碎片,这样就原创 2016-12-06 12:44:31 · 1146 阅读 · 0 评论 -
排序算法(五)快速排序多种版本
快速排序,就像它的名称一样,是时间复杂度比较低的一种排序算法。 我们知道,快速排序是通过分治的方法,将一个大的区间划分成小区间(找一个枢纽,将大的数放置在枢纽的右边,小的数放置在枢纽左边),然后对左右的两个小区间进行排序的过程。所以,快速排序的主要就是将区间进行划分,也就是单趟排序。单趟排序有以下的几种方法:注明:以下3种方法中的GetMidNum(),下文予以解释~1.左原创 2016-11-22 21:23:10 · 7216 阅读 · 5 评论 -
判断给定的序列是否是一棵BST的后序遍历序列
给定一个序列 ,判断该序列是否是一棵二叉搜索树的后序遍历序列。比如:我们知道,后序遍历的最后一个元素就是根节点,前边比它小的都位于根的左子树上,比它大的都位于根的右子树上。所以,对于上述的序列:8是这棵二叉搜索树的根。3,7 ,6都小于8,都位于8的左子树上。 6又是左子树的根,3小于6,是左子树的左孩子,7大于6,是左子树的右孩子。11,1原创 2016-12-03 17:24:14 · 1093 阅读 · 0 评论 -
二叉树中和为给定值的路径
找到二叉树中和为给定值的路径,其实核心还是求出二叉树的路径,如果路径上的值不满足条件,则说明,这条路径不是我们需要的。【实现代码】//找和为某一值的路径templatestruct TreeNode{ T _data; TreeNode* _left; TreeNode* _right; TreeNode(const T& x = T(原创 2016-12-02 17:43:08 · 567 阅读 · 0 评论 -
排序算法(四)选择排序及优化版本
选择排序,是通过每次选择最小的数或者最大的数,然后将它放在它应该出现的位置上。 具体实现过程:将0号下标的数据保存,在之后的数中选择一个最小的数,如果最小的数不是0号数,则将最小的数与0号下标的数进行交换;将1号下标的数进行保存,在之后的数中 选择最小的数,如果最小的数不是1号数,进行交换。以此类推。 下边给出实现代码:void SelectSort(vector<int>& v){原创 2016-11-20 13:40:24 · 5895 阅读 · 4 评论 -
【数据结构】布隆过滤器
1.布隆过滤器的引入: 我们知道,在海量整形数中查找一个数字是采用位图来完成的;如果要在海量的字符串中查找一个字符串是否在其中,位图就是无法解决的,所以引入了布隆过滤器。2.布隆过滤器的概述: 布隆过滤器是由布隆这个人提出的,它是由一系列的二进制向量和一些映射函数来实现的,它主要用于检索一个字符串是否在一个集合中,并且空间效率和查询时间都是远远超过一般的算法,还可以表示全集,其原创 2016-11-08 22:25:00 · 733 阅读 · 0 评论 -
二叉树的线索化(一)
本篇文章主要整理二叉树的先序和中序线索化,以及对线索树的两种遍历。线索化的引入:对于有n个节点的二叉树中,就会有n+1个空指针,导致空间的浪费。推导:对于任何一棵二叉树,叶子节点也就是度为0的节点数为n0,度为2的节点数为n2,则有n0 = n2+1。(总结点数为n)n0+n1+n2 = nn2+1 = n0.两等式联立:2*n0+n1 = n+1.所以我们引入了原创 2016-10-04 22:19:22 · 834 阅读 · 0 评论 -
广义表的基本实现
广义表是线性表的一种推广。下边通过几个例子说明一下广义表:A=(),A是一个空表,长度为0,深度为0.B=(m),B中只有一个元素m,长度为1,深度为1.C=(a,(b,c),d)有4个元素,长度为4,深度为2.广义表的存储:由于广义表的深度我们无法预知,当然不可以采用循环,所以用递归实现咯。下边来看看实现代码:#pragma once#includeusi原创 2016-09-25 18:22:28 · 1293 阅读 · 0 评论 -
【数据结构】栈面试题--两个栈实现一个队列
首先我们必须清楚,栈先进后出,队列先进先出。这道他们各自的特点之后,我们用两个栈来实现一个队列。下边给出图片:下边给出代码:恩原创 2016-09-21 19:08:12 · 1370 阅读 · 0 评论 -
稀疏矩阵的转置
稀疏矩阵-----矩阵中有效元素的个数远远小于总元素的个数。所以,要是我们把矩阵中的所有元素都存储起来的话,这样子对空间就是造成极大的浪费。所以,我们采用压缩存储,即就是,将有效元素存储在一个三元组中(包括元素所在行,列,值),这样就减少了空间的浪费。三元组定义如下:templatestruct Triple{ T _value; size_t _row; size_原创 2016-09-23 15:55:12 · 1201 阅读 · 0 评论 -
【数据结构】栈面试题--两个队列实现一个栈
上篇文章写了用两个栈实现一个队列,这篇文章实现用两个队列实现一个栈,其实两者的思想都是差不多的。下边继续画图说明:原创 2016-09-22 16:38:08 · 1161 阅读 · 0 评论 -
合并两个有序单链表
给出两个有序的单链表,将这两个单链表进行合并,合并出来的链表仍然是有序的。比如给出链表1:1->3->6->7;链表2:2->4->5->8->9合并后的链表为:1->2->3->4->5->6->7->8->9代码展示如下(只给出实现部分)结构体定义:typedef struct LinkNode{ DataType data; struct LinkNode *nex原创 2016-06-21 11:53:19 · 2807 阅读 · 0 评论 -
链表面试题(一)
在前边的博客中,我已经整理了链表的基本操作,在这篇文章,我来整理关于链表的一部分面试题:1.删除无头指针的非尾节点2.逆序链表3.在当前节点前插入一个元素(不给出链表的头指针)4.查找链表的中间节点5.删除链表的倒数第k个结点下边我一一给出解释(尽量画图),和对应的代码:先给出下边代码要用到的结构体的声明:typedef struct LinkNode{ D原创 2016-06-14 13:47:39 · 621 阅读 · 0 评论 -
单链表的基本实现
单链表是方向单一的链表,即就是只能从前向后访问,不能从后向前访问。这篇文章,我将整理出单链表的一些基本功能。1.尾插 2.尾删 3.头插 4.头删5.打印 6.插入7.删除指定元素 8.删除指定元素的全部9.删除指定位置的元素10.排序(此文先给出基本的冒泡排序,其他排序算法之后再给出)下边,我就这些功能一个一个进行说明,尽量配图~~(这里的单链表不带头结点)为了方便大家读以下原创 2016-06-10 14:38:22 · 2049 阅读 · 0 评论 -
链表的交点问题
单链表交点问题的分类:a.两个链表都无环 b.两个链表都有环(交点在环外;交点在环内)下边给出图示: 注意:两个链表的交点处,并不仅仅是data域相等,还要有next域相同。如果一个链表有环,另一个链表无环,他们是不可能有交点的。反证:如果有交点,一个链表有环,另一个链表必然有环。不符合条件。从以上可以看出,要想完全弄清原创 2016-06-24 18:36:11 · 1728 阅读 · 1 评论 -
判断链表是否带环,以及环的入口
给出一个链表,先判断链表是否带环,如果带环,求出环的入口。判断是否带环:用快慢指针。快指针每走两步,慢指针走一步,如果两者在某个点处相遇,则链表带环。下边给出函数的实现代码:typedef struct LinkNode{ DataType data; struct LinkNode *next;}LinkNode,*pLinkNode;typedef struct Li原创 2016-06-24 13:39:19 · 3089 阅读 · 1 评论 -
【数据结构】堆&优先级队列
说实话,之前看数据结构的时候,并没有更多的关注到堆,直到现在......堆数据结构是一种数组现象,可以看成是一种完全二叉树。堆的分类;最大堆:每个父节点都大于其孩子结点。最小堆:每个父节点都小于其孩子结点。注意注意:区分与二叉排序树的区别!!!堆也有很多应用,比如优先级队列,堆排序等等。再多的应用,都是先需要有堆。堆的底层是一个数组,了解STL之后可以将底层写成vect原创 2016-10-11 15:04:52 · 874 阅读 · 0 评论 -
二叉树面试题--已知二叉树的两种遍历序列,求出另一种遍历序列
已知先序遍历序列和中序遍历序列,求出后序序列 或者 已知中序序列和后序序列 ,求出先序遍历。。都是一些考试中容易考的题目。经过研究发现,已知先序序列和后序序列,无法唯一确定一棵树,所以就无法得知中序序列。下边给出例题:一、已知先序和中序,求出后序。下边再举一个例子,如下图:通过上边两个例子的学习,对这种题目有了一定的理解,下边举例已知中序和后序,原创 2016-09-26 09:42:56 · 6192 阅读 · 6 评论 -
【数据结构】栈面试题--一个数组实现两个栈
一个数组实现两个栈,有以下几种方法:1.数组的奇数位置存储一个栈的元素,偶数位置存储另一个栈的元素;2.两个栈分别从数组的中间向两头增长;3.两个栈分别从数组的两头开始增长。从图片中我们都可以看出,前边两种方法再一定的情况下会造成空间的浪费,所以我们采用第三种方式完成。下边给出代码实现:#includeusing namespace std;#include原创 2016-10-03 20:17:37 · 1548 阅读 · 0 评论 -
【数据结构】AVL树
AVL树,是一棵平衡搜索二叉树,既满足搜索树的性质(见二叉搜索树的文章,链接:二叉搜索树),又满足平衡树的性质(左右子树的高度差不大于2)。在二叉搜索树中,我们知道要插入一个元素,必须将他插到合适的位置,但是在AVL树中,不仅要插入到合适的位置,还要保证插入该元素之后这棵树是平衡搜索二叉树。关于如何调整一棵二叉树为平衡二叉树,这里就涉及到四种旋转:左单旋,右单旋,左右双旋,右左原创 2016-10-26 22:42:37 · 714 阅读 · 1 评论 -
【数据结构】非递归遍历二叉树
由于递归时通过栈来实现的,虽然递归代码有时候看起来比较简单,然后递归太深就会造成栈溢出。所以我们可以通过栈来实现二叉树的非递归遍历。下边看解析:【先序遍历】下边看实现代码:void PreOrderTraverseNonR() { stack s; Node* cur = _root; if (cur == NULL) return; wh原创 2016-09-30 22:50:52 · 990 阅读 · 1 评论 -
【面试题】给40亿个无符号不重复且没排过序的数,查找一个数是否在这40亿个数之中
看到这样一道面试题,我们不由的想到前边学习过的哈希表,哈希表查找效率高,唯独就是 空间浪费有点大。而在这道题目之中,40亿个无符号数(表明最高位表示大小),几乎涵盖了整形里的所有的数(总共42亿9千多)。而42亿9千多的数全部放到内存大约需要4G*4 = 16G,加上操作系统,各种运行软件,我们普通的计算机是无法运行这42亿数字的,除非超级计算机。所以,按照将每个数字都占用一个整形空间的方式导入内存原创 2016-11-07 11:24:11 · 1960 阅读 · 0 评论 -
【数据结构】哈希表
哈希表(散列表),是通过关键字key而直接访问在内存存储位置的一种数据结构,它就是 以空间换取时间。通过多开辟几个空间,来实现查找的高效率。 对于哈希表,我们并不是很陌生:在c语言学习阶段,给定一个字符串,查找第一个只出现过一次的字符;在数据结构 矩阵的高效转置方法中,计算原矩阵中每一列中有效数字的个数;在文件压缩项目(之后给出分析总结)中,计算中文件中各个字符出现的次数。 对于构造哈希表,有以原创 2016-11-04 20:37:32 · 1083 阅读 · 0 评论 -
【数据结构】二叉树的递归实现
二叉树的概念,这里就不想多说了,但是你需要知道满二叉树,完全二叉树等等这些基本概念,下边进入正题。首先创建一棵二叉树,下边看代码:Node* _Create(T* a, size_t size,size_t& index,const T& invalid) { assert(a); Node* root = NULL; while (index < size && a[i原创 2016-09-28 22:32:38 · 477 阅读 · 0 评论