二叉搜索树的基本操作

二叉树:树的每个节点最多只能有两个子节点。

二叉搜索树要求:若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值; 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值; 它的左、右子树也分别为二叉排序树。

二叉搜索树实际上就是用了二分法的思想来方便搜索。

先定义一下二叉搜索树节点。

 1class BinaryTreeNode {
 2    BinaryTreeNode(){
 3        left = right = null;
 4    }
 5    BinaryTreeNode(int el){
 6        element = el;
 7        left = right = null;
 8    }
 9    int element;
10    BinaryTreeNode left,right;
11}

二叉搜索树的插入

这里要讨论:插入前root是否为空,有可能是把一个节点插入到一个空树上。

方法:

1、找到插入位置

2、判断是否为空树

3、建立对应key值的树节点插入。

代码:

 1public void insertTree(int key, BinaryTreeNode root) {
 2        BinaryTreeNode p = root, pre = null;
 3        //找到插入节点位置
 4        while(p != null) {
 5            pre = p;
 6            if(key < p.element) {
 7                p = p.left;
 8            }else p = p.right;
 9        }
10        //1、如果是空树,就相当与创建新节点
11        if(root == null) {
12            root = new BinaryTreeNode(key);
13        }
14        //2、插入
15        else if(key < pre.element) {
16            pre.left = new BinaryTreeNode(key); 
17        }
18        else  pre.right = new BinaryTreeNode(key); 
19    }

二叉搜索树的查找

查找节点不难,只要相互比对大小就行。

 1public BinaryTreeNode searchTree(int key,BinaryTreeNode root) {
 2        BinaryTreeNode p = root;
 3        while(p != null) {
 4            //等于直接返回p
 5            if(key == p.element) {
 6                return p;
 7            }
 8            //大于p向右走,小于p向左走
 9            else if(key < p.element) {
10                p = p.left;
11            }else p = p.right;
12        }
13        return null;
14    }

二叉搜索树的删除

这里有两种删除方式:合并删除、复制删除。

合并删除

利用二叉搜索树的本质,右子树的每个值都比左子树大,因此找到左子树中的最大值的节点,让他成为右子树的父节点。

方法:

1、判断是否有右子树,没有就接左子树。

2、判断是否有左子树,没有就接右子树。

3、左右子树存在,找到左子树的最大值,成为右子树的父节点,删除节点赋值为删除节点的左子节点。

代码:

 1//合并删除 1
 2    public void deleteByMerging(BinaryTreeNode node) {
 3        BinaryTreeNode p = node;
 4        if(node != null) {
 5            if(node.right == null) {        //不含右子树,则把左子树接到父节点
 6                node = node.left;
 7            }
 8            else if(node.left == null) {
 9                node = node.right;
10            }
11            else {
12                p = node.left;
13                while(p.right != null) {
14                    p = p.right;
15                }
16                p.right = node.right;
17                p = node;
18                node = node.left;
19            }
20        }
21    }
22    //合并删除 2
23    public void findAndDeleteByMerging(int key) {
24        BinaryTreeNode p = root, pre = null;
25        //先查找到节点位置
26        while(p != null) {
27            if(p.element == key) {
28                break;
29            }
30            pre = p;
31            if(p.element < key) {
32                p = p.right;
33            }else p = p.left;
34        }
35        //在进行讨论删除
36        if(p != null && p.element == key) {
37            if(p == root) {
38                deleteByMerging(root);
39            }
40            else if(pre.left == p) {
41                deleteByMerging(pre.left);
42            }
43            else if(pre.right == p) {
44                deleteByMerging(pre.right);
45            }
46        }
47        else if(root != null) {
48            System.out.println("key = "+key+"is not in the tree");
49        }
50    }

复制删除

找到键值的前驱代替键值。并且不会增加树的高度。

二叉搜索树的基本操作_第1张图片

方法:

1、判断是否有右子树,没有就接左子树。

2、判断是否有左子树,没有就接右子树。

3、左右子树存在,找到左子树的最大值,复制给被删除节点,然后把找到的前驱删除。

代码:

 1//复制删除
 2    public void deleteByCopying(BinaryTreeNode node) {
 3        BinaryTreeNode pre, tmp;
 4        if(node.right == null) {
 5            node = node.left;
 6        }
 7        else if(node.left == null) {
 8            node = node.right;
 9        }
10        else {
11            tmp = node.left;
12            pre = node;
13            while(tmp.right != null) {
14                pre = tmp;
15                tmp = tmp.right;
16            }
17            node.element = tmp.element;
18            if(pre == node) {
19                pre.left = tmp.left;
20            }
21            else pre.right = tmp.right;
22        }
23    }

遍历

前序遍历

1//前序遍历
2    public void preorder(BinaryTreeNode node) {
3        if(node != null) {
4            visit(node);
5            preorder(node.left);
6            preorder(node.right);       
7        }
8    }

中序遍历

1//中序遍历
2    public void inorder(BinaryTreeNode node) {
3        if(node != null) {
4            inorder(node.left);
5            visit(node);
6            inorder(node.right);                
7        }
8    }

后续遍历

1//后序遍历
2    public void postorder(BinaryTreeNode node) {
3         if(node != null) {
4             postorder(node.left);
5             postorder(node.right);
6             visit(node);           
7         }
8    }

汇总

代码会发到github

  1class BinaryTreeNode {
  2    BinaryTreeNode(){
  3        left = right = null;
  4    }
  5    BinaryTreeNode(int el){
  6        element = el;
  7        left = right = null;
  8    }
  9    int element;
 10    BinaryTreeNode left,right;
 11}
 12
 13public class BinaryTree {
 14    //根节点
 15    BinaryTreeNode root;
 16    //树的大小
 17    int size = 0;
 18    //构造方法
 19    BinaryTree(){
 20        root = null;
 21    }
 22    BinaryTree(BinaryTreeNode root){
 23        this.root = root;
 24    }
 25
 26    //插入节点
 27    public void insertTree(int key, BinaryTreeNode root) {
 28        BinaryTreeNode p = root, pre = null;
 29        //找到插入节点位置
 30        while(p != null) {
 31            pre = p;
 32            if(key < p.element) {
 33                p = p.left;
 34            }else p = p.right;
 35        }
 36        //1、如果是空树,就相当与创建新节点
 37        if(root == null) {
 38            root = new BinaryTreeNode(key);
 39        }
 40        //2、插入
 41        else if(key < pre.element) {
 42            pre.left = new BinaryTreeNode(key); 
 43        }
 44        else  pre.right = new BinaryTreeNode(key); 
 45    }
 46
 47    //查找节点
 48    public BinaryTreeNode searchTree(int key,BinaryTreeNode root) {
 49        BinaryTreeNode p = root;
 50        while(p != null) {
 51            //等于直接返回p
 52            if(key == p.element) {
 53                return p;
 54            }
 55            //大于p向右走,小于p向左走
 56            else if(key < p.element) {
 57                p = p.left;
 58            }else p = p.right;
 59        }
 60        return null;
 61    }
 62
 63    //遍历
 64    //visit函数访问节点
 65    public void visit(BinaryTreeNode node) {
 66        System.out.println(node.element);
 67    }
 68    //前序遍历
 69    public void preorder(BinaryTreeNode node) {
 70        if(node != null) {
 71            visit(node);
 72            preorder(node.left);
 73            preorder(node.right);       
 74        }
 75    }
 76    //中序遍历
 77    public void inorder(BinaryTreeNode node) {
 78        if(node != null) {
 79            inorder(node.left);
 80            visit(node);
 81            inorder(node.right);                
 82        }
 83    }
 84    //后序遍历
 85    public void postorder(BinaryTreeNode node) {
 86         if(node != null) {
 87             postorder(node.left);
 88             postorder(node.right);
 89             visit(node);           
 90         }
 91    }
 92
 93    //删除节点
 94    //合并删除 1
 95    public void deleteByMerging(BinaryTreeNode node) {
 96        BinaryTreeNode p = node;
 97        if(node != null) {
 98            if(node.right == null) {        //不含右子树,则把左子树接到父节点
 99                node = node.left;
100            }
101            else if(node.left == null) {
102                node = node.right;
103            }
104            else {
105                p = node.left;
106                while(p.right != null) {
107                    p = p.right;
108                }
109                p.right = node.right;
110                p = node;
111                node = node.left;
112            }
113        }
114    }
115    //合并删除 2
116    public void findAndDeleteByMerging(int key) {
117        BinaryTreeNode p = root, pre = null;
118        //先查找到节点位置
119        while(p != null) {
120            if(p.element == key) {
121                break;
122            }
123            pre = p;
124            if(p.element < key) {
125                p = p.right;
126            }else p = p.left;
127        }
128        //在进行讨论删除
129        if(p != null && p.element == key) {
130            if(p == root) {
131                deleteByMerging(root);
132            }
133            else if(pre.left == p) {
134                deleteByMerging(pre.left);
135            }
136            else if(pre.right == p) {
137                deleteByMerging(pre.right);
138            }
139        }
140        else if(root != null) {
141            System.out.println("key = "+key+"is not in the tree");
142        }
143    }
144
145    //复制删除
146    public void deleteByCopying(BinaryTreeNode node) {
147        BinaryTreeNode pre, tmp;
148        if(node.right == null) {
149            node = node.left;
150        }
151        else if(node.left == null) {
152            node = node.right;
153        }
154        else {
155            tmp = node.left;
156            pre = node;
157            while(tmp.right != null) {
158                pre = tmp;
159                tmp = tmp.right;
160            }
161            node.element = tmp.element;
162            if(pre == node) {
163                pre.left = tmp.left;
164            }
165            else pre.right = tmp.right;
166        }
167    }
168}

二叉搜索树的基本操作_第2张图片

二叉搜索树的基本操作_第3张图片

二叉搜索树的基本操作_第4张图片

有问题和我讨论一下

你可能感兴趣的:(二叉搜索树的基本操作)