mirror of
https://github.com/linghuam/boutique-books.git
synced 2024-11-22 01:24:57 +00:00
m
This commit is contained in:
parent
efcda23436
commit
f2bde64b89
93
b03-数据结构与算法/学习js数据结构与算法.js
Normal file
93
b03-数据结构与算法/学习js数据结构与算法.js
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
function traveseTree(root, callback) {
|
||||||
|
var pCur = root, pLast = null, stack = [];
|
||||||
|
if (root == null) return;
|
||||||
|
// 先把pCur移到左子树最下边
|
||||||
|
while(pCur) {
|
||||||
|
stack.push(pCur);
|
||||||
|
pCur = pCur.left;
|
||||||
|
}
|
||||||
|
while(stack.length) {
|
||||||
|
pCur = stack.pop();
|
||||||
|
//一个根节点被访问的前提是:无右子树或右子树已被访问过
|
||||||
|
if (pCur.right == null || pCur.right == pLast) {
|
||||||
|
callback(pCur);
|
||||||
|
pLast = pCur;
|
||||||
|
}
|
||||||
|
/*这里的else语句可换成带条件的else if:
|
||||||
|
else if (pCur->lchild == pLastVisit)//若左子树刚被访问过,则需先进入右子树(根节点需再次入栈)
|
||||||
|
因为:上面的条件没通过就一定是下面的条件满足。仔细想想!
|
||||||
|
*/
|
||||||
|
else {
|
||||||
|
// 根节点再次入栈
|
||||||
|
stack.push(pCur);
|
||||||
|
// 进入右子树,且可肯定右子树一定不为空
|
||||||
|
pCur = pCur.right;
|
||||||
|
while(pCur) {
|
||||||
|
stack.push(pCur);
|
||||||
|
pCur = pCur.left;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var root = {
|
||||||
|
value: 11,
|
||||||
|
left: {
|
||||||
|
value: 7,
|
||||||
|
left: {
|
||||||
|
value: 5,
|
||||||
|
left: {
|
||||||
|
value: 3,
|
||||||
|
left: null,
|
||||||
|
right: null
|
||||||
|
},
|
||||||
|
right: {
|
||||||
|
value: 6,
|
||||||
|
left: null,
|
||||||
|
right: null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
right: {
|
||||||
|
value: 9,
|
||||||
|
left: {
|
||||||
|
value: 8,
|
||||||
|
left: null,
|
||||||
|
right: null
|
||||||
|
},
|
||||||
|
right: {
|
||||||
|
value: 10,
|
||||||
|
left: null,
|
||||||
|
right: null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
right: {
|
||||||
|
value: 15,
|
||||||
|
left: {
|
||||||
|
value: 13,
|
||||||
|
left: {
|
||||||
|
value: 12,
|
||||||
|
left: null,
|
||||||
|
right: null
|
||||||
|
},
|
||||||
|
right: {
|
||||||
|
value: 14,
|
||||||
|
left: null,
|
||||||
|
right: null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
right: {
|
||||||
|
value: 20,
|
||||||
|
left: {
|
||||||
|
value: 18,
|
||||||
|
left: null,
|
||||||
|
right: null
|
||||||
|
},
|
||||||
|
right: {
|
||||||
|
value: 25,
|
||||||
|
left: null,
|
||||||
|
right: null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
traveseTree(root, e => {e && e.value && console.log(e.value);});
|
@ -199,24 +199,102 @@ function traveseTree(node, callback) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 非递归写法
|
// 非递归写法(借助栈)
|
||||||
function traveseTree(root, callback) {
|
function traveseTree(root, callback) {
|
||||||
var stack = [];
|
var stack = [];
|
||||||
var currentNode = root;
|
var p = root;
|
||||||
while(currentNode) {
|
if (root == null)
|
||||||
while(currentNode.left) {
|
return;
|
||||||
stack.push(currentNode.left);
|
while(stack.length || p) {
|
||||||
currentNode = currentNode.left;
|
// 第一步:遍历左子树,根节点入栈(为了后面根据根节点找到右子树)
|
||||||
|
while(p) {
|
||||||
|
stack.push(p);
|
||||||
|
p = p.left;
|
||||||
}
|
}
|
||||||
callback(stack.pop());
|
// 第二步:出栈(p指向栈顶元素,取p的右子树重复以上过程,直到栈为空且p为空)
|
||||||
callback(stack.pop());
|
callback(p = stack.pop());
|
||||||
|
p = p.right;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
#### 先序遍历(根左右)
|
#### 先序遍历(根左右)
|
||||||
|
|
||||||
|
```js
|
||||||
|
// 递归写法
|
||||||
|
function traveseTree(root, callback) {
|
||||||
|
if (root != null) {
|
||||||
|
callback(root);
|
||||||
|
traveseTree(root.left);
|
||||||
|
traveseTree(root.right);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 非递归写法(借助栈)
|
||||||
|
function traveseTree(root, callback) {
|
||||||
|
var p = root,
|
||||||
|
stack = [];
|
||||||
|
if (root == null) return;
|
||||||
|
while(stack.length || p) {
|
||||||
|
// 第一步:先遍历左子树,边遍历边打印,并将根节点存入栈中,以后借助跟节点进入右子树开启新一轮遍历
|
||||||
|
while(p) {
|
||||||
|
callback(p);
|
||||||
|
stack.push(p);
|
||||||
|
p = p.left;
|
||||||
|
}
|
||||||
|
p = stack.pop();
|
||||||
|
p = p.right;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
#### 后序遍历(左右根)
|
#### 后序遍历(左右根)
|
||||||
|
|
||||||
|
```js
|
||||||
|
// 递归写法
|
||||||
|
function traveseTree(root, callback) {
|
||||||
|
if (root != null) {
|
||||||
|
traveseTree(root.left);
|
||||||
|
traveseTree(root.right);
|
||||||
|
callback(root);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 非递归写法(借助栈)
|
||||||
|
// 后序遍历的难点在于:需要判断上次访问的节点是位于左子树,还是右子树。若是位于左子树,则需跳过根节点,先进入右子树,再回头访问根节点;若是位于右子树,则直接访问根节点。
|
||||||
|
function traveseTree(root, callback) {
|
||||||
|
var pCur = root, pLast = null, stack = [];
|
||||||
|
if (root == null) return;
|
||||||
|
// 先把pCur移到左子树最下边
|
||||||
|
while(pCur) {
|
||||||
|
stack.push(pCur);
|
||||||
|
pCur = pCur.left;
|
||||||
|
}
|
||||||
|
while(stack.length) {
|
||||||
|
pCur = stack.pop();
|
||||||
|
//一个根节点被访问的前提是:无右子树或右子树已被访问过
|
||||||
|
if (pCur.right == null || pCur.right == pLast) {
|
||||||
|
callback(pCur);
|
||||||
|
pLast = pCur;
|
||||||
|
}
|
||||||
|
/*这里的else语句可换成带条件的else if:
|
||||||
|
else if (pCur->lchild == pLastVisit)//若左子树刚被访问过,则需先进入右子树(根节点需再次入栈)
|
||||||
|
因为:上面的条件没通过就一定是下面的条件满足。仔细想想!
|
||||||
|
*/
|
||||||
|
else {
|
||||||
|
// 根节点再次入栈
|
||||||
|
stack.push(pCur);
|
||||||
|
// 进入右子树,且可肯定右子树一定不为空
|
||||||
|
pCur = pCur.right;
|
||||||
|
while(pCur) {
|
||||||
|
stack.push(pCur);
|
||||||
|
pCur = pCur.left;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
### 树的查找
|
### 树的查找
|
||||||
|
|
||||||
### 树的删除
|
### 树的删除
|
Loading…
Reference in New Issue
Block a user