二叉搜索树
-
定义:二叉树中任意节点的右子树的所有节点值都比此节点大,左子树中所有节点的值都比此节点小,每个节点存在指向其父节点的指针
-
操作:
-
查找:
-
递归:
if x==null or k==x.key return x if k<x.key return TREESEARCH(x.left,k) else return TREESEARCH(x.right,k)
-
迭代:
while x!=null and k!=x.key if k<x.key x=x.left else x=x.right return x
-
-
最小关键字和最大关键字:
利用二叉搜索树本身的性质,最小关键字的时候就不断遍历左子树至null,最大关键字就不断遍历右子树至null
-
二叉搜索树中指定节点的前驱和后继:
-
普通解法:根据二叉搜索树的性质,其中序遍历序列为递增有序,再线性查找指定节点的后继
-
进阶解法:
-
若节点的右子树不为空,寻找其右子树的最小关键字所在节点
-
若节点的右子树为空,且此节点位于其父节点的左子树上,直接返回父节点
-
若此节点的右子树为空,且此节点位于其父节点的右子树上,返回其最近的祖先节点,使其位于该祖先节点的左子树上
(注:如果数据结构中有指向父节点的指针,可以直接使用这个递归思想)
实现:递归实现
如果根节点小于或等于要寻找的节点,直接进入右子树递归,如果根节点大于要寻找的节点,暂存左子树递归的结果,如果是null,返回当前节点,不是则返回左子树递归结果
/** * Definition for a binary tree node. * public class TreeNode { * int val; * TreeNode left; * TreeNode right; * TreeNode(int x) { val = x; } * } */ class Solution { public TreeNode inorderSuccessor(TreeNode root, TreeNode p) { if(root==null||p==null) { return null; } else { if(root.val<=p.val) { return inorderSuccessor(root.right,p); } else { return inorderSuccessor(root.left,p)!=null?inorderSuccessor(root.left,p):root; } } }
-
-
}
```从思路到递归的转换不是很直接 前驱的话,和后继正好对称,将其中的左换成右即可
-
二叉搜索树中节点的删除和插入
-
节点插入:
-
思路:保证二叉搜索树的性质,从上往下对节点值进行比较,确保最后插入的位置不影响二叉搜索树的性质
-
题解:
/** * Definition for a binary tree node. * public class TreeNode { * int val; * TreeNode left; * TreeNode right; * TreeNode(int x) { val = x; } * } */ class Solution { public TreeNode insertIntoBST(TreeNode root, int val) { TreeNode temp=root; if(val>temp.val&&temp.right!=null) { insertIntoBST(temp.right,val); } if(val>temp.val&&temp.right==null) { TreeNode temp2=new TreeNode(val); temp.right=temp2; } if(val<temp.val&&temp.left!=null) { insertIntoBST(temp.left,val); } if(val<temp.val&&temp.left==null) { TreeNode temp2=new TreeNode(val); temp.left=temp2; } return root; } }
//递归算法 /** * Definition for a binary tree node. * public class TreeNode { * int val; * TreeNode left; * TreeNode right; * TreeNode(int x) { val = x; } * } */ class Solution { public TreeNode insertIntoBST(TreeNode root, int val) { if(root==null) return new TreeNode(val); if(val>root.val) root.right=insertIntoBST(root.right,val); else root.left=insertIntoBST(root.left,val); return root; } }
//迭代算法 /** * Definition for a binary tree node. * public class TreeNode { * int val; * TreeNode left; * TreeNode right; * TreeNode(int x) { val = x; } * } */ class Solution { public TreeNode insertIntoBST(TreeNode root, int val) { TreeNode node=root; while(node!=null) { if(val>node.val) { if(node.right==null) { node.right=new TreeNode(val); } else { node=node.right; } } else { if(node.left==null) { node.left=new TreeNode(val); } else { node=node.left; } } } return root; } }
-
-
节点的删除:
-
思路1:删除节点共分为三种情况,被删除的节点无子节点,只有左子节点或右子节点,左右子节点均存在
- 无子节点:直接删除,并将该节点的父节点的对应子节点设置成null(父节点不存在的情况可以巧妙化解)
- 只存在一个子节点:找出该子节点,将其父节点设置成当前节点的父节点(父节点不存在的情况可巧妙化解)
- 左右子节点均存在:找出此节点的后继,即右节点中最小关键字所在的节点,后继节点至多存在一个子节点,此时回到第一种或第二种情况
-
题解:
//针对有父节点的数据结构 class Solution { public TreeNode deleteNode(TreeNode root, TreeNode z) { TreeNode child=null; TreeNode delete=null; if((z.left==null)||(z.right==null)) { delete=z;//被删除节点即为当前节点 } else { delete=successor(z);//被删除节点改为当前节点的后继 } if(delete.left!=null)//无论子节点是否存在,先获取 { child=delete.left; } else { child=delete.right; } if(child!=null) { child.parent=delete.parent; } if(delete.parent==null)//说明删除的是根节点 { root=child; } else if(delete==delete.parent.left) { delete.parent.left=child; } else if(delete==delete.parent.right) { delete.parent.right=child; } if(delete!=z) { z.val=delete.val; } return delete; } }
-
思路2:递归,共有三种情况
- 要删除的节点为叶子节点,直接删除
- 要删除的节点不是叶子节点且有右节点,则将其后继的值赋给该节点,递归删除该节点的后继
- 要删除的节点不是叶子节点且无右节点,则将其前驱的值赋给该节点,递归删除其前驱
-
题解2:
/** * Definition for a binary tree node. * public class TreeNode { * int val; * TreeNode left; * TreeNode right; * TreeNode(int x) { val = x; } * } */ class Solution { public int successor(TreeNode root){ root=root.right; while(root.left!=null) { root=root.left; } return root.val; } public int presuccessor(TreeNode root){ root=root.left; while(root.right!=null) { root=root.right; } return root.val; } public TreeNode deleteNode(TreeNode root, int key) { if(root==null) return null; if(key>root.val) { root.right=deleteNode(root.right,key); } else if(key<root.val) { root.left=deleteNode(root.left,key); } else { if(root.left==null&&root.right==null)//叶子节点 { root=null; } else if(root.right!=null) { int success=successor(root); root.val=success; root.right=deleteNode(root.right,success); } else { int presuccess=presuccessor(root); root.val=presuccess; root.left=deleteNode(root.left,presuccess); } } return root; } }
-
-
-