基础数据结构和算法《》

递归 

1.递归应该一种比较常见的实现一些特殊代码逻辑时需要做的,但常常也是最绕的一种方式,在解释递归 之前,我们用循环和递归来做个比较1.1.如果你打开一扇门后,同样发现前方也有一扇们,紧接着你又打开下一扇门...直到打开最后一扇门出去, 或者一直没有碰到尽头 (死循环)——'这就是循环'1.2.如果你打开一扇门,紧接着你又用钥匙打开了这扇门,然后你又看到一扇们...但是当你开到某扇门时, 发现前方是一堵墙无路可走了,你选择原路返回——'这就是递归'2.通过上面的故事可以发现递归其实是两个过程2.1.'递'问题分解去的过程叫'递' -- 就像故事打开的门2.2.'归'遇到终止'递'的条件叫'归' -- 就像故事里的墙 

 满足递归的条件

1.递归是一种解决问题的方法,它从解决问题的各个小部分开始,直到解决最初的大问题。递
归通常涉及函数调用自身
2.还是上面开门的故事,你想知道你开启的第一个门,实际是距离墙的第几扇门,这个问题想要解决
根据第一条的概念进行拆分2.1.'分解成各个小部分',也就是我要知道我下一扇门距离墙是第几扇门2.2.'这个问题与分解之后的子问题,除了数据规模不同,求解思路完全一样',我想知道开启第一扇门距离墙是第几扇门,和我想知道下一扇门距离墙的位置是第几扇门是一样的2.3.'存在递归终止条件',也就这些问题一层一层解析后,直到我知道扇的位置后终止,在一个个回来数

如何编写递归 

1.写出递推公式,找到终止条件
2.写递归代码的关键就是找到如何将大问题分解为小问题的规律,并且基于此写出递推公式,然后再推敲终止条件,
最后将递推公式和终止条件翻译成代码
3.编写递归代码的关键是,只要遇到递归,我们就把它抽象成一个递推公式,不用想一层层的调用关系,不要试图用人
脑去分解递归的每个步骤

递归到底是个什么

1.递归就是栈一种应用场景,也遵循着'先进后出的原则(后进先出)'

 递归阶乘

1.求5*4*3*2*1 的问题,用递归来解决三步走1.1.分解成各个小部分5 * fn(4)   参数n = 5-15 * (4*fn(3))     参数n = 4-15 * 4 * (3*fn(2))  参数n = 3-15 * 4 * 3 * (2*fn(1)) 参数n =2-11.2.推到成递归公式 fn(n) = n*fn(n-1) ,且fn(1) = 11.3.终止条件 fn(1) = 1// 代码
1.递归是栈的结构表现,所以它'递'的过程是在做压栈,'归'的过程在做出栈,其实本质,先算的是
终止条件,然后在依次向上传递
2.如图一,通过浏览器的控制台可以更形象的看出这个过程function factorial(n){console.trace()if(n === 1 || n === 0){return 1}console.log(n)return n * factorial(n-1)
}
factorial(5)

 斐波那契数列

0,1,1,2,3,5,8,13,21
// 斐波那契数列
function fibonacciIterative(n){if(n < 1) return 0  // 结束条件if(n <=2) return 1 // 结束条件return fibonacciIterative(n-2) + fibonacciIterative(n-1) // 递归公式 fn(n) = fn(n-1)+fn(n-2)
}这段代码是一个使用递归方式求解斐波那契数列的函数。该函数接收一个整数参数 n,表示要求解的斐波那契数列的第 n 项(n 从 1 开始计数)。首先判断 n 是否小于 1,如果是,则返回 0;如果 n 小于等于 2,返回 1,这两个条件是递归的结束条件。如果 n 大于 2,则通过递归公式 fn(n) = fn(n-1)+fn(n-2) 计算第 n 项的值,即该项的前两项之和,继续调用 fibonacciIterative 函数求解第 n-1 和 n-2 项的值。递归函数会不断地向下调用自身,直到满足结束条件才返回结果值。由于递归函数会反复调用自身,并且存在重复计算,因此在计算较大的斐波那契数列时,可能会出现性能问题。// 优化的代码
1.向求解斐波那契数列时候,将求解过程图形化,可以看出,有些已经
求过的结点我们还会反复在求,如果把这些一求过的数存起来直接用,也会
提高效率function fibonacciMemoization(n){const memo = [0,1]const fibonacci = (n) => {if(meno[0] != null) return memo[n]return memo[n] = fibonacci(n - 1, memo) + fibonacci(n - 2, memo);}return fibonacci(n);
}

树 

二叉树搜索树 (快速查找)二叉树查找法

1.首先左侧节点存储(比父节点)小的值,右侧节点存储(比父节点)大的值,也就当我们每次去查的时候,
只要去比较查询节点和当前比较父节点大小,来决定他是走左面查询,还是右面查询,这样就不用去遍历
整个树

插入 

1.插入后的数据一定要符合左侧节点存储(比父节点)小的值,右侧节点存储(比父节点)大的值,因此插入的时候也是要先和根节点比较,直到找到末尾,来决定插入的值是作为叶节点左侧还是右侧插入重复数据解决
1.二叉查找树中每一个节点不仅会存储一个数据,因此我们通过链表和支持动态扩容的数组等数据结构,把值相同的数据存储在同一个节点上
2.每个节点仍然只存储一个数据。在查找插入位置过程中,如果碰到一个节点的值,与要插入数据的值相同,就将这个要插入的数据放到这个节点的右子树,也就是说,把这个新插入的数据当作大于这个节点的值来处理

 排序

选择排序 

思路:

1.找到数据中最小值并将放到第一位,然后找到第二小的将其放到第二位

2.选择排序分成两个区间,分别是“排序区间”和“未排序区间”,选择排序每次会从“未排序区间”中找到最小元素,将其放到末尾

3.对引用图说明一下,引用第一个图中的第二个数据说明

        ‘1 5 6 3 2 4’,现在的1是排序区间,‘5 6 3 2 4’是为了排序区间,说明图虽然是5和2直接交换,但实际末尾的'4'也是比较过了的,只是图上没参与本次运算

1.这里有个思维转换,当我们求一个数组中最小值和最大值的时候,我们用等价替换的方法,只是 循环了一次,
问题来了当我们要把数组中所有的都进行排序那单单的一次循环肯定不够的,这时候就是双层for 循环
2.这里还要注意的是'选择排序'的概念,我们其实会将整个数组分成两个区域,'排序区间'和'未排序区间',其中'排序区间'
是在数组前半部分,因此已经排序过的地方肯定是不需要在进行排序因此第二层的循环条件也变成了'let j = i; j < length; j++'// 选择排序function selectionSort(array, compareFn = defaultCompare) {const {length} = arraylet indexMinfor (let i = 0; i < length-1; i++) {// 等价替换indexMin = ifor (let j = i; j < length; j++) {if (compareFn(array[indexMin], array[j]) === Compare.BIGGER_THAN) {indexMin = j}}if (i !== indexMin) {swap(array, i, indexMin)}}return array}console.log(selectionSort(array))

插入排序

1.插入排序每次排一个数组项,以此方式构建最后的排序数组。假定第一项已经排序了,接着,它和第二项进行比较第二项是应该待在原位还是插入到第一项之前呢?这样,头两项就正确排序,接着和第三项比较,以此类推
2.通俗的理解'插入排序'和'选择排序' 在整体思路方面差不多,首先'插入排序'也是将整个排序分成两个区间,分别是'排序区间'和'未排序区间',每次会从'未排序区间'中取值去以排序区间中比较,比较后将这个值插入到'以排序区间'
3.'插入排序'和'选择排序'  做个比较理解,'插入'是从'未排序区间'取值在'以排序区间去比较','选择'是从'未排序区间'
依次找到最小值放到'以排序区间'
4.如图红色区域就是'已排序区间',黄色就是'未排序'区间,依次从黄色区域取值去红色区域比较,并且将值插入到合适的红色区域

 

1.这里默认将第一个元素作为'已排序'区间中的内容,这样方便后续逻辑
2.通过过动态图来理解下面插入算法中的while逻辑,首先是吧整个数组分成两个区域
'已排序区域' 一个是 '为排序区域',第一层for是从为排序区域取出一个,'已排序区域'就是
从当前这个值往后都是以排序区域,因此while 的判断循环j 是从取点位置开始的,注意
动图插入的那个动作,如果你比我小我就把你往后移动,如果你比我大我就到大了位置,
整个while 就结束了,这个值就到了j的位置// 插入排序function insertionSort(array, compareFn = defaultCompare) {const {length} = array;let temp;for (let i = 1; i < length; i++) {let j = i;temp = array[i];while (j > 0 && compareFn(array[j - 1], temp) ===Compare.BIGGER_THAN) {array[j] = array[j - 1];j--;}array[j] = temp;}return array;};insertionSort(array)console.log(array)

结构 -- 数组 · js数据结构与算法 · 看云

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/698009.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

备战蓝桥杯---基础算法刷题1

最近在忙学校官网上的题&#xff0c;就借此记录分享一下有价值的题&#xff1a; 1.注意枚举角度 如果我们就对于不同的k常规的枚举&#xff0c;复杂度直接炸了。 于是我们考虑换一个角度&#xff0c;我们不妨从1开始枚举因子&#xff0c;我们记录下他的倍数的个数sum个&#…

Android platform tool中d8.bat不生效

d8.bat因找不到java_exe文件&#xff0c;触发EOF d8.bat中之前代码为&#xff1a; set java_exe if exist "%~dp0..\tools\lib\find_java.bat" call "%~dp0..\tools\lib\find_java.bat" if exist "%~dp0..\..\tools\lib\find_java.bat" …

分享一个我爱工具网源码优化版

应用介绍 本文来自&#xff1a;分享一个我爱工具网源码优化版 - 源码1688 前几天在网上看到了一个不错的工具网源码&#xff0c;但是源码存在一些问题&#xff0c;遂进行了修改优化。 主要修改内容有&#xff1a; 1、后台改为账号密码登录&#xff0c;上传即用&#xff0c;不…

前后端延迟怎么解决

当今互联网应用的发展越来越迅猛&#xff0c;用户对于网站或应用的性能要求也越来越高。其中一个重要方面就是前后端延迟的解决&#xff0c;也就是减少前端与后端之间的通信时间延迟&#xff0c;提高用户体验。本文将详细介绍如何解决前后端延迟的问题。 网络延迟 数据在网络…

【DAY03 软考中级备考笔记】存储系统,总线系统,输入输出系统和可靠性

存储系统&#xff0c;总线系统&#xff0c;输入输出系统和可靠性 2月22日 – 天气&#xff1a;阴转晴 济南下大雪&#xff0c;居家办公两天。 1. 计算机存储器的分类 根据存储位置划分&#xff1a; 内存/主存&#xff1a;用来保存当前正在运行的程序所需要的数据&#xff0c…

【C++精简版回顾】6.构造函数

一。类的四种初始化方式 1.不使用构造函数初始化类 使用函数引用来初始化类 class MM { public:string& getname() {return name;}int& getage() {return age;}void print() {cout << "name: " << name << endl << "age: &quo…

React学习——快速上手

文章目录 初步模块思维 初步 https://php.cn/faq/400956.html 1、可以手动使用npm来安装各种插件&#xff0c;来从头到尾自己搭建环境。 如&#xff1a; npm install react react-dom --save npm install babel babel-loader babel-core babel-preset-es2015 babel-preset-rea…

3.测试教程 - 基础篇

文章目录 软件测试的生命周期软件测试&软件开发生命周期如何描述一个bug如何定义bug的级别bug的生命周期如何开始第一次测试测试的执行和BUG管理产生争执怎么办&#xff08;处理人际关系&#xff09; 大家好&#xff0c;我是晓星航。今天为大家带来的是 测试基础 相关的讲解…

防火墙内容安全笔记

目录 DFI和DPI IDS和IPS 签名 AV URL过滤 HTTPS过滤 内容过滤 文件类型过滤 文件内容过滤 邮件过滤 VPN概述 密码学概述 对称加密 非对称加密 DFI和DPI DFI和DPI技术 --- 深度检测技术 DPI DPI --- 深度包检测技术 --- 主要针对完整的数据包&#xff08;数据包…

【springBoot】springAOP

AOP的概述 AOP是面向切面编程。切面就是指某一类特定的问题&#xff0c;所以AOP也可以理解为面向特定方法编程。AOP是一种思想&#xff0c;拦截器&#xff0c;统一数据返回和统一异常处理是AOP思想的一种实现。简单来说&#xff1a;AOP是一种思想&#xff0c;对某一类事务的集…

Camtasia2024官方标准版重磅发布更新及新版本功能介绍

Camtasia 2024标准版是一款功能强大的屏幕录制和视频编辑软件。它继承了Camtasia系列一贯的易用性和丰富功能&#xff0c;为用户提供了高效、专业的视频制作体验。 在屏幕录制方面&#xff0c;Camtasia 2024标准版支持录制电脑屏幕上的任何内容&#xff0c;包括网站、软件、视…

9、内网安全-横向移动Exchange服务有账户CVE漏洞无账户口令爆破

用途&#xff1a;个人学习笔记&#xff0c;有所借鉴&#xff0c;欢迎指正&#xff01; 背景&#xff1a; 在内网环境的主机中&#xff0c;大部分部署有Exchange邮件服务&#xff0c;对于Exchange服务的漏洞也是频出&#xff0c;在这种情况下&#xff0c;如果拿到内网中一台主机…

harbor(docker仓库)仓库部署 - 高可用

harbor&#xff08;docker仓库&#xff09;仓库部署 - 高可用 1. harbor高可用1.1 方案说明1. 双主复制2. 多harbor实例共享后端存储 1.2 部署高可用&#xff08;多harbor实例共享后端存储&#xff09;1. 服务器划分2. 安装harbor&#xff08;先部署一套Harbor&#xff0c;用于…

PostgreSQL与MySQL,谁更胜一筹

前言 PostgreSQL与MySQL都是优秀的开源数据库。在日常学习中&#xff0c;新手可能接触最多的是MySql,但是实际工作中&#xff0c;两者的应用场景其实都很广。我之前的做过上网流量销售业务&#xff0c;用的是MySQL,现在接触广告业务&#xff0c;用的是pg数据库&#xff0c;每天…

深入理解 v-for 中 key 的重要性

查看本专栏目录 关于作者 还是大剑师兰特&#xff1a;曾是美国某知名大学计算机专业研究生&#xff0c;现为航空航海领域高级前端工程师&#xff1b;CSDN知名博主&#xff0c;GIS领域优质创作者&#xff0c;深耕openlayers、leaflet、mapbox、cesium&#xff0c;canvas&#x…

【k8s核心概念与专业术语】

k8s架构 1、服务的分类 服务分类按如下图根据数据服务支撑&#xff0c;分为无状态和有状态 无状态引用如下所示&#xff0c;如果一个nginx服务&#xff0c;删除后重新部署有可以访问&#xff0c;这个属于无状态&#xff0c;不涉及到数据存储。 有状态服务&#xff0c;如redis&a…

RF 框架实现企业级 UI 自动化测试

RobotFramework 框架可以作为公司要做自动化 但是又不会代码的一种临时和紧急情况的替代方案&#xff0c;上手简单。 前言 现在大家去找工作&#xff0c;反馈回来的基本上自动化测试都是刚需&#xff01;没有自动化测试技能&#xff0c;纯手工测试基本没有什么市场。 但是很多…

探究全链路压力测试的含义与重要性

全链路压力测试是指对整个应用系统的各个环节或组件进行压力测试&#xff0c;以模拟实际生产环境中的用户负载和流量&#xff0c;评估系统在高负载条件下的性能表现。 1. 全链路压力测试的含义 全链路压力测试涉及系统的所有组件和环节&#xff0c;包括前端用户界面、应用服务器…

初始Nginx(基本概念)

目录 一、Nginx的概念 二、Nginx常用功能 1、HTTP(正向)代理&#xff0c;反向代理 1.1正向代理 1.2 反向代理 2、负载均衡 2.1 轮询法&#xff08;默认方法&#xff09; 2.2 weight权重模式&#xff08;加权轮询&#xff09; 2.3 ip_hash 3、web缓存 三、基础特性 四…

(3)llvm ir转换过程

&#xff08;1&#xff09;DAG Lowering 输入的IR转换成SelectionDAG的过程被称作lowering 就是把llvm ir转成这种 &#xff08;2&#xff09;DAG legalization "DAG legalization"&#xff08;有向无环图合法化&#xff09;是编译器后端&#xff0c;特别是在LLVM中…