总结了一下删除二叉搜索树节点的迭代和递归方法。
1、二叉搜索树 二叉搜索树的重要性质: (1)若左子树不空,则左子树上所有结点的值均小于它的根结点的值; (2)若右子树不空,则右子树上所有结点的值均大于它的根结点的值; (3)左、右子树也分别为二叉搜索树;
2、删除二叉搜索树的节点 删除二叉搜索树的节点有三种情况。 (1)删除节点没有子节点; (2)删除节点只有一个子节点; (3)删除节点有两个子节点。 如下是一棵二叉搜索树:
第一种情况,比如删除节点4,只要把当前节点4直接删除即可。 第二种情况,比如删除节点5,只要把节点5的左子树挂到节点5的父节点上。 第三种情况,比如删除节点3,我们要在节点3的右子树中找到大于3的最小节点,在这儿是节点4。然后用找到的最小节点4赋值给节点3,最后再删掉节点4即可。 下面使用迭代和递归两种方法来解决问题。
2.1、迭代 deleteNode函数主要找到删除节点的位置。其中node是要删除的节点,pre是删除节点的父节点。 del函数是删除节点函数。分为三种情况: (1)要删除的节点没有子节点时,就返回null; (2)要删除的该节点只有左子树或只有右子树时,就返回要删除节点的左子树或右子树; (3)要删除节点有两个子节点时,就要将删除节点右子树中的最小值赋值给要删除节点,然后删去最小节点。这里还有两种情况要讨论,这部分代码如下:
1 2 3 4 5 6 7 8 9 let pre = node;let cur = node.right;while (cur.left){ pre = cur; cur = cur.left; } node.val = cur.val; console .log(pre.left);pre === node ? pre.right = cur.right : pre.left = cur.right;
这段代码中cur是找到的最小节点,node是要删除节点,pre是最小节点的父节点。因为最后要删去cur所以,还是需要记录它的父节点pre。 如果是删除下图中的根节点6,此时pre===node。
1 2 3 if (pre===node){ pre.right=cur.right; }
如果是删除下图中的节点3,那么pre是节点5。
1 2 3 if (pre !== node){ pre.left = cur.right; }
完整代码和注释如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 var deleteNode = function (root, key ) { let node=root; let pre=null ; while (node!==null ){ if (node.val===key){ break ; } pre=node; if (node.val>key){ node=node.left; }else { node=node.right; } } if (node===null ){ return root; } if (pre===null ){ return del(node); } if (pre.left&&pre.left.val===key){ pre.left=del(node); }else if (pre.right&&pre.right.val===key){ pre.right=del(node); } return root; }; function del (node ) { if (node.left===null &&node.right===null ){ return null ; } if (!node.left || !node.right) { return (node.left) ? node.left : node.right; } let pre=node; let cur=node.right; while (cur.left){ pre=cur; cur=cur.left; } node.val=cur.val; console .log(pre.left); pre===node?pre.right=cur.right:pre.left=cur.right; return node; }
2.2、递归 先判断根节点是否为空; 然后开始寻找二叉搜索树中key的位置,如果当前节点的值比key大则去找当前节点的左子树,小则找右子树,直到找到与key值相同的节点; 接着判断节点子树的个数,分为节点至多只有一个子树,和有两个子树这两种情况; 代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 var deleteNode = function (root, key ) { if (root===null ){ return null ; } if (root.val>key){ root.left=deleteNode(root.left,key); } else if (root.val<key){ root.right = deleteNode(root.right,key); } else { if (!root.left||!root.right){ root=root.left?root.left:root.right; }else { let cur=root.right; while (cur.left){ cur=cur.left; } root.val=cur.val; root.right=deleteNode(root.right,cur.val); } } return root; };