可能有一部分人没有读过我上一篇写的二叉堆,因此这里把二叉树的基本概念复制过来了,若是读过的人能够忽略前面针对二叉树基本概念的介绍,另外若是对链表数据结构不清楚的最好先看一下本人以前写的js数据结构-链表node
二叉树(Binary Tree)是一种树形结构,它的特色是每一个节点最多只有两个分支节点,一棵二叉树一般由根节点,分支节点,叶子节点组成。而每一个分支节点也经常被称做为一棵子树。react
经常使用术语
在二叉树中,咱们经常还会用父节点和子节点来描述,好比图中2为6和3的父节点,反之6和3是2子节点算法
在二叉树的第i层上,至多有2^i-1个节点小程序
深度为k的二叉树至多有2^k-1个节点segmentfault
二叉树分为彻底二叉树(complete binary tree)和满二叉树(full binary tree)数组
二叉搜索树知足如下的几个性质:数据结构
咱们来举个例子来深刻理解如下post
一组数据:12,4,18,1,8,16,20
由下图能够看出,左边的图知足了二叉树的性质,它的每一个左子节点都小于父节点,右子节点大于其父节点,同时左子树的节点都小于根节点,右子树的节点都大于根节点this
二叉搜索树主要的几个操做:spa
经过下图,能够知道二叉搜索树的节点一般包含4个域,数据元素,分别指向其左,右节点的指针和一个指向父节点的指针所构成,通常把这种存储结构称为三叉链表。
用代码初始化一个二叉搜索树的结点:
class BinaryTreeNode { constructor(key, value){ this.parent = null; this.left = null; this.right = null; this.key = key; this.value = value; } }
接着咱们再用代码去初始化一个二叉搜索树
class BinarySearchTree { constructor() { this.root = null; } }
static createNode(key, value) { return new BinarySearchTree(key, value); }
看下面这张图,13是咱们要插入的节点,它插入的具体步骤:
经过上面的描述,咱们来看看代码是怎么写的
insert(node){ let p = this.root; let tail = this.root; // 循环遍历,去找到对应的位置 while(tail) { p = tail; // 要插入的节点key比当前节点小 if (node.key < tail.key){ tail = tail.left; } // 要插入的节点key比当前节点大 else { tail = tail.right; } } // 没有根节点,则直接做为根节点插入 if(!p) { this.root = node; return; } // p是最后一个节点,也就是咱们要插入的位置的父节点 // 比父节点大则往右边插入 if(p.key < node.key){ p.right = node; } // 比父节点小则往左边插入 else { p.left = node; } // 指向父节点 node.parent = p; }
查找就很简单了,其实和插入差多,都是去别叫左右节点的大小,而后往下找
search(key) { let p = this.root; if(!p) { return; } while(p && p.key !== key){ if(p.key<key){ p = p.right; }else{ p = p.left; } } return p; }
最经常使用的通常是中序遍历,由于中序遍历能够获得一个已经排好序的列表,这也是为何会用二叉搜索树排序的缘由
根据上面对中序遍历的解释,那么代码就变的很简单,就是一个递归的过程,递归中止的条件就是节点为null
transverse() { return this._transverse(this.root); } *_transverse(node){ if(!node){ return; } yield* this._transverse(node.left); yield node; yield* this._transverse(node.right) }
看上面这张图,咱们简化的来看一下,先访问左节点4,再本身12,而后右节点18,这样输出的就恰好是一个4,12,18
补充:这个地方用了generater,因此返回的一个迭代器。能够经过下面这种方式获得一个有序的数组,这里的前提就当是已经有插入的节点了
const tree = new BinaryTree(); //...中间省略插入过程 // 这样就返回了一个有序的数组 var arr = [...tree.transverse()].map(item=>item.key);
class BinaryTreeNode { constructor(key, value) { // 指向父节点 this.p = null; // 左节点 this.left = null; // 右节点 this.right = null; // 键 this.key = key; // 值 this.value = value; } } class BinaryTree { constructor() { this.root = null; } static createNode(key, value) { return new BinaryTreeNode(key, value); } search(key) { let p = this.root; if (!p) { return; } while (p && p.key !== key) { if (p.key < key) { p = p.right; } else { p = p.left; } } return p; } insert(node) { // 尾指针的父节点指针 let p = this.root; // 尾指针 let tail = this.root; while (tail) { p = tail; if (node.key < tail.key) { tail = tail.left; } else { tail = tail.right; } } if (!p) { this.root = node; return; } // 插入 if (p.key < node.key) { p.right = node; } else { p.left = node; } node.p = p; } transverse() { return this.__transverse(this.root); } *__transverse(node) { if (!node) { return; } yield* this.__transverse(node.left); yield node; yield* this.__transverse(node.right); } }
二叉查找树就讲完了哈,其实这个和链表很像的,仍是操做那么几个指针,既然叫查找树了,它主要仍是用来左一些搜索,还有就是排序了,另外补充一下,二叉查找树里找最大值和最小值也很方即是不是,若是你大体读懂了的话。
这篇文章我写的感受有点乱诶,由于总感受哪里介绍的不到位,让一些基础差的人会看不懂,若是有不懂或者文章哪里写错了,欢迎评论留言哈
后续写什么呢,这个问题我也在想,排序算法,react第三方的一些模拟实现?,作个小程序组件库?仍是别的,容我再想几个小时,由于能够,有建议的朋友们也能够留言说一下哈。最后最后,最重要的请给个赞,请粉一个呢,谢谢啦