前面我们学过快速排序,平均情况下,它的时间复杂度为 O(nlogn)。...尽管这两种排序算法的时间复杂度都是 O(nlogn),甚至堆排序比快速排序的时间复杂度还要稳定,但是,在实际的软件开发中,快速排序的性能要比堆排序好,这是为什么呢?...一直重复这个过程,直到父子节点之间满足刚说的那种大小关系。 我将上面讲的往堆中插入数据的过程,翻译成了代码,你可以结合着一块看。...我们把它跟最后一个元素交换,那最大元素就放到了下标为 n 的位置。...解答开篇 现在我们来看开篇的问题,在实际开发中,为什么快速排序要比堆排序性能好? 我觉得主要有两方面的原因。 第一点,堆排序数据访问的方式没有快速排序友好。 对于快速排序来说,数据是顺序访问的。
软件定义由软件驱动并控制资源,相比高度耦合的一体化硬件更为灵活地为应用提供服务。...根据云计算开源产业联盟定义,软件定义存储(SDS,Software-defined Storage)指将存储物理资源通过抽象、池化整合,并通过智能软件实现存储资源的管理,实现控制平面和数据平面的解耦,最终以存储服务的形式提供给应用...IDC预测软件定义存储未来四年复合增长率高达12.8%,据伦敦研究机构Omdia预测到2023年,软件定义存储市场规模约为860亿美元。那么,为什么软件定义存储是未来,它有什么顺应时代浪潮的地方呢?...目前各大外置磁盘阵列的存储厂商的存储控制器已采用x86 结构,硬件趋于标准化,为软件定义存储布局打下基础。...大容量服务器和磁盘:软件定义存储中分布式存储借助于大容量的服务器和磁盘,能够提供以往外置磁盘阵列才能支持的大存储容量。
golang的变量定义为什么还没有python简洁? 今天的内容其实不能算一篇文章,而是学习golang时遇到的一个比较有意思的问题。...问题2:变量声明 关于go的变量声明, go作为新起之秀,为什么不隐式声明,非得 := 这种方式呢?...所以它的赋值和初始化本应该像c++一样提前先声明类型才能使用。但为了兼顾易用性,:=是go提供的赋值和初始化的语法糖。...python这种弱类型语言可以不用先声明类型,它牺牲了运行效率,提高了开发效率 这个和效率高低有多大关系呢?go只是少了编译的过程。
闲来无事在家学习,突然有位粉丝发消息来问0这样的问题:明明都定义好了,还是说我没有声明啊? 为什么呢?因为你不是明明。...如果不加self,那么就是方法内部的局部变量,你使用的时候,需要传入或者定义。...如果做二次开发,要是没有文档,我真是猜不出来啥意思。
昨天和别人交流 PingCAP TiDB 时,这位同学对“ TiDB 在线扩容对业务几乎没有影响 ” 这一点表示不太理解,惊讶 TiDB 到底是怎么做到的。...不管是 Greenplum 这种 MPP 数据库,还是其它的分库分表数据库,为了实现数据的均衡分布,通常需要在表上定义相关的分布键。...可以明确的说, Greenplum 早期版本里面根本就不 支持所谓的“ 在线 ”扩容。时代在进步,数据库技术也在进步。...TiDB 的扩容是怎么做的以及为什么它几乎不影响业务?TiDB 的扩容机制离不开 TiDB 整体的架构实现。...上述步骤简单理解下来就是说,TiKV 的扩容是一种 先生成副本再迁移 Leader 的一个过程,扩容对业务有影响的地方主要在于生成副本产生的 IO 消耗以及 Leader 切换的影响。
数据猿导读 人工智能无疑是21世纪最具变革性的力量之一,也许人工智能会以好的方式或坏的方式改变世界,但我们一致认为如果没有大数据,人工智能将毫无意义。...人工智能无疑是21世纪最具变革性的力量之一,也许人工智能会以好的方式或坏的方式改变世界,但我们一致认为如果没有大数据,人工智能将毫无意义。...现在人工智能能在没有人为操作的情况下自主学习,举个例子,Google的人工智能软件在Atari 2600的测试中, 49个游戏中有29个游戏获得了75%的专业测试成绩。...有人说不能,而另一些人说部分已经实现了。然而,我们正处于这样一个阶段:机器的理解、学习和与世界互动的能力正逐渐提高,大数据将使人工智能走向成熟。 作者 | 郭敏,微信:littlemin1215
是的,是可以以最高位来排序的,而且也像你说的,以最高位来排序的话,是可以减少数据之间比较的次数。但我们仍然不建议以最高位来排序,因为他有个致命的缺点。 ? ?...显然,不在桶一个桶里的数,他们的大小顺序已经是已知的了,也就是说,右边桶的数一定比左边桶的数大,所有在接下来的个位数排序里,我们只需要进行“各部分”单独排序就可以了,每一小部分都类似于原问题的一个子问题...我的想法:我觉得基数排序并非是一种时间换空间的排序,也就是说,数据量越大,额外的空间并非就越大。因为在把元素放进桶的时候,是完全可以用指针指向这个元素的,也就是说,只有初始的那些桶才算是额外的空间。...2、居然额外空间不是限制基数排序速度的原因,那为啥基数排序没有快速排序快呢?
经过前面两期漫长的介绍文章: 为什么对ChatGPT、ChatGLM这样的大语言模型说“你是某某领域专家”,它的回答会有效得多?...(一) 为什么对ChatGPT、ChatGLM这样的大语言模型说“你是某某领域专家”,它的回答会有效得多?...必须再次强调的是(至少就我们目前所知),没有什么“终极理论原因”可以解释为什么这样的事情会起作用。...它并不总是说出“在整体上有意义”的话(或对应于正确的计算),因为(例如,没有访问Wolfram|Alpha的“计算超能力”),它只是根据训练材料中的内容“听起来正确”的事物。...还有另外一点:与典型的算法计算甚至不同,ChatGPT在内部没有“循环”或“对数据重新计算”的机制。这必然限制了它的计算能力,即使与当前的计算机相比,更不用说与大脑相比了。
这个神经网络没有什么特别的“理论推导”;它只是1998 年作为一项工程而构建的东西,并且被发现可以工作。(当然,这与我们描述的通过生物进化过程产生的大脑没有太大不同。)...(注:784 维空间 784-dimensional space 是一个矩阵,不用纠结为什么是784 维,这也是为什么人工智能受制于算力的原因:计算量大。现在优化计算量也是正在研究的方向之一。)...我们可以说:“看,这个特定的网络可以做到”——这立即让我们对问题的“难度”有了一些概念(例如,需要多少个神经元或层)。但至少目前我们没有办法“提供一个叙述描述”来解释网络在做什么。...也许这是因为它确实是计算上不可简化的,并且除了通过明确追踪每一步之外,没有通用的方法可以找出它的功能。或者也许只是因为我们还没有“弄清楚科学”,并且还没有确定能够概括正在发生的事情的“自然法则”。...实际上没有办法说。它们都“与观察到的数据一致”。但它们对应于不同的“内在”思考方式,以确定如何在“盒子外部”进行操作。其中一些可能对我们人类来说比其他解更“合理”。
让 ChatGPT 更智能的六种策略(上),我们曾提到,在向大模型提问时,告诉它扮演一个领域专家的角色,它的回答会更有针对性。 但为什么会这样呢?...为什么大模型本质上只是预测词汇出现的概率就能让它输出问题的答案呢? 为了寻找这个问题的答案,找到了一篇科普文章,详细解释了大模型的工作原理和它为何能够发挥作用。...(更准确地说,它添加了一个“标记”,它可能只是单词的一部分,这就是为什么它有时可以“组成新单词”。) 在每一步它都会得到一个带有概率的单词列表。...对于类似的事情,我们(至少现在)还没有“简单数学”之类的东西。 那么它的模型会是什么样子呢? 在讨论语言之前,我们先讨论另一个模仿人的任务:识别图像。...有一段时间我们的函数仍然“识别”它,这里是“2”。但很快它就“失去了它”,并开始给出“错误”的结果: 但为什么我们说这是“错误”的结果呢?在这种情况下,我们知道我们通过模糊“2”获得了所有图像。
也就是说如果定义了一个ThreadLocal,每个线程往这个ThreadLocal中读写是线程隔离,互相之间不会影响的。它提供了一种将可变数据通过每个线程有自己的独立副本从而实现线程封闭的机制。...它大致的实现思路是怎样的? Thread类有一个类型为ThreadLocal.ThreadLocalMap的实例变量threadLocals,也就是说每个线程有一个自己的ThreadLocalMap。...> k, Object v) { super(k); value = v; } } Entry便是ThreadLocalMap里定义的节点,它继承了WeakReference...4.2 为什么要弱引用 读到这里,如果不问不答为什么是这样的定义形式,为什么要用弱引用,等于没读懂源码。...因为如果这里使用普通的key-value形式来定义存储结构,实质上就会造成节点的生命周期与线程强绑定,只要线程没有销毁,那么节点在GC分析中一直处于可达状态,没办法被回收,而程序本身也无法判断是否可以清理节点
定义 列表数据结构,我们已经有了链表,为什么还需要重新搞一个压缩列表呢?为了节省内存。 链表的前后指针是一个非常耗费内存的结构,因此在数据量小的时候,这一部分的空间尤其显得浪费。...压缩列表节点的定义 压缩列表的每一个节点的定义为: struct entry{ // 前一个 entry 的长度 int prevlous_entry_length;...它的类型和长度由 encoding 来决定。 新增节点 在前言里提到了,在某些情况下列表键会使用压缩列表,就是在列表键的内容比较少时,那么压缩列表为什么不能用于大的列表键呢?...ziplist 是连续存储的数据结构,内存是没有冗余的(前面的文章讲过的 SDS 中就有冗余空间), 也就是说,每一次新增节点,都需要进行内存申请,然后将如果当前内存连续块够用,那么将新节点添加,如果申请到的是另外一块连续内存空间...它的优势是没有链表的前后指针的内存占用,但是在数据量大的时候,性能有压力。因此只用于数据量小的场景。 ziplist 是 list 键和 hash 键的底层实现数据结构之一。
为什么要用ThreadLocal? 并发编程是一项非常重要的技术,它让我们的程序变得更加高效。...Entry的key为什么设计成弱引用? 前面说过,Entry的key,传入的是ThreadLocal对象,使用了WeakReference对象,即被设计成了弱引用。 那么,为什么要这样设计呢?...也就是说这种情况下Entry的key,一直都不会为null,除非强引用主动断开关联。 此外,你可能还会问这样一个问题:Entry的value为什么不设计成弱引用?...其结果就是:Entry和ThreadLocalMap将会长期存在下去,会导致内存泄露。 6. 如何解决内存泄露问题? 前面说过的ThreadLocal还是会导致内存泄露的问题,我们有没有解决办法呢?...接下来留几个问题给大家思考一下: ThreadLocal变量为什么建议要定义成static的? Entry数组为什么要通过hash算法计算下标,即直线寻址法,而不直接使用下标值?
也就是说 ThreadLocal 本身并不存储值,它只是作为一个 key 来让线程从 ThreadLocalMap 获取 value。...使用线程池的时候,自定义的线程数不规范,若使用强引用,内存泄漏的风险更高。 如何防止内存泄漏? 上面提到entry的value还会有内存泄漏的风险。...也就是说 ThreadLocal 本身并不存储值,它只是作为一个 key 来让线程从 ThreadLocalMap 获取 value。...使用线程池的时候,自定义的线程数不规范,若使用强引用,内存泄漏的风险更高。 如何防止内存泄漏? 上面提到entry的value还会有内存泄漏的风险。...也就是说 ThreadLocal 本身并不存储值,它只是作为一个 key 来让线程从 ThreadLocalMap 获取 value。
从类定义上来看,它和普通的HashMap一样,继承了AbstractMap类和实现了Map接口,也就是说它有着与HashMap差不多的功能。...那么既然jdk已经提供了HashMap,为什么还要再提供一个WeakHashMap呢? 黑格尔曾经说过,存在必合理,接下来我们来看下为什么有WeakHashMap。 ...在JVM里一个对象没用了是指没有任何其他有用对象直接或者间接执行它,具体点就是在GC过程中它是GCRoots不可达的。...接下来让我们看下它的代码,看它具体是怎么实现的。...Entry和普通HashMap的Entry最大的不同是它继承了WeakReference,然后把Key做成了弱引用(注意只有Key没有Value),然后传入了一个ReferenceQueue,这就让它能在某个
其他发生冲突的情况就把新加入的entry对象放到对应数组下标位置的表头,早进来的entry对象后移一个位置,这就形成了一个链表~~ 好的,上面说的挺啰嗦的,下面来个1.8版本的总结,1.8跟1.7差不多...对象,然后直接从entry对象里拿到value的; 接着说:如果通过key找到了entry对象,进入if判断,第一种情况:如果entry对象的散列码和 传进来key的散列码是相等(都是int嘛,直接判断是否相等...为什么默认的加载因子是0.75?HashMap的大小超过了加载因子定义的容量,怎么办?...如何定义这个我也回答不了...因为我们只能初始化数组的大小,并不会知道每个数组元素的链表会有多长,我看同事他们创建hashmap的时候好像都没有给参数,那么如果这10万条数据放到一个大小为16的hashmap...,没必要使用自定义对象了,复杂,麻烦~ 8、那你平时使用hashmap的时候一般用什么当做key,为什么?
同事问我为什么?这一下子把我问蒙了?对啊,只是记得这样用不可以,但是好像自己从来没有细究过为什么? 于是今天决定把这个 HashMap 遍历操作好好地研究一番,防止采坑! foreach 循环?...v = entry.getValue(); System.out.println(k + " = " + v); } } } 输出: OK,遍历没有问题...(为什么说可能,这个我们后面解释) 为什么会抛出这个异常呢? 我们先去看一下 Java API 文档对 HasMap 操作的解释吧。...集合由映射支持,如果在对集合进行迭代时修改了映射(通过迭代器自己的移除操作除外),则迭代的结果是未定义的。...但是有疑问了,我们上面说过 foreach 循环就是通过迭代器进行的遍历啊?为什么到这里是不可以了呢?
Map翻译为“映射”,它如同字典一样,给定一个key值,就能直接定位value值,它的存储结构为“key : value"形式,核心数据结构在Map内部定义了一个接口——Entry,这个数据结构包含了一个...对集合List进行排序,再定义一个LinkedHashMap,遍历集合List中的元素放到LinkedHashMap中,也就是说并没有一个类似Collections.sort(Map, Comparator...那么为什么会出现get方法是使用Object类型,而不是泛型呢?难道JDK的作者没有想到这一点吗?明明能在编译时就能发现的问题,为什么要在运行时再去判断? ...Set keyset() 返回key的set集合,注意set是无序且不可存储重复的值,当然Map中也不可能存在重复的key值,也没有有序无序一说。...这是因为我们在虚拟机栈上定义的sets对象其指针指向的是map.keySet()返回的对象,也就是说这两者指向的是同一个地址,那么只要任一一个对其改变都会影响这个对象本身,这也是Map接口对这个方法的定义
领取专属 10元无门槛券
手把手带您无忧上云