java-实现 哈夫曼树 二叉查找树

二叉树的应用

1,哈夫曼树和哈夫曼编码

 //转载至:https://blog.csdn.net/jdhanhua/article/details/6621026

1.1首先是Node类,因为每次取出两个最小值都行从新排序,将Node实现

Comparable接口用于排序

 1 public class Node implements Comparable<Node>{
 2     public int data=Integer.MAX_VALUE;
 3     public Node lchild=null;
 4     public Node rchild=null;
 5 
 6     public Node(){}
 7     public Node(int data){
 8         this.data=data;
 9     }
10 
11     @Override
12     public int compareTo(Node o) {
13         if(o.data>this.data)
14             return 1;
15         if(o.data<this.data)
16             return -1;
17         return 0;
18     }
19 }
View Code

1.2,hafuffmanTree类

  1 import java.util.*;
  2 
  3 /**
  4  *
  5  * 建树,
  6  * 输出哈夫曼编码
  7  */
  8 
  9 
 10 public class HaffmanTree {
 11     private Node root=new Node();
 12 
 13     /**
 14      * 建树-①根据已排序的升序频率数组建树,每次取出前两个创建树,根节点为前两个和
 15      * ②将根节点插入数组,重新排序,重复①,直至结束
 16      * https://blog.csdn.net/jdhanhua/article/details/6621026
 17      */
 18     public Node createHaffmanTree(List<Node> array){
 19         while(array.size()>1){
 20             Collections.sort(array);
 21             Node left=array.get(array.size()-1);
 22             Node right=array.get(array.size()-2);
 23             Node newNode=new Node(left.data+right.data);
 24             newNode.lchild=left;
 25             newNode.rchild=right;
 26             array.remove(left);
 27             array.remove(right);
 28             array.add(newNode);
 29             //System.out.println("data: "+newNode.data);
 30         }
 31         return array.get(0);
 32     }
 33 
 34     /**
 35      * 打印编码
 36        https://www.it610.com/article/1296876477320601600.htm
 37      遍历的时候加一个编码栈
 38      * 遍历的时候,进入左子树,0入栈,右子树,1入栈,
 39      * 遍历到叶子节点-输出,打印栈,
 40      *返回时栈顶退栈
 41      */
 42     public void HaffmanCode(Node root,Stack<Integer>stack){
 43         if(root==null)
 44             return;
 45         if(root.rchild==null&&root.rchild==null)//叶子节点
 46             System.out.println(root.data+" "+stack);
 47         stack.push(0);
 48         HaffmanCode(root.lchild,stack);
 49         stack.pop();
 50 
 51         stack.push(1);
 52         HaffmanCode(root.rchild,stack);
 53         stack.pop();
 54     }
 55     //打印树-复制上一篇
 56     //H为频率数组个数
 57     public void printTree(Node root,int H){
 58         int h=H;
 59         //System.out.println("树高:"+H);
 60         if(H==0)
 61             System.out.println("树空,无打印");
 62         else{
 63             System.out.println("打印树:");
 64             Queue<Node> queue=new LinkedList<>();
 65             queue.add(root);
 66             int height=1;
 67             //记录每层孩子个数
 68             int len=1;
 69             while(h>0){
 70                 int length=0;
 71                 String space="";
 72                 for(int i=0;i<(((Math.pow(2,H)+1)*3)/(Math.pow(2,height)+1));i++)
 73                     space+=" ";
 74                 for(int i=0;i<len;i++){
 75                     Node curroot=queue.poll();
 76                     if(curroot.data==Integer.MAX_VALUE){
 77                         System.out.print(space);
 78                     }else
 79                         System.out.print(space+curroot.data);
 80 
 81                     if(curroot.lchild!=null){
 82                         queue.add(curroot.lchild);
 83                     }
 84                     else
 85                         queue.add(new Node());
 86                     length++;
 87                     if(curroot.rchild!=null){
 88                         queue.add(curroot.rchild);
 89                     }
 90                     else
 91                         queue.add(new Node());
 92                     length++;
 93                 }
 94                 System.out.println();
 95                 System.out.println();
 96                 len=length;
 97                 height++;
 98                 h--;
 99             }
100             System.out.println();
101         }
102     }
103 
104     //1,2,5,8,7,9
105     public static void main(String args[]) {
106         List<Node> l=new ArrayList<Node>();
107         l.add(new Node(1));
108         l.add(new Node(2));
109         l.add(new Node(5));
110         l.add(new Node(8));
111         l.add(new Node(7));
112         l.add(new Node(9));
113         int H=l.size();
114         System.out.println("l  "+l.size());
115 
116         HaffmanTree h=new HaffmanTree();
117         h.root=h.createHaffmanTree(l);
118 
119         h.printTree(h.root,H);
120         Stack<Integer> stack=new Stack<>();
121         h.HaffmanCode(h.root,stack);
122         
123     }
124 
125 
126 }
View Code

 

 

2,二叉查找树

 2.1,先实现二叉查找树的排序功能

         如果在建树的时候安照,若插入节点值小于根节点值,往根节点左子树继续,大于根节点值

      往右子树继续,如无左/右子树则插入。建树完成后,形成的树的中序遍历结构就是升序的。

如按 {4,2,3,8,7,9,1}  顺序插入建树如图,中序遍历为:1234789

Node类同hafuffman 树,就不写了

sortBiTree

  1 /**
  2  * 二叉搜索树的排序功能
  3  * 给你个待排序数组
  4  * 建树,中序遍历树
  5  *
  6  * 缺点:
  7  * 当待排序的序列为顺序或逆序时,很不稳定,需要平衡二叉树或红黑树那种
  8  * 后面再学
  9  */
 10 import java.util.LinkedList;
 11 import java.util.Queue;
 12 public class SortBitree {
 13     private Node root=null;
 14 
 15 
 16     /**
 17      * 建树
 18      * 空-插入根节点,比根节点小,进入左子树,
 19      * 比根节点大,进入右子树
 20      */
 21     public void inseart(Node root,int data){
 22         //System.out.println(root.data);
 23         if(root==null)
 24             this.root=new Node(data);
 25         else{
 26             //元素不能重复,
 27             if(data<root.data){
 28                 if(root.lchild==null){
 29                     root.lchild=new Node(data);
 30                 }
 31                 else{
 32                     inseart(root.lchild,data);
 33                 }
 34             }
 35             else{
 36                 if(root.rchild==null){
 37                     root.rchild=new Node(data);
 38                 }else
 39                     inseart(root.rchild,data);
 40             }
 41         }
 42     }
 43     //递归求树高-用于打印
 44     //递归
 45     public int treeHeightRec(Node root){
 46         if(root==null||root.data==Integer.MAX_VALUE)
 47             return 0;
 48         else{
 49             int a =treeHeightRec(root.lchild);
 50             int b = treeHeightRec(root.rchild);
 51             return (a>b)?(a+1):(b+1);
 52         }
 53     }
 54     //打印树--233,复制前一篇的方法,如果树层数很深时,打印的比较别扭
 55     public void printTree(Node root){
 56         int H=treeHeightRec(root);
 57         int h=H;
 58         //System.out.println("树高:"+H);
 59         if(H==0)
 60             System.out.println("树空,无打印");
 61         else{
 62             System.out.println("打印树:");
 63             Queue<Node> queue=new LinkedList<>();
 64             queue.add(root);
 65             int height=1;
 66             //记录每层孩子个数
 67             int len=1;
 68             while(h>0){
 69                 int length=0;
 70                 String space="";
 71                 for(int i=0;i<(((Math.pow(2,H)+1)*3)/(Math.pow(2,height)+1));i++)
 72                     space+=" ";
 73                 for(int i=0;i<len;i++){
 74                     Node curroot=queue.poll();
 75                     if(curroot.data==Integer.MAX_VALUE){
 76                         System.out.print(space);
 77                     }else
 78                         System.out.print(space+curroot.data);
 79 
 80                     if(curroot.lchild!=null){
 81                         queue.add(curroot.lchild);
 82                     }
 83                     else
 84                         queue.add(new Node());
 85                     length++;
 86                     if(curroot.rchild!=null){
 87                         queue.add(curroot.rchild);
 88                     }
 89                     else
 90                         queue.add(new Node());
 91                     length++;
 92                 }
 93                 System.out.println();
 94                 System.out.println();
 95                 len=length;
 96                 height++;
 97                 h--;
 98             }
 99             System.out.println();
100         }
101     }
102     //中序遍历
103     public void inOrder(Node root){
104         if(root==null)
105             return;
106         inOrder(root.lchild);
107         System.out.print(root.data+" ");
108         inOrder(root.rchild);
109     }
110     
111     public static void main(String args[]) {
112         SortBitree t=new SortBitree();
113         SortBitree t1=new SortBitree();
114         SortBitree t2=new SortBitree();
115         int[] array={4,2,3,8,7,9,1};
116         int[] array1={1,2,3,4,5,6,7};
117         int[] array2={7,6,5,4,3,2,1};
118 
119         for(int i=0;i<array.length;i++){
120             t.inseart(t.root,array[i]);
121         }
122         System.out.print("排序后的序列: ");t.inOrder(t.root);
123         System.out.println();
124         t.printTree(t.root);
125 
126         for(int i=0;i<array.length;i++){
127             t1.inseart(t1.root,array1[i]);
128         }
129         System.out.print("排序后的序列: ");t1.inOrder(t1.root);
130         System.out.println();
131         t1.printTree(t1.root);
132 
133         for(int i=0;i<array.length;i++){
134             t2.inseart(t.root,array2[i]);
135         }
136         System.out.print("排序后的序列: ");t2.inOrder(t2.root);
137         System.out.println();
138         t2.printTree(t2.root);
139 
140     }
141     
142     
143     
144 }
View Code

 

 

2.2,完整二叉查找树

       排序功能涉及了二叉查找树的插入功能,还有查找,删除功能

查找功能比较简单,二叉遍历一遍,主要是删除功能,比较复杂

/**删除
* ①删除最小/大值,最小/大值-最左/右节点
* -空树
* -只有一个根节点
* -根节点无左/右子树(删除根节点)
* -有左/右子树且非空
*
* ②删除一个节点,-树空
* -是否在树中
* -无左右节点,直接删
* -有左节点(只有左子树),删除左子树的最大节点-返回最大节点,
* 将返回的节点代替被删节点
* -只要有右节点,删除右子树的最小值,将返回的节点代替被删节点
*/

完整代码
  1 //https://www.cnblogs.com/songdechiu/p/6821168.html
  2 //转载一个老哥,太猛了-(key,value)
  3 //这篇也不错---(value)
  4 //https://zhuanlan.zhihu.com/p/84517029
  5 
  6 import java.util.LinkedList;
  7 import java.util.Queue;
  8 
  9 /**二叉查找树-完成的
 10  * 建树-就是不停插入(二叉排序树简单铺垫了,直接复制过来)
 11  * 插入
 12  *
 13  * 查找
 14  *
 15  * 删除
 16  */
 17 
 18 public class SearchBiTree {
 19     private Node root=null;
 20 
 21 
 22     /**
 23      * 打印等辅助函数
 24      */
 25     //递归求树高-用于打印树
 26     //递归
 27     public int treeHeightRec(Node root){
 28         if(root==null||root.data==Integer.MAX_VALUE)
 29             return 0;
 30         else{
 31             int a =treeHeightRec(root.lchild);
 32             int b = treeHeightRec(root.rchild);
 33             return (a>b)?(a+1):(b+1);
 34         }
 35     }
 36     //打印树--233,复制前一篇的方法,如果树层数很深时,打印的比较别扭
 37     public void printTree(Node root){
 38         int H=treeHeightRec(root);
 39         int h=H;
 40         //System.out.println("树高:"+H);
 41         if(H==0)
 42             System.out.println("树空,无打印");
 43         else{
 44             System.out.println("打印树:");
 45             Queue<Node> queue=new LinkedList<>();
 46             queue.add(root);
 47             int height=1;
 48             //记录每层孩子个数
 49             int len=1;
 50             while(h>0){
 51                 int length=0;
 52                 String space="";
 53                 for(int i=0;i<(((Math.pow(2,H)+1)*3)/(Math.pow(2,height)+1));i++)
 54                     space+=" ";
 55                 for(int i=0;i<len;i++){
 56                     Node curroot=queue.poll();
 57                     if(curroot.data==Integer.MAX_VALUE){
 58                         System.out.print(space);
 59                     }else
 60                         System.out.print(space+curroot.data);
 61 
 62                     if(curroot.lchild!=null){
 63                         queue.add(curroot.lchild);
 64                     }
 65                     else
 66                         queue.add(new Node());
 67                     length++;
 68                     if(curroot.rchild!=null){
 69                         queue.add(curroot.rchild);
 70                     }
 71                     else
 72                         queue.add(new Node());
 73                     length++;
 74                 }
 75                 System.out.println();
 76                 System.out.println();
 77                 len=length;
 78                 height++;
 79                 h--;
 80             }
 81             System.out.println();
 82         }
 83     }
 84     //中序遍历
 85     public void inOrder(Node root){
 86         if(root==null)
 87             return;
 88         inOrder(root.lchild);
 89         System.out.print(root.data+" ");
 90         inOrder(root.rchild);
 91     }
 92 
 93 
 94     /**
 95      * 以下为新加内容
 96      */
 97     //查找--是否存在
 98     public boolean isExit(Node root,int data){
 99         if(root==null)//树空
100             return false;
101         if(root.data==data)
102             return true;
103         else if(data<root.data){
104             if(root.lchild==null)
105                 return false;
106             else
107                 return isExit(root.lchild,data);
108         }else{
109             if(root.rchild==null)
110                 return false;
111             else
112                 return isExit(root.rchild,data);
113         }
114     }
115     //插入-先搜索,不存在则插入,
116     public void inseart(Node root,int data){
117         if(!isExit(root,data))
118             //System.out.println(root.data);
119             if(root==null)
120                 this.root=new Node(data);
121             else{
122                 //元素不能重复,
123                 if(data<root.data){
124                     if(root.lchild==null){
125                         root.lchild=new Node(data);
126                     }
127                     else{
128                         inseart(root.lchild,data);
129                     }
130                 }
131                 else{
132                     if(root.rchild==null){
133                         root.rchild=new Node(data);
134                     }else
135                         inseart(root.rchild,data);
136                 }
137             }
138         else
139             System.out.println(data+"已在排序树中");
140     }
141 
142     /**删除
143      * ①删除最小/大值,最小/大值-最左/右节点
144      *                -空树
145      *                -只有一个根节点
146      *                -根节点无左/右子树(删除根节点)
147      *                -有左/右子树且非空
148      *
149      * ②删除一个节点,-树空
150      *                -是否在树中
151      *                -无左右节点,直接删
152      *                -有左节点(只有左子树),删除左子树的最大节点-返回最大节点,
153      *                   将返回的节点代替被删节点
154      *                -只要有右节点,删除右子树的最小值,将返回的节点代替被删节点
155      */
156     //删除最小值
157     public Node deleteMin(Node root){
158         //空树
159         if(root==null){
160             System.out.println("树空,无最小值");
161             return null;
162         }
163         //只有一个根节点
164         else if(root.lchild==null&&root.rchild==null){
165             this.root=null;
166             return root;
167         }
168         //根节点无左子树(删除根节点)
169         else if(root.lchild==null){
170             Node n=new Node(root.data);
171             root.data=root.rchild.data;
172             root.lchild=root.rchild.lchild;
173             root.rchild=root.rchild.rchild;
174             return n;
175         }
176         //有左子树且非空
177         Node preNode=new Node();
178         while(root.lchild!=null){
179             preNode=root;
180             root=root.lchild;
181         }
182         preNode.lchild=root.rchild;
183         return root;
184     }
185     //删除最大值
186     public Node deleteMax(Node root){
187         //空树
188         if(root==null){
189             System.out.println("树空,无最大值");
190             return null;
191         }
192         //只有一个根节点
193         else if(root.lchild==null&&root.rchild==null){
194             this.root=null;
195             return root;
196         }
197         //根节点无右子树(删除根节点)
198         else if(root.rchild==null){
199             Node n=new Node(root.data);
200             root.data=root.lchild.data;
201             root.lchild=root.lchild.lchild;
202             root.rchild=root.lchild.rchild;
203             return n;
204         }
205         //有右子树且非空
206         Node preNode=new Node();
207         while(root.rchild!=null){
208             preNode=root;
209             root=root.rchild;
210         }
211         preNode.rchild=root.lchild;
212         return root;
213     }
214     //删除一个值
215     public void delete(Node root,int data){
216         //在树中(树非空)
217         if(!isExit(root,data)){
218             System.out.println("值不在树中");
219         }
220         //只有一个节点-即删除根节点
221         if(root.lchild==null&&root.rchild==null){
222             this.root=null;
223         }
224         //先遍历到节点,在删除-将替换节点的值赋给该节点,
225         //记录被删节点何其前驱节点-非递归遍历法
226         else{
227             Node preNode=root;
228             String lORr="";//记录前驱节点的哪个孩子时待删节点
229             while(root.data!=data){
230                 if(data<root.data){
231                     preNode=root;
232                     lORr="l";
233                     root=root.lchild;
234                 }
235                 else if(data>root.data){
236                     preNode=root;
237                     lORr="r";
238                     root=root.rchild;
239                 }
240             }
241             //此时root即待删除节点;
242             //该节点无子节点
243             if(root.lchild==null&&root.rchild==null){
244                 if(lORr=="l")
245                     preNode.lchild=null;
246                 else
247                     preNode.rchild=null;
248             }
249             //只有左子节点
250             else if(root.lchild!=null&&root.rchild==null){
251                 //如果左子节点是叶子节点--因为根节点表示问题,左子树只有根节点,数据是写入特殊值Integer.MAX_VALUE
252                 //而不是删掉=null
253                 if(root.lchild.lchild==null&&root.lchild.rchild==null){
254                     if(lORr=="l")
255                         preNode.lchild=root.lchild;
256                     else
257                         preNode.rchild=root.lchild;
258                 }else{
259                     Node replaceNode=deleteMax(root.lchild);
260                     root.data=replaceNode.data;
261                 }
262             }
263             //有右子节点
264             else if(root.rchild!=null){
265                 if(root.rchild.lchild==null&&root.rchild.rchild==null){
266                     if(lORr=="l"){
267                         preNode.lchild=root.rchild;
268                         root.rchild.lchild=root.lchild;//接替root的左子树;
269                     }
270                     else{
271                         preNode.rchild=root.rchild;
272                         root.rchild.lchild=root.lchild;
273                     }
274                 }else{
275                     Node replaceNode=deleteMin(root.rchild);
276                     root.data=replaceNode.data;
277                 }
278             }
279 
280 
281         }
282     }
283     public static void main(String args[]) {
284         SearchBiTree t=new SearchBiTree();
285         int[] array={8,4,6,16,14,18,2};
286 
287         for(int i=0;i<array.length;i++){
288             t.inseart(t.root,array[i]);
289         }
290         System.out.print("排序后的序列: ");t.inOrder(t.root);
291         System.out.println();
292         t.printTree(t.root);
293 
294         t.inseart(t.root,12);
295         t.inseart(t.root,5);
296         t.printTree(t.root);
297         t.inseart(t.root,16);
298         t.inseart(t.root,13);
299         t.printTree(t.root);
300         t.delete(t.root,14);
301         t.printTree(t.root);
302 
303 
304         System.out.println(t.deleteMax(t.root).data);
305         t.printTree(t.root);
306         t.deleteMin(t.root);
307         t.printTree(t.root);
308 
309         /**
310          * 删除
311          */
312 
313         SearchBiTree t2=new SearchBiTree();
314         t2.printTree(t2.root);
315         t2.inseart(t2.root,2);
316         t2.printTree(t2.root);
317         t2.deleteMin(t2.root);
318         t2.printTree(t2.root);
319         t2.inseart(t2.root,11);
320         t2.inseart(t2.root,10);
321         t2.inseart(t2.root,9);
322         t2.inseart(t2.root,8);
323         t2.printTree(t2.root);
324 
325         System.out.println(t2.deleteMax(t2.root).data);
326         t2.printTree(t2.root);
327 
328 
329 
330 
331     }
332 }
View Code

 

posted on 2020-09-20 12:39  呵呵哒9876  阅读(221)  评论(0)    收藏  举报