一。用JAVA写二叉树
public class BinaryTree { Node root; //得到树的深度 public Integer getHeight(){ return getHeight(root); } private Integer getHeight(Node node){ if(node==null) return 0; else{ int left=getHeight(node.getLeftChildTree()); int right=getHeight(node.getRightChildTree()); return left>right?left+1:right+1;//左子树 右子树最深的,再加上父节点本身深度1 } } //得到节点数量 public Integer getSize(){ return getSize(root); }; private Integer getSize(Node node){ if(node==null) return 0; else{ int leftSize=getSize(node.getLeftChildTree()); int rightSize=getSize(node.getRightChildTree()); return leftSize+rightSize+1; } } //前序遍历,迭代 public void preOrder(Node node){ if(node==null) return; else{ System.out.println("preOrder"+node.getData()); preOrder(node.getLeftChildTree()); preOrder(node.getRightChildTree()); } } //中序遍历,迭代 public void midOrder(Node node){ if(node==null) return; else{ midOrder(node.getLeftChildTree()); System.out.println("midOrder"+node.getData()); midOrder(node.getRightChildTree()); } } //后序遍历,迭代 public void proOrder(Node node){ if(node==null) return; else{ proOrder(node.getLeftChildTree()); proOrder(node.getRightChildTree()); System.out.println("proOrder"+node.getData()); } } //前序遍历,非迭代,利用栈,要遍历一个节点,就先把它压入,再弹出,输出数据,把此节点的右节点压入,再把左节点压入 public void nonRecOrder(Node node){ if(node==null) return; Stack<Node>stack=new Stack<>(); stack.push(root); while(!stack.isEmpty()){ Node pop = stack.pop(); System.out.println("nonRecOrder:"+pop.getData()); if(pop.getRightChildTree()!=null)//不要把空节点push栈 stack.push(pop.getRightChildTree()); if(pop.getLeftChildTree()!=null) stack.push(pop.getLeftChildTree()); } } /** * A * B C * D E F */ public BinaryTree(){ root=new Node("A"); Node nodeB=new Node("B"); Node nodeC=new Node("C"); Node nodeD=new Node("D"); Node nodeE=new Node("E"); Node nodeF=new Node("F"); nodeB.setLeftChildTree(nodeD); nodeB.setRightChildTree(nodeE); nodeC.setRightChildTree(nodeF); root.setLeftChildTree(nodeB); root.setRightChildTree(nodeC); } public class Node<T>{ private Integer index; private Node leftChildTree; private Node rightChildTree; private T data; public Integer getIndex() { return index; } public void setIndex(Integer index) { this.index = index; } public Node getLeftChildTree() { return leftChildTree; } public void setLeftChildTree(Node leftChildTree) { this.leftChildTree = leftChildTree; } public Node getRightChildTree() { return rightChildTree; } public void setRightChildTree(Node rightChildTree) { this.rightChildTree = rightChildTree; } public T getData() { return data; } public void setData(T data) { this.data = data; } public Node(T data){ this.data=data; leftChildTree=null; rightChildTree=null; } } public static void main(String[] args) { BinaryTree tree=new BinaryTree(); System.out.println("treeHeight"+tree.getHeight()); System.out.println("treeSize"+tree.getSize()); tree.preOrder(tree.root); tree.midOrder(tree.root); tree.proOrder(tree.root); tree.nonRecOrder(tree.root); } }
二。建立二叉树
用前序遍历反向生成二叉树
/** * A * B C * D # E * # # # F * * ABD###CE#F 用队列 */ public void creatBinaryTree(LinkedList<String> data){ creatBinaryTree(0,data); } private Node creatBinaryTree(int index,LinkedList<String> data){ if(data.isEmpty()){return null;} String d = data.pop(); Node node=new Node<String>(d); if(d==null){ return null; } if(index==0){ root=node; } if(d.equals("#")){ return null; } node.leftChildTree=creatBinaryTree(++index,data); node.rightChildTree=creatBinaryTree(++index,data); return node; } public static void main(String[] args) { BinaryTree tree=new BinaryTree(); LinkedList l=new LinkedList(); String []data=new String[]{"A","B","D","#","#","#","C","E","#","F"}; for(String d:data){ l.offer(d); } tree.creatBinaryTree(l); tree.preOrder(tree.root); }
三。树、森林、二叉树的转换
1树转换为二叉树
2森林转化为二叉树
3二叉树转换为树
4二叉树转换为森林
四。赫夫曼树用于数据压缩
1赫夫曼树
带权的节点:比例40的是70-90分的人,判断1个人的分数要走一遍路径,判断40个人路径长就得乘40
2赫夫曼树的构造
3赫夫曼编码
五。遍历树中元素,put新元素
之前数据是泛型,现在用Integer,方便对比。
数据比父节点数据小的放在左子树,数据比父节点数据大的放右子树,树中的数据按此排序的,则查询节省效率,类似二分法
/** * 30 * 20 40 * 10 25 35 50 * @param data * @return */
public class Node<T>{ private Integer index; private Node<T> leftChildTree; private Node<T> rightChildTree; private Node<T> parent; //父节点 private T data; }
private Node<Integer>put(Integer data){ if (data==null) return null; Node<Integer> node=new Node<Integer>(data); if(root==null){ root=node; return node; } node = root; Node <Integer> parent=null; while(node!=null){ parent=node; if(node.data>data){ node=node.leftChildTree; } else if(node.data<data){ node=node.rightChildTree; }else{ return node; } } node=new Node<Integer>(data); node.parent=parent; if(parent.data>data){ parent.leftChildTree=node; }else{ parent.rightChildTree=node; } return node; }
六。遍历通过数据找到节点、删除节点
public Node getNodeByData(Integer data){ if(data==null||root==null) return null; Node <Integer>node=root; while (node!=null){ //System.out.println(node.data); if(node.getData().equals(data)){ return node; }else if(node.data>data){ node=node.leftChildTree; }else{ node=node.rightChildTree; } } return null; }
得到某个数据节点下的树
public void anyPreOrder(Integer data){ Node nodeByData = getNodeByData(data); preOrder(nodeByData); }
删除某节点
public Integer delete(Integer data){ Node node = getNodeByData(data); if(node==null){ return null; } List<Integer>list=new ArrayList<>(); Node parent=node.parent; if(parent.leftChildTree==node){//要删除节点的父节点 关系中断 parent.leftChildTree=null; }else{ parent.rightChildTree=null; } getDataPreOrder(list, node); list.remove(data); for(Integer i:list){ //把数据重新放一次 put(i); } return data; } //找到某节点下的所有数据放在list,旧节点属性置空 private void getDataPreOrder(List list,Node node){ if (node==null) return; node.parent=null; list.add(node.getData()); getDataPreOrder(list, node.leftChildTree); node.leftChildTree=null; getDataPreOrder(list, node.rightChildTree); node.rightChildTree=null; node.data=null; }