首先我们实现二叉树的构造
(function () {
/**
* 首先我们定义一个Node的构造函数
*/
function Node(data) {
this.left = null;
this.right = null;
this.data = data;
}
/**
* 二叉树的创建
* 我们规定用数字0表示为空节点
*/
function createTree (data) {
let dat = data.shift();
let p = null;
if (dat != 0) {
p = new Node(dat);
p.left = createTree(data);
p.right = createTree(data);
}
return p;
}
// 构造一棵二叉树
let arr = [1,2,4,0,0,5,0,0,3,6,0,0,7,0,0],
root = createTree(arr);
})();
递归遍历
// 前序遍历
function prevTraverse (node) {
if (node === null) return;
prevTraverse(node.left);
console.log(node.data);
prevTraverse(node.right);
}
// 中序遍历
function middleTraverse (node) {
if (node === null) return;
console.log(node.data);
middleTraverse(node.left);
middleTraverse(node.right);
}
// 后序遍历
function lastTraverse (node) {
if (node === null) return;
lastTraverse(node.left);
lastTraverse(node.right);
console.log(node.data);
}
非递归遍历
非递归前序遍历
- 我们用栈arr来保存遍历过程中的节点
- 首先将根节点保存到栈中,循环遍历栈直到栈为空
- 因为是前序遍历,因此第一步打印根节点
- 打印完毕后,查询当前节点是否有右孩子,右孩子要先入栈
- 查询当前节点是否有左孩子,左孩子后入栈
- 右孩子比左孩子先入栈的原因是,在下一个循环中左孩子要先出栈,右孩子后出栈
- 右孩子出栈后又相当于一个根节点,先打印根节点,然后再继续向下执行上述类似查找步骤
function prevTraverseUnRecursion (root) {
let arr = [],
node = null;
arr.unshift(root);
while (arr.length !== 0) {
node = arr.shift();
console.log(node.data);
if (node.right !== null) {
arr.unshift(node.right);
}
if (node.left !== null) {
arr.unshift(node.left);
}
}
}
非递归中序遍历
- 非递归中序遍历首先要访问左孩子,然后在访问根节点,最后在访问右孩子
- 因此,在执行过程中,需要有一次跨域根节点的过程,此时栈已经空了,而这个时候是需要访问右孩子的
- 所以,当栈为空,且节点为空时表明整个访问过程结束
- 否则,如果当前节点为空,表明已经到达最底部;如果当前节点不为空,继续向下查找
function middleTraverseUnRecursion (root) {
let arr = [],
node = root;
while (arr.length !== 0 || node !== null) {
if (node === null) {
node = arr.shift();
console.log(node.data);
node = node.right;
} else {
arr.unshift(node);
node = node.left;
}
}
}
非递归后序遍历
- 我们采用栈来保存之前经过的节点,首先将根节点保存到栈中,并用parentNode记录下栈顶的节点
- 我们要使用parentNode来判断是否要继续向下搜寻,直到parentNode的左孩子和右孩子都为空。
- 我们需要使用一个循环来遍历栈arr,直到arr为空
- 第一种情况就是不断向下搜寻的过程,最近一次打印的节点traverseNode既不是parentNode的左孩子,也不是parentNode的右孩子
- 第二种情况也是不断的搜寻过程,只不过此时刚打印完parentNode的左孩子traverseNode,转到了parentNode的右孩子
- 第三种情况就是parentNode的左孩子和右孩子都不存在,说明此时已经到了最底端,需要从弹出栈顶的元素并进行打印,同时更新最近打印过的节点traverseNode
function lastTraverseUnRecursion (root) {
let arr = [],
parentNode = null,
traverseNode = null;
if (root !== null) {
arr.unshift(root);
while (arr.length !==0) {
parentNode = arr[0];
if (parentNode.left !== null && traverseNode !== parentNode.left &&traverseNode !== parentNode.right) {
arr.unshift(parentNode.left);
} else if (parentNode.right !== null && traverseNode !== parentNode.right) {
arr.unshift(parentNode.right);
} else {
traverseNode = arr.shift();
console.log(traverseNode.data);
}
}
}
}
网友评论