二叉排序树
二叉排序树:BST(Binary Sort(Search) Tree), 对于二叉排序树的任何一个非叶子节点,要求左子节点的值比当前节点的值小,右子节点的值比当前节点的值大。 特别说明:如果有相同的值,可以将该节点放在左子节点或右子节点
二叉排序树的创建和遍历
比如针对前面的数据 (7, 3, 10, 12, 5, 1, 9) ,对应的二叉排序树为:
一个数组创建成对应的二叉排序树,并使用中序遍历二叉排序树,比如: 数组为 Array(7, 3, 10, 12, 5, 1, 9) , 创建成对应的二叉排序树为 :
代码:
package zhangke;
public class bst1 {
public static void main(String[] args) {
int []arr = {7, 3, 10, 12, 5, 1, 9};
bst er = new bst();
for (int i = 0; i < arr.length; i++) {
er.add(new Node(arr[i]));
}
er.midOrder();
}
}
class bst{
private Node root;
//添加结点
public void add(Node node){
if(root==null){
root=node;
}else {
root.add(node);
}
}
public void midOrder(){
if(root!=null){
root.midOrder();
}else {
System.out.println("empty!");
}
}
}
class Node {
private int value;//结点权值
private Node left;//指向左子节点
private Node right;//指向右子节点
//添加结点的方法
//递归的形式添加结点 注意需要满足二叉排序树的要求
public void add(Node node){
if (node==null){
return;
}
if(node.value<this.value){
if (this.left==null){//若当前结点 左子节点为null
this.left = node;
}else{
this.left.add(node);//递归的向左子树添加
}
}else {//添加的结点的值>当前结点的值
if(this.right==null){
this.right=node;
}else{
this.right.add(node);//递归的向右子树添加
}
}
}
public void midOrder(){
if(this.left!=null){
this.left. midOrder();
}
System.out.println(this);
if(this.right!=null){
this.right. midOrder();
}
}
public Node(int value) {
this.value = value;
}
public int getValue() {
return value;
}
public Node getLeft() {
return left;
}
public void setLeft(Node left) {
this.left = left;
}
public Node getRight() {
return right;
}
public void setRight(Node right) {
this.right = right;
}
public void setValue(int value) {
this.value = value;
}
@Override
public String toString() {
return "Node{" +
"value=" + value +
'}';
}
}
二叉排序树的删除
二叉排序树的删除情况比较复杂,有下面三种情况需要考虑
①删除叶子节点 (比如:2, 5, 9, 12)
②删除只有一颗子树的节点 (比如:1)
③删除有两颗子树的节点. (比如:7, 3,10 )
①删除叶子节点 删除的节点是叶子节点,即该节点下没有左右子节点。
比如这里的 (比如:2, 5, 9, 12)
1)需要先去找到要删除的结点 targetNode
2)找到 targetNode的父节点parent
3)确定targetNode是parent的左还是右子结点
4)根据前面的情况来对应删除
左子节点 parent.left=null
右子节点 parent.right=null
②删除节点有一个子节点
删除的节点有一个子节点,即该节点有左子节点或者右子节点。
比如这里的 (比如:1 )
1)需要先去找到要删除的结点 targetNode
2)找到 targetNode的父节点parent
3)确定targetNode的子节点是左还是右结点
4)targetNode是parent的左还是右子节点
5)若targetNode有左子节点
5.1若targetNode是parent的左子节点
parent.left=targetNode.left
5.2若targetNode是parent的右子节点
parent.right=targetNode.left
6)若targetNode有右子节点
6.1若targetNode是parent的左子节点
parent.left=targetNode.right
6.2若targetNode是parent的右子节点
parent.right=targetNode.right
③删除节点有两个子节点
删除的节点有两个子节点,即该节点有左子节点和右子节点。
比如这里的 (比如:7,3,10)
1)需要先去找到要删除的结点 targetNode
2)找到 targetNode的父节点parent
3)从targetNode的右子树 找到最小的结点(或者左子树找到最大值)
4)用一个临时变量 将最小结点的值保存(temp)
5)删除该最小结点
6)targetNode.value = temp
代码:
package zhangke;
public class bst1 {
public static void main(String[] args) {
int []arr = {7,3,10,12,5,1,9,2};
bst er = new bst();
for (int i = 0; i < arr.length; i++) {
er.add(new Node(arr[i]));
}
er.delNode(2);
er.delNode(5);
er.delNode(9);
er.delNode(12);
er.delNode(7);
er.delNode(3);
er.delNode(1);
er.delNode(10);
er.midOrder();
}
}
class bst{
private Node root;
//添加结点
public void add(Node node){
if(root==null){
root=node;
}else {
root.add(node);
}
}
public void midOrder(){
if(root!=null){
root.midOrder();
}else {
System.out.println("empty!");
}
}
public Node search(int value){
if(root==null){
return null;
}else {
return root.Search(value);
}
}
public Node parentSearch(int value){
if(root==null){
return null;
}else {
return root.searchParent(value);
}
}
//返回
/**
*
* @param node 当做二叉排序树的根节点
* @return 返回以node为根节点的二叉排序树的最小结点的值
*/
public int delRigthTreeMin(Node node){
Node t = node;
while (t.left!=null){
t=t.left;
}
delNode(t.getValue());
return t.getValue();
}
public void delNode(int value){
if(root==null){
return;
}else {
//1.先找到要删除的节点
Node targetNode = search(value);
if (targetNode == null) {
return;
}
//若当前这个二叉排序树只有一个结点
if(root.getLeft()==null&&root.getRight()==null){
root=null;
return;
}
//找targetNode的父节点
Node parent = parentSearch(value);
//若要删除的是叶子结点
if(targetNode.getLeft()==null&&targetNode.getRight()==null){
//判断targetNode是父结点的左还是右子结点
if(parent.getLeft()!=null&&parent.getLeft().getValue()==value){
parent.setLeft(null);
}else if(parent.getRight()!=null&&parent.getRight().getValue()==value) {
parent.setRight(null);
}
}else if(targetNode.getLeft()!=null&&targetNode.getRight()!=null){//删除有两颗子树的结点
int i = delRigthTreeMin(targetNode.right);
targetNode.setValue(i);
}else {//删除只有一颗子树的结点
//若要删除的结点有左子节点
if (targetNode.left!=null){
if(parent!=null){
if(parent.left.getValue()==value){//若targetNode是parent的左子节点
parent.left=targetNode.left;
}else if(parent.right==targetNode){
parent.right=targetNode.left;
}
}else {
root=targetNode.left;
}
}else {
if(parent!=null){
if(parent.left.getValue()==value){//若targetNode是parent的左子节点
parent.left=targetNode.right;
}else if(parent.right==targetNode){
parent.right=targetNode.right;
}
}else {
root=targetNode.right;
}
}
}
}
}
}
class Node {
private int value;//结点权值
Node left;//指向左子节点
Node right;//指向右子节点
//查找要删除的结点
public Node Search(int value){
if(value==this.value){
return this;
}else if(value<this.value){
if(this.left==null){
return null;
}
return this.left.Search(value);
}else {
if(this.right==null){
return null;
}
return this.right.Search(value);
}
}
//查找要删除结点的父结点
public Node searchParent(int value){
if((this.left!=null&&this.left.value==value)||(this.right!=null&&this.right.value==value)){
return this;
}else {
//若查找的值 小于当前结点的值 且当前结点的左子节点不为空
if(value<this.value&&this.left!=null){
return this.left.searchParent(value);
}else if(value>=this.value&&this.right!=null){
return this.right.searchParent(value);
}else{
return null;//没有父节点
}
}
}
//添加结点的方法
//递归的形式添加结点 注意需要满足二叉排序树的要求
public void add(Node node){
if (node==null){
return;
}
if(node.value<this.value){
if (this.left==null){//若当前结点 左子节点为null
this.left = node;
}else{
this.left.add(node);//递归的向左子树添加
}
}else {//添加的结点的值>当前结点的值
if(this.right==null){
this.right=node;
}else{
this.right.add(node);//递归的向右子树添加
}
}
}
public void midOrder(){
if(this.left!=null){
this.left. midOrder();
}
System.out.println(this);
if(this.right!=null){
this.right. midOrder();
}
}
public Node(int value) {
this.value = value;
}
public int getValue() {
return value;
}
public Node getLeft() {
return left;
}
public void setLeft(Node left) {
this.left = left;
}
public Node getRight() {
return right;
}
public void setRight(Node right) {
this.right = right;
}
public void setValue(int value) {
this.value = value;
}
@Override
public String toString() {
return "Node{" +
"value=" + value +
'}';
}
}