关系型数据库 & 非关系型数据库区别
成本 - 速度 - 存储 - 扩展 - 持久性 - 一致性
- 1.成本:Nosql数据库简单易部署,基本都是开源软件,不需要像使用Oracle那样花费大量成本购买使用,相比关系型数据库价格便宜。
- 2**.查询速度**:Nosql数据库将数据存储于缓存之中,而且不需要经过SQL层的解析,关系型数据库将数据存储在硬盘中,自然查询速度远不及Nosql数据库。
- 3.存储数据的格式:Nosql的存储格式是key,value形式、文档形式、图片形式等等,所以可以存储基础类型以及对象或者是集合等各种格式,而数据库则只支持基础类型。
- 4.扩展性:关系型数据库有类似join这样的多表查询机制的限制导致扩展很艰难。Nosql基于键值对,数据之间没有耦合性,所以非常容易水平扩展。
- 5.持久存储:Nosql不使用于持久存储,海量数据的持久存储,还是需要关系型数据库
- 6.数据一致性:非关系型数据库一般强调的是数据最终一致性,不像关系型数据库一样强调数据的强一致性,从非关系型数据库中读到的有可能还是处于一个中间态的数据,Nosql不提供对事务的处理。
数据可脏读、幻读、不可重复读
- 脏读: 读取未提交数据.A事务读取B事务尚未提交的数据,此时如果B事务发生错误并执行回滚操作,那么A事务读取到的数据就是脏数据。就好像原本的数据比较干净、纯粹,此时由于B事务更改了它,这个数据变得不再纯粹。这种情况常发生于转账与取款操作中
- 幻读:前后多次读取,数据总量不一致。事务A在执行读取操作,需要两次统计数据的总量,前一次查询数据总量后,此时事务B执行了新增数据的操作并提交后,这个时候事务A读取的数据总量和之前统计的不一样,就像产生了幻觉一样,平白无故的多了几条数据,成为幻读。读取了其他事务新增的数据。
- 不可重复读: 前后多次读取,数据内容不一致。不可重复读是读取了其他事务更改的数据
一个数组很多数,找出/判断两个数相加等于10
function findSumNum(arr,sum){ arr.sort();// let i = 0,j=arr.length-1; while(i<=j){ if(arr[i]+arr[j]<sum) i++; else if(arr[i]+arr[j]>sum) j--;// else { console.log(arr[i]+','+arr[j]) i++;// } } }
数组去重 | indexOf | includes| Set
//1 filter function unique(arr) { return arr.filter(function(item, index, arr) { //当前元素,在原始数组中的第一个索引==当前索引值,否则返回当前元素 return arr.indexOf(item, 0) === index;//indexOf回某个指定的字符串值在字符串中首次出现的位置,方法对大小写敏感!如果要检索的字符串值没有出现,则该方法返回 -1。 }); } //2 indexOf 、 includes function unique(arr) { if (!Array.isArray(arr)) { console.log('type error!') return } var array =[];//新数组 for(var i = 0; i < arr.length; i++) { //if (array .indexOf(arr[i]) === -1) { //不包含 if( !array.includes( arr[i]) ) {//includes 检测数组是否有某个值 array.push(arr[i]); } } return array } //3 es6 Set function unique (arr) { //Set类似于数组,区别在于它所有的成员都是唯一的,不能有重复的值 return Array.from(new Set(arr)) //Array.from() 方法从一个类似数组或可迭代对象中创建一个新的,浅拷贝的数组实例。 }
https://segmentfault.com/a/1190000016418021?utm_source=tag-newest
手写找出数组重复最多的元素
function findNum(a){ var result = [0,0]; //[数,重复次数] for (var i = 0; i < a.length; i++) { for (var j = 0,count = 0; j < a.length; j++) { if (a[i]==a[j]) { ++count; }; }; if(count>result[0]) {// result[0] = count; result[1] = a[i];// }else if(count==result[0]&&result[1]<a[i]) {// result[1] = a[i];// } } alert("数"+result[1]+"重复了最多次,为"+result[0]); } var arr = [2,2,3,3,3,4,4,4,4,4,4,4,4,43,3]; findNum(arr);
后代选择器,子选择器,相邻兄弟选择器
- 后代选择器(包含子选择器,且包含子选择器的子孙选择器):
p em
- 子选择器(父选择器的一级子元素):
h1 > strong
- 相邻兄弟选择器:
h1+p
sessionID | URL重写
session机制。session机制是一种服务器端的机制,服务器使用一种类似于散列表的结构(也可能就是使用散列表)来保存信息。
当程序需要为某个客户端的请求创建一个session时,服务器首先检查这个客户端的请求里是否已包含了一个session标识------------称为session id,如果已包含则说明以前已经为此客户端创建过session,服务器就按照session id把这个session检索出来使用(检索不到,会新建一个),如果客户端请求不包含session id,则为此客户端创建一个session并且生成一个与此session相关联的session id,session id的值应该是一个既不会重复,又不容易被找到规律以仿造的字符串,这个session id将被在本次响应中返回给客户端保存。
保存这个session id的方式可以采用cookie,这样在交互过程中浏览器可以自动的按照规则把这个标识发挥给服务器。一般这个cookie的名字都是类似于SEEESIONID。
但cookie可以被人为的禁止,则必须有其他机制以便在cookie被禁止时仍然能够把session id传递回服务器。
- 经常被使用的一种技术叫做URL重写,就是把session id直接附加在URL路径的后面。
- 还有一种技术叫做表单隐藏字段。就是服务器会自动修改表单,添加一个隐藏字段,以便在表单提交时能够把session id传递回服务器。
SQL:Drop、truncate、delete
- 当你不再需要该表时, 用 drop;
- 当你仍要保留该表,但要删除所有记录时, 用 truncate;
- 当你要删除部分记录时,用 delete.
前端 怎么做到一个屏幕分辨率的自适应
https://www.cnblogs.com/HCJJ/p/6408363.html
- em:是一种相对单位,它相对于父元素的字体大小。浏览器默认的字体大小是16px,因此 1em 也就等于 16px。
- rem是一种相对单位,它相对于根元素
html
的字体大小。REM会让页面根据不同的显示设备进行适配缩放,那么必然就会有一个 标准页面尺寸,就目前而言,整个前端开发界使用最多的标准页面尺寸则是根据iphone4或者 iPhone5为依据的640px*1366px
,也有以iphone6为基准的750px。这个标准的页面尺寸,我们可以将其定义为1,如果当前的显示设备尺寸小于标准页面尺寸(640px或者750px)那么便让页面尺寸缩小,使其小于1。而当显示设备尺寸大于标准页面尺寸,我们即可以做一些其它的适配,也可以将页面整个居中显示在显示设备中然后不进行任何缩放操作。实际上rem布局与px布局并没有什么本质的区别,这个我们可以代入实例去理解,比如现在html
的font-size
的大小是100px,即 1rem = 100px,如果现在页面中要放入一个200*200的盒子,那么按照等比关系:
div{ width:2rem; height:2rem; background:gray; }
- REM 实现的页面缩放适配原理, rem 是依据
html
标记的font-size
大小的相对单位,对于使用rem为单位的页面,在被载入到显示设备显示的时候,会根据显示设备的尺寸,然后对应的修改html标签的font-size值,这样便可以一处修改,整个页面内容都会发生改变,即实现根据设备尺寸进行缩放的效果。REM方式进行移动端布局的原理都是相同的,但是不同的在与对于设备尺寸的检测上,就目前而言分为两种,一种是通过CSS meida查询,另一种则是通过JS检测。
- CSS Media
@media screen and (min-width:320px) and (max-width:359px) { html { font-size: 50px; } } @media screen and (min-width:360px) and (max-width:374px) { html { font-size: 56.25px; } } @media screen and (min-width:375px) and (max-width:383px) { html { font-size: 58.59375px; } } @media screen and (min-width:384px) and (max-width:399px) { html { font-size: 60px; } } @media screen and (min-width:400px) and (max-width:413px) { html { font-size: 62.5px; } } @media screen and (min-width:414px) and (max-width:431px) { html { font-size: 64.6875px; } } @media screen and (min-width:432px) and (max-width:479px) { html { font-size: 67.5px; } } @media screen and (min-width:480px) and (max-width:539px) { html { font-size: 75px; } } @media screen and (min-width:540px) and (max-width:639px) { html { font-size: 84.375px; } } @media screen and (min-width:640px) { html { font-size: 100px; } body { max-width: 640px !important; margin: 0px auto !important; } }
- 响应式REM布局的优点在于可以根据设计稿的特点,自定义的对某些设备进行单独适配,而缺点是检测规则固定不可变,这一点相比于“JS自动换算”更为明显。
- JS检测
(function(win,doc){ var timer = null, html = doc.documentElement, baseWidth = html.dataset.basewidth*1 || 640, metaEl = document.querySelector('meta[name="viewport"]'), event = 'onorientationchange' in win ? 'onorientationchange' : 'resize'; if(!metaEl){ metaEl = document.createElement('meta'); metaEl.setAttribute('name','viewport'); metaEl.setAttribute('content','initial-scale=1,maximum-scale=1,minimum-scale=1,user-scalable=0'); html.firstElementChild.appendChild(metaEl); } function layoutCalc(){ var width = html.getBoundingClientRect().width, ratio = width / baseWidth * 100, devicePixelRatio = window.devicePixelRatio, rem = ratio < 100 ? ratio < 50 ? 50 : ratio : 100; if(!/\.\d+/.test(devicePixelRatio.toString())){ html.dataset.dpr = devicePixelRatio; } html.style.fontSize = rem + 'px'; } win.addEventListener(event,function(){ clearTimeout(timer);//节流 timer = setTimeout(layoutCalc,300); },false); win.addEventListener('pageShow',function(e){ if(e.persisted){ clearTimeout(timer); timer = setTimeout(layoutCalc,300); } },false); layoutCalc(); }(window,document));
- 自定义基准页面尺寸:通过为 html 标签添加
data-basewidth
属性来自定义指定基准页面的尺寸。
<html data-basewidth="750" > </html>
- 定义页面内容的字体大小:对于一些符合标准的dpr(设备像素比https://blog.csdn.net/a419419/article/details/79295799)值(只要是整数,例如:1,2,3),都会为
html
标签再附加一个data-dpr
属性,然后开发者便可以根据这个属性为条件,实现在不同dpr情况下,对内容字体的大小的调整
html[data-dpr="1"] .dpr-text{ font-size:12px; } html[data-dpr="2"] .dpr-text{ font-size:24px; } html[data-dpr="3"] .dpr-text{ font-size:36px; }
<p class="dpr-text">测试文字</p>
- 相比“响应式方式”JS自动换算无需添加规则,适合于各类型的显示设备。
- vh/vw都是相对于视口的单位,浏览器视口的区域就是通过
window.innerWidth
以及window.innerHeigth
度量得到的范围。浏览器会将整个视口的宽度或者高度划分为100等份,因此1vw或者1wh就是相对视口宽度或者高度的1%。例如浏览器视口的宽度是1920,那么 1920/100 每等份即19.2px。
一行三列排版
contain & cover
- contain: 此时会保持图像的纵横比并将图像缩放成将适合背景定位区域的最大大小。等比例缩放图象到垂直或者水平,其中一项填满区域。
- cover: 此时会保持图像的纵横比并将图像缩放成将完全覆盖背景定位区域的最小大小。等比例缩放图象到垂直和水平,两项均填满区域。
Vue watch,computed和method区别
- computed:计算属性将被混入到 Vue 实例中。所有 getter 和 setter 的 this 上下文自动地绑定为 Vue 实例。
注意如果你为一个计算属性使用了箭头函数,则this
不会指向这个组件的实例,不过你仍然可以将其实例作为函数的第一个参数来访问。计算属性的结果会被缓存,除非依赖的响应式属性变化才会重新计算。注意,如果某个依赖 (比如非响应式属性) 在该实例范畴之外,则计算属性是不会被更新的。 - methods: methods 将被混入到 Vue 实例中。可以直接通过 VM 实例访问这些方法,或者在指令表达式中使用。方法中的
this
自动绑定为 Vue 实例。注意,不应该使用箭头函数来定义 method 函数 (例如plus: () => this.a++
)。理由是箭头函数绑定了父级作用域的上下文,所以this
将不会按照期望指向 Vue 实例,this.a
将是 undefined。 - watch: 一个对象,键是需要观察的表达式,值是对应回调函数。值也可以是方法名,或者包含选项的对象。Vue 实例将会在实例化时调用
$watch()
,遍历 watch 对象的每一个属性。注意,不应该使用箭头函数来定义 watcher 函数 (例如searchQuery: newValue => this.updateAutocomplete(newValue)
)。理由是箭头函数绑定了父级作用域的上下文,所以this
将不会按照期望指向 Vue 实例,this.updateAutocomplete
将是 undefined。
能使用watch属性的场景基本上都可以使用computed属性,而且computed属性开销小,性能高,因此能使用computed就尽量使用computed属性.
当执行异步操作的时候你可能就必须用watch而不是computed了。
Vue不能检测到对象属性的添加或删除:三种解决方法
- 方案一:利用Vue.set(object,key,value)
- 方案二:利用this.$set(this.object,key,value)
- 方案三:利用Object.assign({},this.obj)
Document.write()与innerHtml()区别
- document.write是直接将内容写入页面的内容流,如果在写之前没有调用document.open, 浏览器会自动调用open。每次写完关闭之后重新调用该函数,会导致页面被重写会导致页面全部重绘
- innerHTML可以将内容写入某个具体的DOM节点,不会导致页面全部重绘
innerHTML很多情况下都优于document.write,其原因在于其允许更精确的控制要刷新页面的那一个部分。
实现http长连接
- 先创建http请求方法
- 然后设置请求地址
- 在然后需要设置下请求参数的编码格式一般设置成utf8
- 然后就开始设置长连接了,这个主要是再header中设置Connection=keep-alive
- 如果需要设置长连接的有效时间就在添加Keep-Alive:timeout=60(单位:秒)
- 完成长连接的header设置后就开始设置请求参数了
- 最后就是执行者http的长连接请求了
在HTTP/1.0中默认使用短连接。也就是说,客户端和服务器每进行一次HTTP操作,就建立一次连接,任务结束就中断连接。当客户端浏览器访问的某个HTML或其他类型的Web页中包含有其他的Web资源(如JavaScript文件、图像文件、CSS文件等),每遇到这样一个Web资源,浏览器就会重新建立一个HTTP会话。
而**从HTTP/1.1起,默认使用长连接,用以保持连接特性。**使用长连接的HTTP协议,会在响应头加入这行代码:
Connection:keep-alive
在使用长连接的情况下,当一个网页打开完成后,客户端和服务器之间用于传输HTTP数据的TCP连接不会关闭,客户端再次访问这个服务器时,会继续使用这一条已经建立的连接。Keep-Alive不会永久保持连接,它有一个保持时间,可以在不同的服务器软件(如Apache)中设定这个时间。实现长连接需要客户端和服务端都支持长连接。
HTTP协议的长连接和短连接,实质上是TCP协议的长连接和短连接。
https://www.cnblogs.com/blogtech/p/10981606.html
Websocket
允许服务端主动向客户端推送数据。在 WebSocket API 中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。
现在,很多网站为了实现推送技术,所用的技术都是 Ajax 轮询。轮询是在特定的的时间间隔(如每1秒),由浏览器对服务器发出HTTP请求,然后由服务器返回最新的数据给客户端的浏览器。这种传统的模式带来很明显的缺点,即浏览器需要不断的向服务器发出请求,然而HTTP请求可能包含较长的头部,其中真正有效的数据可能只是很小的一部分,显然这样会浪费很多的带宽等资源。
浏览器通过 JavaScript 向服务器发出建立 WebSocket 连接的请求,连接建立以后,客户端和服务器端就可以通过 TCP 连接直接交换数据。
当你获取 Web Socket 连接后,你可以通过 send() 方法来向服务器发送数据,并通过 onmessage 事件来接收服务器返回的数据。
var Socket = new WebSocket(url, [protocol] );
css动画 transform,transition ,animation
- transform:描述了元素的静态样式,本身不会呈现动画效果,可以对元素进行 旋转rotate、扭曲skew、缩放scale和移动translate以及矩阵变形matrix.
transform常常配合transition和animation使用 - transition样式过渡,从一种效果逐渐改变为另一种效果。transition是一个合写属性:
transition:transition-property transition-duration transition-timing-function transition-delay//从左到右分别是:css属性、过渡效果花费时间、速度曲线、过渡开始的延迟时间
- animation动画 由@keyframes来描述每一帧的样式
div{ animation:myAnimation 5s infinite } @keyframes myAnimation { 0%{left:0;transform:rotate(0);} 100%{left:200px;transform:rotate(180deg);} }
- (1)transform仅描述元素的静态样式,常常配合transition和animation使用
(2)transition通常和hover等事件配合使用,animation是自发的,立即播放
(3)animation可设置循环次数
(4)animation可设置每一帧的样式和时间,transition只能设置头尾
(5)transition可与js配合使用,js设定要变化的样式,transition负责动画效果
/*css:*/ div{ width:100px; height:100px; transition:all 1s; } //js divEle.onclick = function(){ divEle.style.width = "200px"; divEle.style.height = "200px"; }
浏览器兼容性问题与解决方案
https://blog.csdn.net/weixin_38536027/article/details/79375411
typeof 类型判断
- 使用typeof()或者typeof进行基本数据类型检测,null是Null类型,属于基本类型,但是typeof null 返回的是字符串’object’;
console.log(typeof undefined);//未定义undefined console.log(typeof null);//object
- 引用类型只能使用 instanceof,基本数据类型无法使用instanceof 进行检测数据类型,因为基本数据类型使用instanceof进行检测,结果都是返回false
css中什么属性让字体更清晰
将-webkit-font-smoothing设置为antialiased,变得非常平滑,效果非常不错。
其默认可以支持6个值(如图),暂时我能看到效果的就是三个:
none(用于小像素文本) | subpixel-antialiased(默认) | antialiased(反锯齿)
this的指向问题
全局-ES5-ES6-DOM事件-构造函数-apply/call/bind
在`非严格模式`下,函数中的this指向window对象,因为此时函数fn是window的一个属性,所以运行fn时,fn中的this指向window。其实this的指向就是指向函数的`运行时`环境。
在`严格模式`下,若不使用window调用函数,函数中的this指向undefined;使用window调用时,指向的是window对象。
var fn = function () { 'use strict' console.log(this); console.log(this === window) } fn(); //undfined //false window.fn(); //Window对象 //true
在`严格模式`下有一种例外的情况,就是在定时器中的this,此时无论使用window调用还是不使用window调用,this都指向window。
- 在ES6中箭头函数this的指向:在ES6中箭头函数this的指向取决于
定义时
环境中的this指向一致
var fun = () => { console.log(this); console.log(this === window); } fun(); //Window对象 //true //定义箭头函数时,就是这个过程:()=>{...}所在的环境是window,所以运行fun()时,箭头函数内部的this指向window
var obj = { name:'Jay', age:25, fn:()=>{console.log(this)}, fun:function(){ console.log(this) } }; //在定义fn时,fn内部this的指向就是定义obj对象时所在的环境,obj所在的环境是window,所以调用obj.fn()时,返回的this就是Window对象 obj.fn(); //Window对象 obj.fun();//{name: "Jay", age: 25, fn: ƒ, fun: ƒ}
DOM事件处理函数中this的指向是 触发该事件的 对象
<div id='app'>App</div> <script> var $id = document.querySelector('#app'); $id.onclick = function () { console.log(this); } </script> //当点击App时,console.log(this),打印出来的值时 <div id='app'>App</div>
function Person (){ this.name = 'Jay', this.age = 25; console.log(this); } var p1 = new Person(); //Person {name: "Jay", age: 25}
- 改变this的指向
可以使用call()、apply()、bind()改变函数内部this的指向(ES6中的箭头函数除外)。其中call()和apply()在传入要绑定的this指向时,立即执行。bind()在传入要绑定的this指向时,并不执行,需要再次调用才会执行。
使用bind()改变this的指向
var obj = { name:'Jay', age:25 }; function fn(){ console.log(this===obj); console.log(this); } //fn.bind(obj);不会立即执行,需要再次调用才会执行。 var fn1 = fn.bind(obj); fn1();//再次调用 //true //{name: "Jay", age: 25}
- 需要注意的是,当使用call()、apply()、bind()改变函数内部this的指向时,如果传入的不是一个对象,会调用相对的构造函数,进行隐式类型装换。
function fn(){ console.log(typeof this === 'object'); console.log(this); } fn.apply('I am a string'); //true //String{"I am a string"}
普通函数和箭头函数区别
- 箭头函数相当于匿名函数,并且简化了函数定义。箭头函数是匿名函数,不能作为构造函数,不能使用new
- 箭头函数不绑定arguments,取而代之用rest参数…解决
- 箭头函数不绑定this,会捕获其所在的上下文的this值,作为自己的this值
- 箭头函数通过 call() 或 apply() 方法调用一个函数时,只传入了一个参数,对 this 并没有影响。
- 箭头函数没有原型属性
- 箭头函数不能当做Generator函数,不能使用yield关键字
箭头函数的 this 永远指向其上下文的 this ,任何方法都改变不了其指向,如 call() , bind() , apply()
普通函数的this指向 调用 它的那个对象
CSS行内和块状元素的区别?
HTML可以将元素分类方式分为行内元素、块状元素和行内块状元素三种。首先需要说明的是,这三者是可以互相转换的,使用display属性能够将三者任意转换:
(1)display:inline;转换为行内元素
(2)display:block;转换为块状元素
(3)display:inline-block;转换为行内块状元素
- 行内元素特征:
(1)设置宽高无效
(2)对margin仅设置左右方向有效,上下无效;padding设置上下左右都有效,即会撑大空间
(3)不会自动进行换行
- 块状元素特征:
(1)能够识别宽高
(2)margin和padding的上下左右均对其有效
(3)可以自动换行
(4)多个块状元素标签写在一起,默认排列方式为从上至下
- 行内块状元素特征:
(1)不自动换行
(2)能够识别宽高
(3)默认排列方式为从左到右
(4)margin和padding上下左右均有效
对HTML语义化标签的理解
HTML标签可以分为有语义的标签,和无语义的标签。比如table表示表格,form表示表单,a标签表示超链接,strong标签表强调。无语义标签典型的有div,span等。
- 为什么要进行语义化?
1,现在的开发基本上都是一个团队合作进行开发。这种情况下,我们写的代码不仅要让我们自己能看懂,而且也应该让别人也容易理解和阅读,要保证代码的可维护性,这一点很重要。但是在实际开发中,由于HTML的灵活性,以及CSS的强大,以至于实现同一种界面样式,不同的人写出来的代码可能实现方式都不太一样。实现糟糕的,可能全是div套div,这样的代码到时候维护的话可能就是一场灾难。这一点,个人觉得是最主要的因素。
2,和搜索引擎建立良好沟通,有助于爬虫抓取更多的有效信息
3,考虑到代码的可复用性,可移植性,方便其他设备的解析执行。移动设备、盲人阅读器等。 - 使用HTML语义化好处
html语义化让页面的内容结构化,结构更清晰,便于对浏览器、搜索引擎解析;
即使在没有样式CSS情况下也以一种文档格式显示,并且是容易阅读的;
搜索引擎的爬虫也依赖于HTML标记来确定上下文和各个关键字的权重,利于SEO;
使阅读源代码的人对网站更容易将网站分块,便于阅读维护理解。
jQuery中哪些方法可以创建插件函数
- 向jQuery添加全局函数,这样就可以使用【$.函数名称】直接调用了
//定义 $.全局函数名称 = function(参数){ //todo } //调用 $.全局函数名称
- 通过jQuery的extend方法,一次性向jQuery添加多个全局函数
$.extend({ 方法名称1: function(参数){} }, 方法名称2: function(参数){} });
- 向jQuery添加插件函数,使用jQuery.插件名称 = { 方法名称:function(){}}
$.插件名称= { 方法1: function(参数可选){}, 方法2: function(){} }; //调用 $.插件名称.方法1();
- 向jQuery的fn对象中添加方法,这样就可以绑定到jQuery的对象上,从而直接使用的方法
//向Jquery的fn中扩展方法 $.fn.方法名称 = function(参数可选){ } //调用 $('选择器')方法名称();
js是怎么避免多个文件之间的全局污染的
- 定义全局变量命名空间,只创建一个全局变量,并定义该变量为当前应用容器,把其他全局变量追加在该命名空间下
- 利用匿名函数将脚本包裹起来
(function(doc,win){ //todo })(document,window)
冒泡排序- O(n²) - 稳定
var bubbleSort = function(arr) { for (var i = 0, len = arr.length; i < len - 1; i++) { for (var j = i + 1; j < len; j++) { if (arr[i] < arr[j]) {// var temp = arr[j]; arr[j] = arr[i]; arr[i] = temp; } } } return arr; };
快速排序 - O(nlogn) - 不稳定
var quickSort = function(arr) { if (arr.length <= 1) { return arr; } var pivotIndex = Math.floor(arr.length / 2); var pivot = arr.splice(pivotIndex, 1)[0];// var left = []; var right = []; for (var i = 0; i < arr.length; i++) { if (arr[i] < pivot) { // left.push(arr[i]); } else { right.push(arr[i]); } } return quickSort(left).concat([pivot], quickSort(right));//** };
二叉树遍历
//先序 function DLR(tree){ console.log(tree.value);// if(tree.left){ DLR(tree.left); } if(tree.right){ DLR(tree.right); } } //中序 function LDR(tree){ if(tree.left){ LDR(tree.left); } console.log(tree.value);// if(tree.right){ LDR(tree.right); } } //后序 function LRD(tree){ if(tree.left){ LRD(tree.left); } if(tree.right){ LRD(tree.right); } console.log(tree.value);// }