算法与数据结构

算法跟数据结构的入门

﹥>﹥吖頭↗ 提交于 2019-11-30 18:13:21
什么是算法   算法的五个特征:有穷性,确定性,可行性,有输入,有输出   算法的设计原则:正确性,可读性,健壮性bug/高效率与低存储。内存+cpu内存占用最小。   评价算法的两个重要指标:时间复杂度(运行一个程序花费的时间),空间复杂度(运行程序所需要的内存 OOM 一般就是找数组容器等)。     1.常数性时间复杂度0(1)      及运行代码:            2.线性性0(m)            线性性 O(m)            3.       对数性 nlog(n) 快速排序            4.           平方性            5.     时间复杂度优化标准就是:尽量往低的优化 , 一般在程序中找 for while 递归等就能大概算出时间复杂度 。     以上几个性能对比 :O(1)>O(n)>O(nlogn)>O(n^2) 什么是数据结构     数据结构是计算机存储、组织数据的方式,指相互之间存在一种或多种特定关系的数据元素的集合。通常情况下,精心选择的数据结构可以带来更高的运行或者存储效率。   基础数据结构     1.数组     元素之间可以快速的随机访问     每个元素都必须是连续的,当需要扩容时,就需要将已有的数据复制到已有的存储空间     ArrayList:使用最多的数据结构,访问快

索引数据结构 B+树等

人盡茶涼 提交于 2019-11-30 16:53:52
本文将详细介绍数据结构中的一些常用的搜索树结构,包括:B树、B-树、B+树、B*树;分别介绍这些树结构的定义、特征、搜索方法、性能等情况,最后给出了一个简要的总结。 一、 B 树 B树即二叉搜索树,它的特征是: 1.所有非叶子结点至多拥有两个儿子(Left和Right); 2.所有结点存储一个关键字; 3.非叶子结点的左指针指向小于其关键字的子树,右指针指向大于其关键字的子树; 一颗典型的B树图如下所示: B 树的搜索: 从根结点开始,如果查询的关键字与结点的关键字相等,那么就命中;否则,如果查询关键字比结点关键字小,就进入左儿子;如果比结点关键字大,就进入右儿子;如果左儿子或右儿子的指针为空,则报告找不到相应的关键字; B 树的性能: 如果B树的所有非叶子结点的左右子树的结点数目均保持差不多(平衡),那么B树的搜索性能逼近二分查找;但它比连续内存空间的二分查找的优点是,改变B树结构(插入与删除结点)不需要移动大段的内存数据,甚至通常是常数开销,如下图所示: 但B树在经过多次插入与删除后,有可能导致不同的结构,如下图: 右边也是一个B树,但它的搜索性能已经是线性的了;同样的关键字集合有可能导致不同的树结构索引;所以,使用B树还要考虑尽可能让B树保持左图的结构,和避免右图的结构,也就是所谓的“平衡”问题; 实际使用的B树都是在原B树的基础上加上平衡算法,即“平衡二叉树”

看数据结构写代码(33) 树与回溯法(一) 子集树

人盡茶涼 提交于 2019-11-30 16:38:46
回溯法 是 一种 在 穷举 中,裁剪 不满足 条件 的 分支,已达到 提高 效率的 方法。其基本原型 是 树的 先序遍历,从 树根 到 树叶的路径 是 问题的 一个 解。 回溯法的基本框架 = 确定 解空间 + 深度优先遍历 + 裁剪函数 + 确定结果函数 其中 解空间,分为 子集树 和 排序树。 具体 概念 详解:参考 点击打开链接 和 点击打开链接 递归算法通用 模板如下: 回溯法对解空间作 深度优先搜索 ,因此,在一般情况下用递归方法实现回溯法。 // 针对N叉树的递归回溯方法 void backtrack (int t) { if (t > n) { // 到达叶子结点,将结果输出 output (x); } else { // 遍历结点t的所有子结点 for (int i = f(n,t); i <= g(n,t); i ++ ) { x[t] = h[i]; // 如果不满足剪枝条件,则继续遍历 if (constraint (t) && bound (t)) backtrack (t + 1); } } } 下面的 三个例子 都是 根据 这个 模板 来 写的。 // Backtrack.cpp : 定义控制台应用程序的入口点。 // #include "stdafx.h" #include <cstring> #define SET_MAX_SIZE 1000

数据结构与算法-栈

余生颓废 提交于 2019-11-30 15:09:20
1.栈的原理 后进先出(LIFO-last in first out):最后插入的元素最先出来,是一种“操作受限”的线性表,只允许在端插入和删除数据 2.栈的实现 顺序栈:用数组实现,顺序栈需要动态扩容,在初始化时需要给定一个固定大小的数组,当栈大于固定大小时需要扩充数组的大小。 template<class T> class MyArrayStack { public: MyArrayStack(); ~MyArrayStack(); public: bool empty() const; void push(T const&); void pop(); T top() const; protected: T *m_pArrayData; int m_nSize; int m_nMaxSize; }; template<class T> MyArrayStack<T>::MyArrayStack(){ m_nSize = 0; m_nMaxSize = 2; m_pArrayData = new T[m_nMaxSize]; } template<class T> MyArrayStack<T>::~MyArrayStack(){ delete []m_pArrayData; m_pArrayData = NULL; } template<class T> bool

数据结构与算法-数组

生来就可爱ヽ(ⅴ<●) 提交于 2019-11-30 15:08:34
数组是由相同类型的元素(element)的集合所组成的数据结构,分配一块连续的内存来存储。利用元素的索引(index)可以计算出该元素对应的存储地址。(维基百科) 1. 存储结构   数组是线性表数据结构,定义数组时,系统会分配一份连续的内存空间来存储一组相同的类型的数据,如int num[n]; 2. 多维数组   数组定义为一维数组、二维数组、三维数组…n维数组,其格式可以写成int num[n][m]; 3. 查找、插入、删除时间复杂度   3.1 需要查找数组第K个数时,数组会根据下标来访问,查找的时间复杂度为O(1)   3.2 需要在数组的第K个数插入一个数Y,在有序数组的情况下,插入的时间复杂度为O(n) void ArrayAdd(int* pNum, int nCount, int nAddIndex, int nAddNum) { int nEnd = nAddIndex-1; for(int nIndex=nCount-1; nIndex>=nEnd; nIndex—) { pNum[nIndex+1] = pNum[nIndex]; } pNum[nEnd] = nAddNum; }   3.3 需要删除数组的第K个数,时间复杂度为O(n) void ArrayDelete(int* pNum, int nCount, int nDeleteIndex) {

图解数据结构-树及树的遍历

末鹿安然 提交于 2019-11-30 14:58:14
当你第一次学习编码时,大部分人都是将数组作为主要数据结构来学习。 之后,你将会学习到哈希表。如果你是计算机专业的,你肯定需要选修一门数据结构的课程。上课时,你又会学习到链表,队列和栈等数据结构。这些都被统称为线性的数据结构,因为它们在逻辑上都有起点和终点。 当你开始学习树和图的数据结构时,你会觉得它是如此的混乱。因为它的存储方式不是线性的,它们都有自己特定的方式存储数据。 定义 树是众所周知的非线性数据结构。它们不以线性方式存储数据。他们按层次组织数据。 树的定义 树(Tree)是n(n>=0)个结点的有限集。n=0时称为空树。 在任意一颗非空树中: (1) 有且仅有一个 特定的称为根(Root)的结点。 (2)当n>1时,其余结点可分为m(m>0)个 互不相交的有限集 T1、T2、.....、Tm,其中每一个集合本身又是一棵树,并且称为根的子树(SubTree)。 下图就符合树的定义: 其中根结点A有两个子树: 我们硬盘的文件系统就是很经典的树形结构。 “树”它具有以下的特点: ①每个节点有零个或多个子节点; ②没有父节点的节点称为根节点; ③每一个非根节点有且只有一个父节点; ④除了根节点外,每个子节点可以分为多个不相交的子树; 树( tree )是被称为结点( node )的实体的集合。结点通过边( edge )连接。每个结点都包含值或数据( value/date )

Java数据结构与算法(1):线性表

痞子三分冷 提交于 2019-11-30 13:38:48
线性表是一种简单的数据类型,它是具有相同类型的n个数据元素组成的有限序列。形如如A 0 ,A 1 ,...,A n-1 。大小为0的表为空表,称A i 后继A i-1 ,并称A i-1 前驱A i 。 printList打印出表元素,makeEmpty置空表,find返回某一项首次出现的位置,insert和remove一般是从表的某个位置插入和删除某个元素;而findKth则返回某个位置上的元素,next和previous会取一个位置作为参数返回前驱元和后继元的值。 表的数组实现 对表的所有操作都可以通过数组实现。数组的存储示意图如下: 这种存储结构的特点是: 数据是连续的,随机访问速度快 。printList以线性时间执行,findKth操作则话费常数时间。对于插入和删除来说效率是比较低下的,最坏情况下,在位置0的插入需要将所有元素向后移动一个位置。 基于数组的链表实现: public class MyArrayList<T> implements Iterable<T>{ private static final int DEFAULT_CAPACITY=10; private int size; private T[] items; public MyArrayList() { doClear(); } public void clear() { doClear(); }

数据结构——KMP(串)

喜夏-厌秋 提交于 2019-11-30 13:31:48
KMP一个非常经典的字符串模式匹配算法   先来说说 KMP 的历史吧。 一、背景      KMP算法是一种改进的字符串匹配算法,由D.E.Knuth,J.H.Morris和V.R.Pratt提出的,因此人们称它为克努特—莫里斯—普拉特操作(简称KMP算法)。KMP算法的核心是利用匹配失败后的信息,尽量减少模式串与主串的匹配次数以达到快速匹配的目的。具体实现就是通过一个next()函数实现,函数本身包含了模式串的局部匹配信息。KMP算法的时间复杂度度O(m+n)。KMP也可以处理最重复长子串问题,最长子串问题……这里挂一道最简单的题leetcode的 实现 strStr() ,大家看完可以去试一试。 补充说明:    强调两个概念: 真前缀 ,真后缀     如图所示,所谓的真前缀,就是在指在除了自身之外的全部字符串的头部顺序组合;而"真后最",就是指在除自身之外的一个字符串的全部尾串的顺序组合 。与后缀、前缀不同:              真前/后缀不包含自身字符!!! 二、朴素字符串匹配算法   其实就是我们最开始的时候写的字符串匹配,就是两个字符串逐一匹配。不作详细介绍,代码如下 /** * @brief 朴素字符串匹配 * @note * @param MainString: 主串 * @param Pattern: 模式串 * @retval */ int

细谈Redis五大数据类型

对着背影说爱祢 提交于 2019-11-30 13:22:08
文章原创于公众号:程序猿周先森。本平台不定时更新,喜欢我的文章,欢迎关注我的微信公众号。 上一篇文章有提到,Redis中使用最频繁的有5种数据类型:String、List、Hash、Set、SortSet。上一篇文章只是单纯介绍了下这5种数据类型使用到的指令以及常用场景,本篇文章会谈谈5种数据类型的底层数据结构以及各自常用的操作命令来分别进行解析。Redis作为目前最流行的Key-Value型内存数据库,不仅数据库操作在内存中进行,并且可定期的将数据持久化到磁盘中,所以性能相对普通数据库高很多,而在Redis中,每个Value实际上都是以一个redisObject结构来表示: typedef struct redisObject{ unsigned type:4; unsigned encoding:4; void *ptr; int refCount; unsigned lru: } 我们可以看看这几个参数分别的含义: type:对象的数据类型,一般情况就是5大数据类型。 encode:redisObject对象底层编码实现,主要编码类型有简单动态字符串,链表,字典,跳跃表,整数集合及压缩列表。 *ptr:指向底层实现数据结构的指针。 refCount:计数器,当引用计数值为0将会释放对象。 lru:最后一次访问本对象的时间。 String数据类型 String 数据结构是简单的

数据结构

佐手、 提交于 2019-11-30 09:38:48
1. 几个景点算法: 1.  修路问题:最小生成树(加权值)+ 普利姆 2. 最短路径:图+弗洛伊德算法 3. 汉诺塔: 分支的算法 4. 八皇后:回朔法、 5. 丢手帕 : 约瑟夫问题 2. 线性结构 与非线性结构 1.线性结构 :数据元素之间存在一对一的线性关系 顺序存储结构 , 链式存储结构 (数组,队列,链表和栈) 2 . 非线性结构:(二维数组,多维数组,广义表,树结构,图结构) 3. 稀疏数组 因为该数组中记录了很多值是默认值0,记录了很多没有意义的数据 -》 稀疏数组 代码实现 public class XiShuJuZhen { //创建一个原始的二维数组 11*11 @Test public void testArray() { int[][] charArray = new int[11][11]; //0表示没有棋子,1 表示黑子 2表示蓝子 charArray[1][2] = 1; charArray[2][3] = 2; charArray[4][5] = 2; System.out.println("输出原始的二维数组"); for (int[] is : charArray) { for (int is2 : is) { System.out.print("\t"+is2); } System.out.println(); } /* *