二叉树的意思就是说:每个节点不能多于有两个儿子。
- 一棵树至少会有一个节点(根节点)
- 树由节点组成,而节点的定义就是:一个数据、两个指针(如果有节点就指向节点、没有节点就指向null):
- 因此,我们定义树的时候往往是**->定义节点->节点连接起来就成了树**,
二叉树中还有一种特殊的二叉树:二叉查找树(binary search tree)
- 定义:当前根节点的左边全部比根节点小,当前根节点的右边全部比根节点大。
- 明眼人可以看出,这对我们来找一个数是非常方便快捷的
使用js创建一个二叉查找树
function Node(key) { this.key = key; this.left = null; this.right = null; } function BinarySearchTree() { this.root = null; } // 查询树排序插入 function insertNode(node, newNode) { // 如果新节点值小于当前节点值,则插入左子节点 if (newNode.key < node.key) { if (node.left === null) { node.left = newNode; } else { insertNode(node.left, newNode); } } else { // 如果新节点值大于当前节点值,则插入右子节点 if (node.right === null) { node.right = newNode; } else { insertNode(node.right, newNode); } } } // 插入 BinarySearchTree.prototype.insert = function (key) { let newNode = new Node(key); if (this.root === null) { this.root = newNode; } else { insertNode(this.root, newNode); } } let tree = new BinarySearchTree() tree.insert(19) tree.insert(10) tree.insert(20) tree.insert(23) tree.insert(1) tree.insert(18) console.log(tree)
打印出来的效果
创建的二叉树结构就是下图所示
遍历二叉树
二叉树遍历有三种方式
- 先序遍历
- 先访问根节点,然后访问左节点,最后访问右节点(根->左->右)
- 中序遍历
- 先访问左节点,然后访问根节点,最后访问右节点(左->根->右)
- 后序遍历
- 先访问左节点,然后访问右节点,最后访问根节点(左->右->根)
以上面的二叉树为例:
- 如果是先序遍历:
19->10->1->18->20->23
- 如果是中序遍历:
1->10->18->19->20->23
- 如果是后序遍历:
1->18->10->23->20->19
let tree = new BinarySearchTree() tree.insert(19) tree.insert(10) tree.insert(20) tree.insert(23) tree.insert(1) tree.insert(18) // console.log(tree) // 先序遍历 function preTraverseBTree(treeNode) { if(treeNode !== null) { console.log(treeNode.key) preTraverseBTree(treeNode.left) preTraverseBTree(treeNode.right) } } // 中序遍历 function inTraverseBTree(treeNode) { if(treeNode !== null) { inTraverseBTree(treeNode.left) console.log(treeNode.key) inTraverseBTree(treeNode.right) } } // 后序遍历 function afterTraverseBTree(treeNode) { if(treeNode !== null) { afterTraverseBTree(treeNode.left) afterTraverseBTree(treeNode.right) console.log(treeNode.key) } } console.log('先序遍历') preTraverseBTree(tree.root) console.log('中序遍历') inTraverseBTree(tree.root) console.log('后序遍历') afterTraverseBTree(tree.root)
无论先中后遍历,每个节点的遍历如果访问有孩子的节点,先处理孩子的(逻辑是一样的)
- 因此我们很容易想到递归
- 递归的出口就是:当没有子节点了,就返回