数据结构
文章平均质量分 77
午饭要阳光
热爱编程
展开
-
跳表分析与实现
一、什么是跳表 跳表全称叫做跳跃表,简称跳表。跳表是一个随机化的数据结构,可以被看做二叉树的一个变种,它在性能上和红黑树,AVL树不相上下,但是跳表的原理非常简单,目前在Redis和LeveIDB中都有用到。 在对有序顺序表进行搜索时,使用二分查找时间复杂度是O(logn),但是有序顺序表的插入和删除却是O(n)的算法。 在对有序链表进行搜索时,时间复原创 2017-07-11 21:54:08 · 6772 阅读 · 0 评论 -
排序——Quick
一、快速排序的过程快速排序: 快速排序是一种划分交换的方法,它采用分治法进行排序。其基本思想是取待排序元素序列中的某个元素作为基准值,按照这个元素的大小,将整个元素序列划分成两个左右两个子序列,使得左子序列的值都比这个元素小,右子序列中的值都比这个元素值要大于或等于,基准元素值则排在这两个序列中间,然后再对这两个子序列进行同样的方法,直到所有元素都排在相应的位置(即序列中只有一个元素或者原创 2016-11-23 13:12:28 · 1479 阅读 · 0 评论 -
排序——Merge
归并排序是一种基于分治法的一种排序方法。它将要排序的序列分成两个长度相等的子序列,为每一个子序列进行排序,然后再将子序列合并成一个有序的序列。实现:void _MergeSort(int *a,int begin,int end,int *tmp){ int mid = ((begin^end) >> 1) + (begin&end); if (m原创 2016-11-23 18:34:18 · 1049 阅读 · 0 评论 -
计数排序
计数排序主要思想: 给定一组要排序的序列,找出这组序列中的最大值,然后开辟一个最大值加1大小的数组,将这个数组里面的元素全部置零,然后用这个数组统计出要排序的序列中各个元素出现的次数。等到统计完成的时候,排序就已经完成了。例: 计数排序是一种非比较的排序方法,它的时间复杂度是O(N+K),空间复杂度是0(K),其中K是要排序的数组的范围。可以看出计数排序是一种以原创 2016-11-25 20:23:05 · 749 阅读 · 0 评论 -
基数排序
基数排序的主要思想: 基数排序又称"桶子法",他从低位开始将待排序的数按照这一位的值放到相应的编号为0到9的桶中。等到低位排完之后得到一个序列,再将这个序列按照次低位的大小进入相应的桶中。以此类推,直到将所有的位都排完之后,这组数就已经有序了。例: 基数排序是一种非比较排序,它的时间复杂度是O(N*digit),其中digit是这组待排序中的最大的数的数量级,它原创 2016-11-25 23:10:48 · 960 阅读 · 0 评论 -
并查集
在一个有N个元素的集合问题中,我们通常是让每个元素构成一个单元素的集合,然后按一定顺序将属于同一集合的元素进行合并。在此过程中要不断的查询某个元素归属于哪个集合,适合于描述这类问题的抽象数据类型我们称之为并查集。例: 已知有n个人和m对好友关系,并且这些好友关系存储在r里面,如果两个人是直接或间接的好友,则认为他们属于同一个朋友圈。 n=5,m=3,r={{1,2},{2,3},{4原创 2016-11-26 13:05:08 · 785 阅读 · 0 评论 -
海量数据排序
排序分为内部排序和外部排序两大类,若要排序的元素很多,整个序列的排序过程不可能在内存中完成,则此类排序就称为外部排序。针对外部排序这种问题,下面我们来介绍一种方法。 由于要排序的数据量很大,不可能一次性加载到内存,所以我们就采取"分而治之"的方法。先将大文件分割成若干的小文件,使得小文件中的数据能够完全加载到内存。然后分别将每个小文件加载到内存并使用快速排序使之有序,将有序的序列再放回到小文原创 2016-11-27 13:13:24 · 2277 阅读 · 0 评论 -
B+树&B*树简介
一、B+树B+树是B树的变体,也是一种多路搜索树,它的定义如下:1、根节点要么是叶子结点,要么至少具有两个孩子2、一棵M路的B树M至少大于2,每个非根结点的孩子的个数有[M/2,M]3、所有叶子结点都在同一层4、非根结点的子树指针与关键字的个数是相等的,也就是说孩子的个数与关键字的个数是相等的。5、为所有孩子结点都增加了一个链指针,可以按照关键码排序的次序遍历全部记录。原创 2016-11-27 19:23:16 · 1010 阅读 · 0 评论 -
图
图是一种非线性数据结构,由顶点集合(vertex)和边的集合组成的一种数据结构。Graph=(V,E);V={x|x是顶点集合}; V是顶点的集合E={|x,y属于V}; E是边的集合图分为无向图和有向图。1、无向图2、有向图完全图:在由n个顶点组成的无向图中,若有N(N-1)/2条边,则成为无向完全图。(也就是说任意两个点都有路原创 2016-12-02 21:17:27 · 1807 阅读 · 0 评论 -
时间复杂度&空间复杂度分析
时间复杂度: 一般情况下,算法中基本操作重复执行的次数是问题规模n的某个函数f(n),进而分析f(n)随n的变化情况并确定T(n)的数量级。这里用"O"来表示数量级,给出算法的时间复杂度。 T(n)=O(f(n)); 它表示随着问题规模的n的增大,算法的执行时间的增长率和f(n)的增长率相同,这称作算法的渐进时间复杂度,简称时间复杂度。而我们原创 2016-09-06 20:25:41 · 26863 阅读 · 10 评论 -
走出这个迷宫
求解迷宫路径是一个典型的问题,通常我们都是用 栈+回溯法+试探法 来解决这个问题。下面为大家介绍一下怎样用栈怎样找出迷宫的路径 。在实现代码之前我们先来分下一下:1、迷宫地图的设置 我们可以把迷宫地图存到文本里面,当需要的时候我们在重文本里面读取。因为迷宫的大小不确定,所以我们要动态开辟二维数组来存放地图。如图:在第一行我们要存迷宫的 行 列 入口的横坐原创 2016-09-09 18:28:37 · 1503 阅读 · 0 评论 -
迷宫路径&广度优先求解&深度优先求解&迷宫游戏
求解迷宫的通道是数据结构中一个很经典的问题,解决这个问题大概有两种思路,一种是深度优先,一种是广度优先。深度优先是只要找到一条通道就可以了,而广度优先则是寻找最短的路径。下面我们来对这两种思想做一个剖析。深度优先: 如果要用一句俗语来解释深度优先的话,那么一定是“不撞南墙不回头”。深度优先的重点于“深”,找到一条路就一头扎下去,原创 2016-09-13 18:57:09 · 3478 阅读 · 0 评论 -
栈&&队列面试题
问题:1. 实现一个栈,要求实现Push(出栈)、Pop(入栈)、Min(返回最小值的操作)的时间复杂度为O(1)2. 使用两个栈实现一个队列3. 使用两个队列实现一个栈4. 判断元素出栈、入栈顺序的合法性。如:入栈的序列(1, 2, 3, 4, 5),出栈序列为(4, 5, 3, 2, 1)是合法序列,入栈的序列(1, 2, 3, 4, 5),出栈序列为(1, 5原创 2016-09-15 17:07:05 · 1742 阅读 · 3 评论 -
稀疏矩阵的快速转置
为了节省空间,对于稀疏矩阵我们通常要压缩存储。具体方法是用一个三元数组按照行优先的方式保存每一个有效值的行、列、值。三原数组的类型:templatestruct ThirdArray{ size_t _x; //行 size_t _y; //列 T _value; Thi原创 2016-09-22 08:01:34 · 4481 阅读 · 0 评论 -
线索化二叉树
线索化二叉树为我们提供了一种不需要递归和借助栈就能遍历一颗二叉树的方法,如果将二叉树写成STL的形式,那么线索化就可以为之提供迭代器,这也是线索化二叉树的最主要的用法。线索化二叉树有三种方式,前序线索化,中序线索化和后序线索化。一般只要掌握前序线索化和中序线索化就可以了。后序线索化遍历的时候要借助于三叉链表或者FindParent(寻找父亲结点的函数)。 将一颗搜索二叉树转换成有序双向链表原创 2016-11-20 22:26:03 · 897 阅读 · 0 评论 -
二叉树经典面试题
以下二叉树的结点类型如下:templatestruct BinaryTreeNode{ T _data; BinaryTreeNode *_left; BinaryTreeNode *_right; BinaryTreeNode(const T& data = T()) :_data(data) , _left(NULL) , _right(NULL){}};原创 2016-11-18 20:18:21 · 2272 阅读 · 0 评论 -
LRU缓存策略设计
一、什么是LRU缓存策略 LRU(Least Recently Used)近期最少使用算法。它的原理就是,缓存一定量的数据,当缓存数量超过设置的阈值时就删除一部分旧的数据。 那么我们怎样判定旧数据呢???根据局部性原理,距离当前最久没有被访问过的数据应该被淘汰。二、LRU缓存策略实现原理 1、使用双向链表记录数据的被使用的时间 因为我们要删除最久没有被访问的数据原创 2017-06-02 11:53:28 · 1867 阅读 · 2 评论 -
AVL树
AVL树又称作高度平衡二叉树,它实际上是一种优化了的搜索二叉树。我们知道,由于二叉搜索树存在缺陷,有可能会退化成单链表,这样的话搜索的效率就降低了。为了将二叉搜索树的效率控制在O(logN)的级别,所以我们要给二叉搜索树加上一些条件,使得二叉搜索树高度平衡,时间复杂度为O(logN)。概念:1、首先AVL树是一颗二叉搜索树。2、其次它的左子树和右子树都是AVL树。3、它的左原创 2016-10-26 18:41:10 · 1659 阅读 · 0 评论 -
数据结构知识框图
数据结构知识框图:原创 2017-03-06 17:26:13 · 3319 阅读 · 4 评论 -
huffman算法---文件压缩
利用huffman编码的思想对文件进行压缩,主要原理是通过huffman编码来重新表示字符,使得出现频率高的字符编码短,出现少的字符编码长。整体下来的话,所需的总的bit位是减少的。但是要注意当大部分字符出现的频率都差不多时,huffman压缩的压缩效率会很低。一、利用huffman树对文件进行压缩主要分为以下两部分:压缩:1、统计字符出现的次数 因为文件的底层原创 2016-10-30 23:04:53 · 2324 阅读 · 0 评论 -
如何设计一个简单内存池
什么是内存池??? 通常我们用new或malloc来分配内存的话,由于申请的大小不确定,所以当频繁的使用时会造成内存碎片和效率的降低。为了克服这种问题我们提出了内存池的概念。内存池是一种内存分配方式。内存池的优点就是可以有效的减少内存碎片化,分配内存更快速,减少内存泄漏等优点。 内存池是在真正使用内存之前,先申请分配一个大的内存块留作备用。当真正需要使用内存的时候,就从内存池中分配一块原创 2016-12-04 20:59:39 · 6519 阅读 · 4 评论 -
揭秘——STL空间配置器
为什么要有空间配置器呢?这主要是从两个方面来考虑的。1、小块内存带来的内存碎片问题 单从分配的角度来看。由于频繁分配、释放小块内存容易在堆中造成外碎片(极端情况下就是堆中空闲的内存总量满足一个请求,但是这些空闲的块都不连续,导致任何一个单独的空闲的块都无法满足这个请求)。2、小块内存频繁申请释放带来的性能问题。 关于性能这个问题要是再深究起来还是比较原创 2016-12-07 23:07:10 · 5316 阅读 · 0 评论 -
对一个数组,按照给定的下标进行排序,仅使用两两交换的方式
对一个数组,按照给定的下标进行排序,仅使用两两交换的方式,空间复杂度O(1)。例:原数组 A B C D E,现给定新位置为3 0 1 4 2 排序后的结果是D A B E C 初次见到这道题的时候,着实让我头疼了一把,最后经人指点,自己也就有了一个大致的思路,下面将这道题的解法做一下总结。分析:这道题要用到挖洞法的思想,不过要在挖洞法的基础上再做一些改进。 例1:原数组 A B C D原创 2016-12-17 15:11:50 · 5010 阅读 · 2 评论 -
BitMap(位图)
1K=1024byte 1M=1024K=1024*1024byte(约100万个字节) 1G=1024M=1024*1024K=1024*1024*1024byte(约10亿个字节) 假设现在有40亿个不重复且无序的无符号整数,现在给你一个整数让你快速判断它是否在这40亿个数里面???(假设现在只有4G的内存) 这道题的解决办法很简单,就是用这个数到这40个数中去原创 2016-11-08 13:50:56 · 1564 阅读 · 0 评论 -
BloomFilter(布隆过滤器)
bloomfilter(布隆过滤器): 要判断一个元素是否在一个集合中出现,一般情况下就是将这个集合的元素保存下来,然后再到这个集合中一一比较即可,但是如果这个集合中的元素很多的话,不仅需要的内存很大,而且查找起来也比较慢。 为了提高效率我们可以采用hash表,并且将集合中的元素都映射到bitmap中的一个位上,这样的话就会节省空间和查找的时间。但是由于哈希冲突的原因,我们有可原创 2016-11-08 14:29:58 · 1806 阅读 · 0 评论 -
大数据——面试题总结(1)
1、给出一个超过100G的log file,log中存着ip地址,设计算法找到出现次数最多的ip地址?分析: 由于文件超过100G,所以我们必须先对文件进行切分,然后再利用数据结构的知识求解。关键是如何切分效率最高???解决方法: 我们可以使用哈希切分,将同一个ip都分割到同一个文件中,注意同一个ip经过同一个散列函数 一定会进入到同一个文件中,然后再统计每一个原创 2016-11-09 15:27:52 · 2999 阅读 · 0 评论 -
浅析B-树
B树是一种适合与外查找的的搜索树,他是一种平衡的多叉树。在B树的每个结点中包含一组指针recptr[M]指向实际记录的存放地址。key[i]与recptr[i]形成一个索引项,通过key[i]可以找到某个记录的存储地址recptr[i]。M阶的B树具有以下特点:1、根节点要么是叶子结点,要么具有两个孩子。2、非根结点(叶结点除外)都具有[M/2,M]个孩子。3、非根结点都具原创 2016-11-12 15:15:09 · 1551 阅读 · 0 评论 -
set与map用法简介
在介绍容器之前,我们先来介绍一下pair,pair是一种模板类型,每个pair可以存储两个值,这两个值的类型可以是任何类型的。它定义在#include 中。可以看到,pair的两个成员分别是first和second。一、set(集合): set是一种key结构,它的元素就是它的键值,set不允许有两个相同的键值,set中的所有元素的键值都会自动被排序。set和原创 2016-11-13 18:58:37 · 1122 阅读 · 1 评论 -
排序——Shell
希尔排序又称为缩小增量排序,它是插入排序的一种变形。希尔排序: 设待排序元素有n个,首先取一个整数gap例如:对{ 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 }进行升序排列。具体代码实现:void ShellSort(int *a, int len) //插入排序的变形,通过预排序使得元素大致有序,再通过插入排序使原创 2016-11-17 13:34:23 · 1349 阅读 · 1 评论 -
二叉树的递归实现
二叉树是一种非线性结构,用途非常广泛。二叉树它的每一个结点的度都不大于2,所以一般用二叉链表来实现二叉树。二叉链表: 二叉树可以分为根结点和左子树,右子树。左子树和右子树依旧可以这样划分。所以二叉树是典型的递归结构,所以用递归来实现二叉树的逻辑是非常简单的,只要不断的对二叉树进行划分即可。#pragma once #include#include#incl原创 2016-09-25 10:48:03 · 1129 阅读 · 0 评论 -
非递归创建二叉树&非递归访问二叉树
由于递归创建二叉树的效率太低,所以我们需要采取非递归的方式来创建和访问一颗二叉树。因为栈和递归的原理相同,所以任何递归方法都可以借助栈转化成非递归的方法。下面我们使用非递归的方式 ,采用先序创建来创建一颗二叉树。并且提供前、中、后三种非递归的遍历方式。#pragma once #include#includeusing namespace std;templatestruc原创 2016-09-26 18:01:38 · 1819 阅读 · 0 评论 -
二叉树的算法实现
#ifndef __TREE_H__ //条件编译#define __TREE_H__#define _CRT_SECURE_NO_WARNINGS 1#include#include#define MAXSIZE 1000 typedef int ElemType;typed原创 2016-05-24 21:25:29 · 1610 阅读 · 1 评论 -
顺序表基本算法
#ifndef __SEQLIST_H__#define __SEQLIST_H__#define _CRT_SECURE_NO_WARNINGS 1#include#include#include#include#define MAX 100typedef int DataType;typedef struct Seqlist{ DataType Data[MAX];原创 2016-05-25 23:56:15 · 6031 阅读 · 0 评论 -
动态顺序表算法
#ifndef __SEQLIST_D_H__ //条件编译#define __SEQLIST_D_H__#define _CRT_SECURE_NO_WARNINGS 1#include#include#include#define INIT_SIZE 2#define ADD_SIZE 3typedef int DataT原创 2016-05-31 20:57:12 · 1699 阅读 · 0 评论 -
排序--Bubble的三种优化
BubbleSort 冒泡排序是许多人接触的第一种排序方式,由于这种方式比较简单,所以大部分人也没有深入研究,所以写出的代码是这样的:void BubbleSort(int *arr, int len){ assert(arr); int i = 0; int j = 0; int tmp = 0; for (i = 0; i < len - 1; i++) {原创 2016-06-01 17:35:07 · 4231 阅读 · 2 评论 -
排序--InsertSort优化
InsertSort:(以升序为例)插入排序的基本思想是: 每次将一个待排的记录,按照其关键字的大小,插入到前面已经排好序的有序区中适当的位置,直到全部记录插入完毕为止。 假设待排序的记录存放在数组R[0..n]中,初始时R[0]是一个有序区,R[1..n]是无序区,从i=1开始,依次将R[i]插入到有序区R[0..i-1]中,生成一个包含n个记录的有序区。原创 2016-06-03 16:58:59 · 3345 阅读 · 0 评论 -
排序--SelectSort优化
SelectSort:(以升序为例) 选择排序的基本思想:初始时,有序区为0,每一趟在无序区中选出一个关键字最小的元素,然后与无序区第一个元素交换,然后无序区减1,有序区加1,直到记录全部排完。 直接选择排序:第一趟排序在R[0..n]中选出一个关键字最小的与R[0]交换,第二趟在R[1..n]中选择一个最小的与R[1]进行交换,以此类推直到无序区的记录只剩一个时排序完成。原创 2016-06-03 19:21:05 · 3060 阅读 · 2 评论 -
链表--基本算法
#ifndef __LINKLIST_H__#define __LINKLIST_H__#define _CRT_SECURE_NO_WARNINGS 1#include#include#includetypedef int DataType;typedef struct LinkNode{ DataType data; struct LinkNode *next;}Link原创 2016-06-05 00:05:50 · 5494 阅读 · 0 评论 -
单链表实现
单链表:1、逻辑上连续,位置上可以不连续的存储方式。2、单链表由无数个结点组成,每个结点由数据段和指针域组成,数据段存储数据,指针域存储后继的地址。3、每个结点最多有一个前继和一个后继。4、其中第一个结点没有前继,所以我们通常建立一个头结点来保存他的位置,其中头结点的数据段我们不关注。5、最后一个结点没有后继,所以我们将最后一个结点的指针域赋为NULL.//函数原创 2016-05-12 23:29:57 · 733 阅读 · 0 评论 -
顺序表的实现
顺序表:逻辑上连续,物理结构上也连续实现一个具有“增、删(根据位置删除,根据元素删除)、查、初始化、输入、打印”等简单功能的顺序表:源码:头文件部分("sequence.h"):#define _CRT_SECURE_NO_WARNINGS 1#include #include#define MAXSIZE 20typedef int ElemType;typ原创 2016-05-12 23:30:58 · 596 阅读 · 0 评论