You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
let a1 = 0; // 栈内存
let a2 = "this is string" // 栈内存
let a3 = null; // 栈内存
let b = { x: 10 }; // 变量 b 存在于栈中,{ x: 10 } 作为对象存在于堆中
let c = [1, 2, 3]; // 变量 c 存在于栈中,[1, 2, 3] 作为对象存在于堆中
引用类型发生复制
let a = { x: 10, y: 20 }
let b = a;
b.x = 5;
console.log(a.x); // 5
function getLeafCount(treeJson) {
if (!treeJson.children) {
return 1;
} else {
let count = 0;
for (let i in treeJson.children) {
count += getLeafCount(treeJson.children[i])
}
return count;
}
}
The text was updated successfully, but these errors were encountered:
栈内存与堆内存 、浅拷贝与深拷贝
栈也被用在编程语言的编译器和内存中保存变量、方法调用等,比如函数的调用栈。
堆
堆数据结构是一种树状结构。
它的存取数据的方式,与书架与书非常相似。我们不关心书的放置顺序是怎样的,只需知道书的名字就可以取出我们想要的书了。
好比在 JSON 格式的数据中,我们存储的 key-value 是可以无序的,只要知道 key,就能取出这个 key 对应的 value。
堆与栈比较
栈内存与堆内存
引用类型发生复制
浅拷贝与深拷贝
上面讲的引用类型的复制就是浅拷贝,复制得到的访问地址都指向同一个内存空间。所以修改了其中一个的值,另外一个也跟着改变了。
深拷贝:复制得到的访问地址指向不同的内存空间,互不相干。所以修改其中一个值,另外一个不会改变。
深拷贝的的复制过程
深拷贝方式
数组
对象
一、对象的循环
二、JSON.parse 与 JSON.stringify
可实现多维对象的深拷贝。
注意:进行JSON.stringify() 序列化的过程中,undefined、任意的函数以及 symbol 值,在序列化过程中会被忽略(出现在非数组对象的属性值中时)或者被转换成 null(出现在数组中时)。
三、es6 扩展运算
四、Object.assign()
Object.assign() 只能实现一维对象的深拷贝。
通用深拷贝方法
简陋版
但上面的深拷贝方法遇到循环引用,会陷入一个循环的递归过程,从而导致爆栈。如:
终极版
递归
基本上,所有的递归问题都可以用递推公式来表示,比如:
为什么使用递归 ?递归的优缺点 ?
什么样的问题可以用递归解决呢 ?
一个问题只要同时满足以下 3 个条件,就可以用递归来解决。
比如,前面讲的电影院的例子,你要知道,自己在哪一排的问题,可以分解为前一排的人在哪一排这样一个子问题。
比如电影院那个例子,你求解自己在哪一排的思路,和前面一排人求解自己在哪一排的思路,是一模一样的。
比如电影院的例子,第一排的人不需要再继续询问任何人,就知道自己在哪一排,也就是 f(1) = 1,这就是递归的终止条件。
递归常见问题及解决方案
如何实现递归 ?
递归代码编写
写递归代码的关键就是找到如何将大问题分解为小问题的规律,并且基于此写出递推公式,然后再推敲终止条件,最后将递推公式和终止条件翻译成代码。
递归代码理解
对于递归代码,若试图想清楚整个递和归的过程,实际上是进入了一个思维误区。
理解递归代码,就把它抽象成一个递推公式,不用想一层层的调用关系,不要试图用人脑去分解递归的每个步骤。
看一个多叉树的例子
叶子结点:就是深度为 0 的结点,也就是没有孩子结点的结点,简单的说就是一个二叉树任意一个分支上的终端节点。
数据结构格式,参考如下代码:
我们如何获取根节点的所有叶子节点个数呢 ?
递归代码如下:
The text was updated successfully, but these errors were encountered: