二叉搜索树的操作及其实现

简介: 二叉搜索树的操作及其实现

二叉搜索树的概念:

二叉搜索树是一种特殊的二叉树,要么是一颗空树,要么满足以下几点:

1、 若它的左子树不为空,则左子树上所有节点的值都小于根节点的值

2、若它的右子树不为空,则右子树上所有节点的值都大于根节点的值

3、它的左右子树也分别为二叉搜索树

下面就是一颗典型的二叉搜索树:

二叉搜索树的操作及其实现

二叉搜索树的查找效率是比较高的,类似与我们所熟知的二分查找。它的查找方式是这样的:如果我们要查找6这个数字,那么我们从根节点开始,遇到根节点的val是5,6>5,所以我们要往右搜寻,遇到7的时候,6<7,这时我们向右左找即可,这就找到了我们要找的数字。

我们可以看的出它的时间复杂度是O(logn),也就是搜索树的高度,但是,如果这颗搜索树呈现线性的化,也就是一条线的情况:

这时我们在搜索的时候就类似于线性查找,时间复杂度就达到了O(n)了。

然后就是二叉搜索树的插入操作,我们怎么把数据插入到原来的二叉搜索树当中呢?插入的操作和查找有点类似,需要搜索到需要查找的位置。具体逻辑为:当树空的时候直接new一个结点即可,不空的情况下,当我们要插入一个元素的时候我们需要知道它的前一个元素,这样我们才能实现插入操作,插入的位置都是为空的,所以我们要查找到它适合的位置即可。

二叉搜索树的删除属于最重要的内容,因为它的删除操作可能比较复杂一点,我们在删除某一个结点的时候需要调整,你怎么知道调整后是什么样子的呢?删除前我们还是要进行搜索,找到待删除结点的位置。

这里先说一下删除的步骤:

设待删除结点为 cur, 待删除结点的双亲结点为 parent

一. cur.left == null (要删除结点的左边为空时)

1. cur 是 root,则 root = cur.right

2. cur 不是 root,cur 是 parent.left,则 parent.left = cur.right

3. cur 不是 root,cur 是 parent.right,则 parent.right = cur.right

二. cur.right == null (要删除结点的右边为空时)

1. cur 是 root,则 root = cur.left

2. cur 不是 root,cur 是 parent.left,则 parent.left = cur.left

3. cur 不是 root,cur 是 parent.right,则 parent.right = cur.left

三. cur.left != null && cur.right != null

1. 需要使用替换法进行删除,即在它的右子树中寻找中序下的第一个结点(关键码最小),用它的值填补到被 删除节点中,再来处理该结点的删除问题

下面对二叉搜索树进行实现:

1. public class BinarySearchTree {
2. 
3. static class TreeNode {
4. public int key;
5. public TreeNode left;
6. public TreeNode right;
7. 
8.         TreeNode(int key) {
9. this.key = key;
10.         }
11.     }
12. 
13. public TreeNode root;
14. 
15. /**
16.      * 插入一个元素
17.      * @param key
18.      */
19. public boolean insert(int key) {
20. //根结点
21. if(root==null){
22.             root=new TreeNode(key);
23. return true;
24.         }
25. 
26. //找到需要插入的位置
27.         TreeNode cur=root;//找位置
28.         TreeNode parent=cur;//插入位置的父节点
29. while(cur!=null){
30. if(cur.key<key){
31.                 parent=cur;
32.                 cur=cur.right;
33.             } else if (cur.key>key) {
34.                 parent=cur;
35.                 cur=cur.left;
36.             }else{
37. //不可以插入相同的元素
38. return false;
39.             }
40.         }
41. //此时cur为空了,这个位置就是插入的位置
42. //这里需要讨论插入到parent的左边还是右边
43. if(key> parent.key){
44. //插入右边
45.             parent.right=new TreeNode(key);
46.         }else{
47. //插入左边
48.             parent.left=new TreeNode(key);
49.         }
50. return true;
51.     }
52. 
53. /**
54.      * 查找key是否存在
55.      * @param key
56.      * @return
57.      */
58. public TreeNode search(int key) {
59.        TreeNode cur=root;
60. 
61. //我们搜索的最差情况为当前结点为空
62. while (cur!=null){
63. 
64. //先判断根结点
65. if(cur.key==key){
66. return cur;
67. //如果key比结点的key大向右找
68.             } else if (cur.key<key) {
69.                 cur=cur.right;
70. //如果key比结点的key小向左找
71.             } else {
72. 
73.                 cur=cur.left;
74.             }
75.         }
76. //如果cur为空则返回空
77. return null;
78.     }
79. //中序遍历
80. public void inOrder(TreeNode root){
81. 
82. if(root==null){
83. return;
84.         }
85.         inOrder(root.left);
86.         System.out.print(root.key+" ");
87.         inOrder(root.right);
88. 
89. 
90.     }
91. 
92. 
93. /**
94.      * 删除key的值
95.      * @param key
96.      * @return
97.      */
98. public void remove(int key) {
99. 
100. TreeNode parent = null;
101. TreeNode cur = root;
102. while (cur != null) {
103. if(cur.key == key) {
104.                 removeNode(parent,cur);
105. return;
106.             }else if(cur.key < key) {
107.                 parent = cur;
108.                 cur = cur.right;
109.             }else {
110.                 parent = cur;
111.                 cur = cur.left;
112.             }
113.         }
114.     }
115. 
116. private void removeNode(TreeNode parent,TreeNode cur) {
117. if(cur.left == null) {
118. if(cur == root) {
119.                 root = cur.right;
120.             }else if(cur == parent.left) {
121.                 parent.left = cur.right;
122.             }else {
123.                 parent.right = cur.right;
124.             }
125.         }else if(cur.right == null) {
126. if(cur == root) {
127.                 root = cur.left;
128.             } else if (cur == parent.left) {
129.                 parent.left = cur.left;
130.             }else {
131.                 parent.right = cur.left;
132.             }
133.         }else {
134. TreeNode target = cur.right;
135. TreeNode targetParent = cur;
136. while (target.left != null) {
137.                 targetParent = target;
138.                 target = target.left;
139.             }
140.             cur.key = target.key;
141. if(target == targetParent.left) {
142.                 targetParent.left = target.right;
143.             }else {
144.                 targetParent.right = target.right;
145.             }
146.         }
147.     }
148. 
149. 
150. }


相关文章
|
19天前
|
存储 C++
二叉树的操作(C++实现)
二叉树的操作(C++实现)
|
19天前
|
Serverless
二叉树的常见操作
二叉树的常见操作
|
19天前
|
Java C++ Python
leetcode-701:二叉搜索树中的插入操作
leetcode-701:二叉搜索树中的插入操作
18 1
|
19天前
|
存储 算法 程序员
【算法训练-二叉树 七】【二叉搜索树】验证二叉搜索树、将二叉搜索树转为排序的双向循环链表
【算法训练-二叉树 七】【二叉搜索树】验证二叉搜索树、将二叉搜索树转为排序的双向循环链表
37 0
二叉搜索树的实现(代码版实现)
二叉搜索树的实现(代码版实现)
|
12月前
|
算法
代码随想录训练营day22| 235. 二叉搜索树的最近公共祖先 701.二叉搜索树中的插入操作 450.删除二叉搜索树中的节点...
代码随想录训练营day22| 235. 二叉搜索树的最近公共祖先 701.二叉搜索树中的插入操作 450.删除二叉搜索树中的节点...
|
12月前
|
C语言
二叉树的相关操作
本文主要是针对C语言数据结构的二叉树的相关操作包括遍历、线索化等进行介绍。
10763 4
二叉树的相关操作
leetcode 701二叉搜索树中的插入操作
leetcode 701二叉搜索树中的插入操作
52 0
leetcode 701二叉搜索树中的插入操作
代码随想录刷题|LeetCode 235.二叉搜索树的最近公共祖先 701.二叉搜索树中的插入操作 450.删除二叉搜索树中的节点
代码随想录刷题|LeetCode 235.二叉搜索树的最近公共祖先 701.二叉搜索树中的插入操作 450.删除二叉搜索树中的节点
Day22——二叉搜索树最近的公共祖先、二叉搜索树中的插入操作、删除二叉搜索树中的节点
Day22——二叉搜索树最近的公共祖先、二叉搜索树中的插入操作、删除二叉搜索树中的节点
89 0