二叉树:树的每个节点最多只能有两个子节点。
二叉搜索树要求:若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值; 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值; 它的左、右子树也分别为二叉排序树。
二叉搜索树实际上就是用了二分法的思想来方便搜索。
先定义一下二叉搜索树节点。
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、判断是否有右子树,没有就接左子树。
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}
有问题和我讨论一下