时间复杂度

数组和链表的区别

丶灬走出姿态 提交于 2019-11-29 18:48:07
数组: 数组是将元素在内存中连续存放,由于每个元素占用内存 相同,可以通过下标迅速访问数组中任何元素。但是如果要在数组中增加一个元素,需要移动大量元素,在内存中空出一个元素的空间,然后将要增加的元素放在其 中。同样的道理,如果想删除一个元素,同样需要移动大量元素去填掉被移动的元素。如果应用需要快速访问数据,很少或不插入和删除元素,就应该用数组。 链表: 链表恰好相反,链表中的元素在内存中不是顺序存储的,而是通过存在元素中的指针联系到一起。比如:上一个元素有个指针指到下一个元素,以此类推,直到最后 一个元素。如果要访问链表中一个元素,需要从第一个元素开始,一直找到需要的元素位置。但是增加和删除一个元素对于链表数据结构就非常简单了,只要修改元 素中的指针就可以了。如果应用需要经常插入和删除元素你就需要用链表数据结构了。 C++语言中可以用数组处理一组数据类型相同的数据, 但不允许动态定义数组的大小,即在使用数组之前必须确定数组的大小。而在实际应用中,用户使用数组之前有时无法准确确定数组的大小,只能将数组定义成足够 大小,这样数组中有些空间可能不被使用,从而造成内存空间的浪费。链表是一种常见的数据组织形式,它采用动态分配内存的形式实现。需要时可以用new分配 内存空间,不需要时用delete将已分配的空间释放,不会造成内存空间的浪费。   (1) 从逻辑结构角度来看    a,

红黑树存在的合理性

我只是一个虾纸丫 提交于 2019-11-29 18:18:43
写在前面   主要描述为什么有了二叉查找树/平衡树还需要红黑树 1、二叉查找树的缺点   二叉查找树,相信大家都接触过,二叉查找树的特点就是左子树的节点值比父亲节点小,而右子树的节点值比父亲节点大,如图   基于二叉查找树的这种特点,我们在查找某个节点的时候,可以采取类似于二分查找的思想,快速找到某个节点。n 个节点的二叉查找树,正常的情况下,查找的时间复杂度为 O(logn)。   之所以说是正常情况下,是因为二叉查找树有可能出现一种极端的情况,例如    这种情况也是满足二叉查找树的条件,然而,此时的二叉查找树已经近似退化为一条链表,这样的二叉查找树的查找时间复杂度顿时变成了 O(n),可想而知,我们必须不能让这种情况发生,为了解决这个问题,于是我们引申出了平衡二叉树。 2、平衡二叉树   平衡二叉树就是为了解决二叉查找树退化成一颗链表而诞生了,平衡树具有如下特点   1、具有二叉查找树的全部特性。   2、每个节点的左子树和右子树的高度差至多等于1。   例如:图一就是一颗平衡树了,而图二则不是(节点右边标的是这个节点的高度)   对于图二,因为节点9的左孩子高度为2,而右孩子高度为0。他们之间的差值超过1了。   平衡树基于这种特点就可以保证不会出现大量节点偏向于一边的情况了。关于平衡树如何构建、插入、删除、左旋、右旋等操作这里不在说明,具体可以看我之前写的一篇文章:

算法和算法评价

自作多情 提交于 2019-11-29 18:14:16
算法的基本概念 算法: 对特定问题求解步骤的一种描述,它是指令的有限序列,其中的每条指令表示一个或多个操作。 根据以上定义,可以知道,算法一定是可以解决特定问题的,其次,它是有限的,然后,每一个指令都表示特定的操作。于是可以知道算法的五个特性: 有穷性: 一个算法必须在执行有穷步之后结束,且每一步都必须在有穷时间内完成。如果有类似无限循环的语句,那么就不能称之为算法。 可行性: 一个算法是可行的,即算法中描述的操作都是可以通过已经实现的基本运算执行有限次来实现的。每一步操作都是可以实现的才能称之为算法。 确定性: 算法中每条指令、每条语句必须有确切的含义,相同的输入必须得出到相同的输出,不能产生二义性。 输入: 一个算法必须有零个或多个输入。 输出: 一个算法必须有一个或多个输出。 算法为什么是有穷的?在操作系统中使用了很多无穷的代码语句,它们也是非常有用的,它们不是算法,那它们又是什么?对此,引入一个 程序 的概念,什么是算法,什么又是程序 根据上面的算法的定义,可以知道,算法是解决问题的一种方法或一个过程,例如如何将输入转换成输出。一个问题可以有很多不同的算法。而程序是某种程序设计语言对算法的具体实现。我们可以用 C 语言来编写,也可以用 Python 语言来编写,只要是在计算机内部运行的程序设计语言都可以。这是对算法和程序的简单描述。我们发现,算法更像一个解决问题的 “指导者

Redis五大数据类型详解

别来无恙 提交于 2019-11-29 16:44:39
关于Redis的五大数据类型,它们分别为:String、List、Hash、Set、SortSet。本文将会从它的 底层数据结构 、 常用操作命令 、一些 特点 和 实际应用 这几个方面进行解析。对于数据结构的解析,本文只会从大的方面来解析,不会介绍详细的代码实现。 String 1.实现结构   String是Redis中最常用的一种数据类型,也是Redis中最简单的一种数据类型。首先,表面上它是字符串,但其实他可以灵活的表示 字符串、整数、浮点数 3种值。Redis会自动的识别这3种值。那么,String的底层数据机构又是怎样的呢?由于Redis是使用c语言实现的,而c语言中没有String这一数据类型,那么就需要自己实现一个类似于String的 结构体 。它的名字就叫做SDS(simple dynamic string),下面是它的代码结构。 1 typedef struct sdshdr { 2 // buf中已经占用的字符长度 3 unsigned int len; 4 // buf中剩余可用的字符长度 5 unsigned int free; 6 // 数据空间 7 char buf[]; 8 } 如果有了解过Java集合框架类的朋友都知道,这种结构与集合中 动态数组结构 类似,那么就会涉及到一系列的扩容判断和操作,但这些具体的做法在这里不深入讲解

数据结构----二叉搜索树

爱⌒轻易说出口 提交于 2019-11-29 16:34:00
在数据结构中,二叉树是一种比较常见的树结构。在有的应用场景下,为什么要使用二查搜索树呢?使用二查搜索树可以给我们带来什么好处呢? 比如我们做查询操作时,数组的查询插入或者删除的最坏的时间复杂度是O(n) 当我们把这个数组进行排序以后,查询的最坏时间复杂度为o(log n),但是插入和删除元素的时间复杂度依然没有发生变化。 二叉搜素树的查询插入和删除的最坏时间复杂度都为o(log n),所以使用二叉搜索树可以大大的提高效率。 二叉搜索树服从以下的规则: 任意一个节点的值都大于左子树节点的值 任意一个节点的值都小于右子树节点的值 每个节点的左右子树依然是一颗二叉搜索树 package com.BinarySearchTree; import java.util.ArrayList; public class BinarySearchTree { public static void main(String[] args) { BinarySearchTree binarySearchTree = new BinarySearchTree(); binarySearchTree.add(7); binarySearchTree.add(4); binarySearchTree.add(9); binarySearchTree.add(2); binarySearchTree.add(5)

算法--入门

拜拜、爱过 提交于 2019-11-29 16:07:51
什么是算法? 算法是解决问题方案准确而完整的描述,是一系列解决问题的清晰指令,算法代表着的是用系统的方法描述解决问题的策略机制。也就是,对一定范围内的规范输入,在有限的时间内获得所要求的输出。如果一个算法有缺陷,或者不适合这个问题。那么这个算法将不能解决这个问题。不同的算法可以在不同的时间空间或者效率来完成未完成的任务。一个算法的优劣可以用 时间复杂度和空间复杂度衡量。 算法的指令指令描述的是一个计算,当运行时能从一个初始状态和初始输入开始,经过一系列的有限清晰定义状态,最终产生输出并停止一个状态。一个状态到另一个状态的转移不一定是确定的。随机算法在内的一些算法,包含了一些随即输入。 一个算法应该有五个特征 : 有穷性: 必须在执行有限的几个步骤后结束。 确切性: 算法的每一个步骤必须明确的定义。 输入项: 一个算法有0个或者多个输入,以刻画运算对象的初始情况,所谓的0个输入是指算法本身的初始条件; 输出项: 一个算法有一个或多个输出,以反映对输入数据加工后的结果。没有输出 算法毫无意义。 可行性: 算法的任何执行计算步骤都可以分解为可执行的操作步骤,即每一个计算都可以在有限的时间完成(也称为有效性)   算法的评定: 同一个问题可以用不同的算法解决,算法的质量优劣影响算法乃至程序的效率。算法分析的目的在于找到合适的算法。一个算法的评价主要有时间复杂度和空间复杂度来考虑。 stop

视频笔记

佐手、 提交于 2019-11-29 16:07:33
(1)算法与数据结构: 任务的安排,不要先入先出。采用优先队列 加密货币,区块链。 必要条: 算法与数据及结构。 算法和数据结构是有用和有趣的。 Binary Tree 链表和数结合区块链。 (2)如何事半功倍的学习算法 《outliers》 chunk it up 切碎成知识点 Deliberate practicing 刻意练习 Feedback 反馈 星际争霸: 控兵 运营 Sorting Link_list list spanning tree Tree_Graph Stack Hashing Abstrack_data_type{ stack{Vector}; Queue{Linked List, Priority Queue{ Heap } }; SetP{Hash Set, Tree Set } Map{ Hash Map, Tree Map } } Data struct Aglum 刻意练习: Feedback 反馈: 主动反馈, 被动反馈。算法和面试题。 (03)如何计算算法的复杂度 Algorithm 时间复杂度,空间复杂度。 Big O notation O(1): 常数级 O(N): for循环 O(N^2):for嵌套 O(log(n)): for(int i=0;i<n;i = i*2) O(k^N): for(int i=0; i<math.pow

数据结构与算法之排序详解 一点课堂(多岸学院)

时光毁灭记忆、已成空白 提交于 2019-11-29 15:20:18
通过前面的知识,我们已经知道,有序的数据在查找时有极大的性能提升。很多查找都基于有序数据,但并不是所有的结构都能像二叉排序树一样,在插入数据时就已经排好序,很多时候往往是无序的数据,需要我们使用时再进行排序,这就意味着我们需要寻找高效率的排序算法。接下来,我们对当下使用较为普遍的几个算法逐一进行分析。这里推荐一个可以查看算法运行动态过程的网站,加深对算法原理的理解。 基础知识 排序定义 假设含有n个记录的序列为{r1. r2, ..., rn},其相应的关键字分别为{k1, k2, ..., kn},需确定1, 2, ..., n的一种排列p1, p2, ..., pn,使其相应的关键字满足kp1≤kp2≤...≤kpn(非递减或非递增) 关系,即使得序列成为一个按关键字有序的序列{rp1, rp2, ..., rpn} , 这样的操作就称为排序。 稳定性 假设ki=kj( 1≤i≤n, 1≤j≤ n, i≠j ) ,且在排序前的序列中 ri 领先于 rj (即i<j) 。如果排序后 ri 仍领先于 rj,则称所用的排序方法是稳定的;反之,若可能使得排序后的序列中 rj 领先 ri,则称所用的排序方法是不稳定的。 简单来说,就是对于原数据中相等的数据,排序前后如果相对位置没有改变,就是稳定的。 内排序与外排序 内排序是在排序整个过程中,待排序的所有记录全部被放置在内存中

常用的比较排序算法总结

佐手、 提交于 2019-11-29 15:15:49
写在前面 一直很惧怕算法,总是感觉特别伤脑子,因此至今为止,几种基本的排序算法一直都不是很清楚,更别说时间复杂度、空间复杂度什么的了。 今天抽空理了一下,其实感觉还好,并没有那么可怕,虽然代码写出来还是磕磕绊绊,但是思想和原理还是大致上摸清楚了,记录、分享。 另一篇文章: 三种非比较排序算法总结 说明 关于排序,前辈们已经讲解的够多了,我这里主要摘录一些概念。 排序算法分类 比较排序,时间复杂度为O(nlogn) ~ O(n^2),主要有: 冒泡排序,选择排序,插入排序,归并排序,堆排序,快速排序 等 非比较排序,时间复杂度可以达到O(n),主要有: 计数排序,基数排序,桶排序 等 排序稳定性 排序算法稳定性的简单形式化定义为:如果Ai = Aj,排序前Ai在Aj之前,排序后Ai还在Aj之前,则称这种排序算法是稳定的。 常用排序算法总结(一) 关于时间复杂度和空间复杂度 选择排序 选择排序每次比较的是数组中特定索引的值与全数组中每个值的大小比较,每次都选出一个最小(最大)值,如果当前索引的值大于之后索引的值,则两者进行交换 // 分类 -------------- 内部比较排序 // 数据结构 ---------- 数组 // 最差时间复杂度 ---- O(n^2) // 最优时间复杂度 ---- O(n^2) // 平均时间复杂度 ---- O(n^2) // 所需辅助空间 --

经典排序算法

大城市里の小女人 提交于 2019-11-29 15:15:19
经典排序算法 算法复杂度 相关概念 稳定 :如果a原本在b前面,而a=b,排序之后a仍然在b的前面。 不稳定 :如果a原本在b的前面,而a=b,排序之后 a 可能会出现在 b 的后面。 时间复杂度 :对排序数据的总的操作次数。反映当n变化时,操作次数呈现什么规律。 空间复杂度: 是指算法在计算机内执行时所需存储空间的度量,它也是数据规模n的函数。 1、冒泡排序(Bubble Sort) 冒泡排序是一种简单的排序算法。它重复地走访过要排序的数列,一次比较两个元素,如果它们的顺序错误就把它们交换过来。走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。这个算法的名字由来是因为越小的元素会经由交换慢慢“浮”到数列的顶端。 1.1 算法描述 比较相邻的元素。如果第一个比第二个大,就交换它们两个; 对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对,这样在最后的元素应该会是最大的数; 针对所有的元素重复以上的步骤,除了最后一个; 重复步骤1~3,直到排序完成。 1.2 动图演示 1.3 代码实现 1 function bubbleSort(arr) { 2 3 var len = arr.length; 4 5 for (var i = 0; i < len - 1; i++) { 6 7 for (var j = 0; j < len - 1 - i; j++