玩转数据结构笔记----二叉搜索树

  1 import java.util.LinkedList;
  2 import java.util.Queue;
  3 import java.util.Stack;
  4 
  5 public class BST <E extends  Comparable>{
  6 
  7     private class Node{
  8         public E e;
  9         public Node left,right;
 10 
 11         public Node(E e){
 12             this.e=e;
 13             left=null;
 14             right=null;
 15         }
 16     }
 17 
 18     private Node root;
 19     private int size;
 20 
 21     public BST(){
 22         root=null;
 23         size=0;
 24     }
 25 
 26     //向二分搜索树添加新元素
 27     public void add(E e){
 28         root=add(root,e);
 29     }
 30 
 31     //向以node为根的二分搜索树中插入元素E,递归算法
 32     //返回插入新节点后二分搜索树的根
 33     private Node add(Node node,E e){
 34         if (node==null){
 35             size++;
 36             return new Node(e);
 37         }
 38 
 39         if (e.compareTo(node.e)<0)
 40             node.left=add(node.left,e);
 41         else if (e.compareTo(node.e)>0)
 42             node.right=add(node.right,e);
 43 
 44         return node;
 45     }
 46 
 47     public int size(){
 48         return size;
 49     }
 50 
 51     public boolean isEmpty(){
 52         return size==0;
 53     }
 54 
 55     //看二分搜索树是否包含元素e
 56     public boolean contain(E e){
 57         return contains(root,e);
 58     }
 59 
 60 
 61     //看以node为根的二分搜索树是否包含元素e,递归算法
 62     private boolean contains(Node node,E e){
 63         if (node==null)
 64             return false;
 65         if (e.compareTo(node.e)==0)
 66             return true;
 67         else if (e.compareTo(node.e)<0)
 68             return contains(node.left,e);
 69         else
 70             return contains(node.right,e);
 71     }
 72 
 73     //二分搜索树的前序遍历
 74     public void preOrder(){
 75         preOrder(root);
 76     }
 77 
 78     //前序遍历以node为根的二分搜索树,递归算法
 79     private void preOrder(Node node){
 80         if (node==null)
 81             return;
 82 
 83         System.out.println(node.e);
 84         preOrder(node.left);
 85         preOrder(node.right);
 86     }
 87 
 88     //二分搜索树的非递归前序遍历-----比递归实现复杂(中序遍历和后序遍历非递归实现比前序遍历更难)
 89     public void preOrderNR(){
 90         Stack<Node>stack=new Stack<>();
 91         stack.push(root);
 92         while (!stack.isEmpty()){
 93             Node cur=stack.pop();
 94             System.out.println(cur.e);
 95 
 96             if (cur.right!=null)
 97                 stack.push(cur.right);
 98             if (cur.left!=null)
 99                 stack.push(cur.left);
100         }
101     }
102 
103     //二分搜索树的中序遍历
104     public void inOrder(){
105         inOrder(root);
106     }
107 
108     //中序遍历以node为根的二分搜索树,递归算法
109     private void inOrder(Node node){
110         if (node==null)
111             return;
112 
113         inOrder(node.left);
114         System.out.println(node.e);
115         inOrder(node.right);
116     }
117 
118     //二分搜索树的后序遍历-----应用: 为二分搜索树释放内存
119     public void postOrder(){
120         postOrder(root);
121     }
122 
123     //后序遍历以node为根的二分搜索树,递归算法
124     private void postOrder(Node node){
125         if (node==null)
126             return;
127 
128         postOrder(node.left);
129         postOrder(node.right);
130         System.out.println(node.e);
131     }
132 
133     //二分搜索树的层序遍历
134     //广度优先遍历的意义:
135     //1. 更快的找到问题的解. 常用于算法设计中-最短路径
136     //2. 图的深度优先遍历和广度优先遍历
137     public void levelOrder(){
138         Queue<Node>q=new LinkedList<>();
139         q.add(root);
140         while (!q.isEmpty()){
141             Node cur=q.remove();
142             System.out.println(cur.e);
143 
144             if (cur.left!=null)
145                 q.add(cur.left);
146             if (cur.right!=null)
147                 q.add(cur.right);
148         }
149     }
150     //寻找二分搜索树的最小元素
151     public E minimum(){
152         if (size==0)
153             throw new IllegalArgumentException("BST is empty");
154 
155         return minimum(root).e;
156     }
157 
158     //返回以node为根的二分搜索树的最小值所在的节点
159     private Node minimum(Node node){
160         if (node.left==null)
161             return node;
162         return minimum(node.left);
163     }
164 
165      //寻找二分搜索树的最大元素
166      public E maximum(){
167          if (size==0)
168              throw new IllegalArgumentException("BST is empty");
169 
170          return maximum(root).e;
171      }
172 
173     //返回以node为根的二分搜索树的最小值所在的节点
174     private Node maximum(Node node){
175         if (node.right==null)
176             return node;
177         return maximum(node.right);
178     }
179 
180     @Override
181     public String toString(){
182         StringBuilder res=new StringBuilder();
183         generateBSTString(root,0,res);
184         return res.toString();
185     }
186 
187     //从二分搜索树中删除最小值所在节点, 返回最小值
188     public E removeMin(){
189         E ret=minimum();
190         root=removeMin(root);
191         return ret;
192     }
193 
194     //删除掉以node为根的二分搜索树中的最小节点
195     //返回删除节点后新的二分搜索树的根
196     private Node removeMin(Node node){
197         if (node.left==null){
198             Node rightNode=node.right;
199             node.right=null;
200             size--;
201             return rightNode;
202         }
203 
204         node.left=removeMin(node.left);
205         return node;
206     }
207 
208     //从二分搜索树中删除最大值所在节点
209     public E removeMax(){
210         E ret=minimum();
211         root=removeMax(root);
212         return ret;
213     }
214 
215     //删除掉以node为根的二分搜索树中的最大节点
216     //返回删除节点后新的二分搜索树的根
217     private Node removeMax(Node node){
218         if (node.right==null){
219             Node leftNode=node.left;
220             node.right=null;
221             size--;
222             return leftNode;
223         }
224 
225         node.right=removeMax(node.right);
226         return node;
227     }
228 
229     //生成以node为根节点,深度为depth的描述二叉树的字符串
230     private void generateBSTString(Node node,int depth,StringBuilder res){
231         if (node==null){
232             res.append(generateDepthString(depth)+"null\n");
233             return;
234         }
235 
236         res.append(generateDepthString(depth)+node.e+"\n");
237         generateBSTString(node.left,depth+1,res);
238         generateBSTString(node.right,depth+1,res);
239     }
240 
241     //从二分搜索树删除掉元素为e的节点
242     public void remove(E e){
243         root=remove(root,e);
244     }
245 
246     //删除以node为根的二分搜索树中值为e的节点,递归算法
247     //返回删除节点后新的二分搜索树的根
248     private Node remove(Node node,E e){
249         if (node==null)
250             return null;
251         if (e.compareTo(node.e)<0){
252             node.left=remove(node.left,e);
253             return node;
254         }else if (e.compareTo(node.e)>0){
255             node.right=remove(node.right,e);
256             return node;
257         }else { //e==node.e
258 
259             //待删除节点左子树为空的情况
260             if (node.left==null){
261                 Node rightNode=node.right;
262                 node.right=null;
263                 size--;
264                 return rightNode;
265             }
266 
267             //待删除节点右子树为空的情况
268             if (node.right==null){
269                 Node leftNode=node.left;
270                 node.left=null;
271                 size--;
272                 return leftNode;
273             }
274 
275             //待删除节点左右子树均不为空的情况
276             //找到比待删除节点大的最小节点, 即待删除节点右子树的最小节点
277             //用这个节点顶替待删除节点的位置
278             Node successor=minimum(node.right);
279             successor.right=removeMin(node.right);
280             successor.left=node.left;
281 
282             node.left=node.right=null;
283 
284             return successor;
285         }
286     }
287 
288     private String generateDepthString(int depth){
289         StringBuilder res=new StringBuilder();
290         for (int i=0;i<depth;i++)
291             res.append("--");
292         return res.toString();
293     }
294 
295 }

 

 
 
 
posted @ 2021-11-28 01:27  灰之魔女伊蕾娜  阅读(41)  评论(0)    收藏  举报