树(二叉树的插入删除查找遍历)
Posted S-Mustard
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了树(二叉树的插入删除查找遍历)相关的知识,希望对你有一定的参考价值。
树:由边连着节点而构成
根:树顶端的节点称为根,一棵树只有一个根
父节点:每个节点(除了根)都恰好有一条边向上连接到另一个节点,上面的这个节点就称为下面的节点的父节点
子节点:每个节点都可能有一条或多条向下连接的其他节点,下面的这些节点成为它的子节点
叶子节点:没有子节点的节点称为叶子节点
子树:每个节点都可以作为子树的根
二叉树:每个节点最多只能有两个节点
查询,插入,删除都很快(跟数组和链表相比)
public class Node { public int iData;//节点值(整数) public double dData;//节点值(小数) public Node leftChild;//子节点(左) public Node rightChild;//子节点(右) public void displayNode() {//以{iData,dData}的方式输出值 System.out.print(‘{‘); System.out.print(iData); System.out.print(‘,‘); System.out.print(dData); System.out.print(‘}‘); } }
import java.util.Stack; public class Tree { private Node root;//根节点 public Tree() { root=null; } //插入值 public void insert(int id,double dd) { Node newNode=new Node(); newNode.iData=id; newNode.dData=dd; if(root==null) { root=newNode; }else { Node current=root;//current标志当前节点 Node parent;//parent标志当前节点发生变化后,之前的current节点就是父节点. while(true) { parent=current; if(id<current.iData) {//如果id是小的,就往左边找位置 current=current.leftChild;//一直往左边找,循环,直到左边没有找的了 if(current==null) {//即找到位置(循环的出口) parent.leftChild=newNode;//插入数据 return; } }else {//向右边找 current=current.rightChild; if(current==null) { parent.rightChild=newNode; return; } } } } } //删除 public boolean delete(int key) { Node current=root; Node parent=root; boolean isLeftChild=true; while(current.iData!=key) {//找节点 parent=current; if(key<current.iData) { isLeftChild=true; current=current.leftChild; }else { isLeftChild=false; current=current.rightChild; } if(current==null) return false;//没找到 } //删除 if(current.leftChild==null && current.rightChild==null) {//删除的是叶子结点 if(current==root) root=null;//删的是根(1) else if(isLeftChild) {//删除的是左子叶子 parent.leftChild=null;//(2) }else {//删除的是右子叶子 parent.rightChild=null;//(3) } }else if(current.rightChild==null) {//删除的节点不是叶子结点,然后删除的是只有左子树 if(current==root)//(4) root=current.leftChild;//只用将根节点的左子节点标记为root就ok else if(isLeftChild)//(5) parent.leftChild=current.leftChild;//如果当前结点是父节点的左子节点,只用将父节点的左子节点标记为当前节点的左子节点 else //(6) parent.rightChild=current.leftChild;//如果当前节点是父节点的右子节点,只用将父节点的有子节点标记为当前节点的左子节点 }else if(current.leftChild==null) {//要删的节点只有右子树(与上面方法一样) if(current==root)//只用将根节点的右子节点标记为root就ok root=current.rightChild;//(7) else if(isLeftChild) parent.leftChild=current.rightChild;//(8) else parent.rightChild=current.rightChild;//(9) }else {//左右子树都有 Node successor=getSuccessor(current);//寻找继承者 if(current==root) root=successor;//如果当前结点是根(10) else if(isLeftChild)parent.leftChild=successor;//如果当前节点是左子节点(11) else parent.rightChild=successor;//(12) successor.leftChild=current.leftChild;//建立好替换后完整的树 } return true; } //查找 public Node find(int key) { Node current=root; while(current.iData!=key) { if(key<current.iData) { current=current.leftChild; }else { current=current.rightChild; } if(current==null) { return null; } } return current; } //遍历(三种方法) public void traverse(int traverseType) { switch(traverseType){ case 1: System.out.print("从上至下,从左至右:"); preOrder(root); break; case 2: System.out.print("从下至下,从左至右:"); inOrder(root); break; case 3: System.out.print("从下至上,从右至左:"); postOrder(root); break; } System.out.println(); } //找到继承者(树) private Node getSuccessor(Node delNode) { Node successorParent=delNode; Node successor=delNode;// Node current=delNode.rightChild;//临时变量 while(current!=null) { successorParent=successor; successor=current; current=current.leftChild;//找delNode节点的右子树的左子节点 } if(successor!=delNode.rightChild) {//将根为继承者的树建立好 successorParent.leftChild=successor.rightChild; successor.rightChild=delNode.rightChild; }//如果是叶子,就不要建立树 return successor;//返回继承者 } //从上至下,从左至右 private void preOrder(Node localRoot) { if(localRoot!=null) { System.out.print(localRoot.iData+" "); preOrder(localRoot.leftChild); preOrder(localRoot.rightChild); } } private void inOrder(Node localRoot) { if(localRoot!=null) { inOrder(localRoot.leftChild); System.out.print(localRoot.iData+" "); inOrder(localRoot.rightChild); } } private void postOrder(Node localRoot) { if(localRoot!=null) { postOrder(localRoot.leftChild); postOrder(localRoot.rightChild); System.out.print(localRoot.iData+" "); } } //显示一个树的结构 public void dispalyTree() { Stack globalStack=new Stack(); globalStack.push(root);//从这个栈里面要取的输出的值 int nBlanks=32;//空格数 boolean isRowEmpth=false; //树的开始分割线 System.out.println("................................"); while(isRowEmpth==false) {//当输出的节点有子节点时这个循环会继续执行 Stack localStack=new Stack();//本地栈(存入当前节点的子节点,里面循环结束最后都倒入globalStack中) isRowEmpth=true; for(int j=0;j<nBlanks;j++) System.out.print(" ");//左边加32个空格 while(!globalStack.isEmpty()) {//循环输出globalStack栈中的内容,每一次循环都将当前节点的子节点放入本地栈中 Node temp=(Node)globalStack.pop(); if(temp!=null) {//值为空就输出--,值不为空就输出值,并且值为空的节点肯定没有子节点。 System.out.print(temp.iData); localStack.push(temp.leftChild); localStack.push(temp.rightChild); if(temp.leftChild!=null||temp.rightChild!=null) isRowEmpth=false;//如果取出的值有子节点,就继续外层循环(如果当前节点没有子节点就不会进行下一次外层循环) }else {//空的数据项 System.out.print("--"); localStack.push(null); localStack.push(null); } for(int j=0;j<nBlanks*2-2;j++) { System.out.print(" "); } } System.out.println(); nBlanks/=2; while(!localStack.isEmpty()) { globalStack.push(localStack.pop()); } } //树的结束分割线 System.out.println("--------------------------------------"); } }
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; public class Test { public static void main(String[] agrs) throws IOException { int value; Tree theTree=new Tree(); theTree.insert(50, 1.5); theTree.insert(25, 1.5); theTree.insert(75, 1.5); theTree.insert(12, 1.5); theTree.insert(37, 1.5); theTree.insert(43, 1.5); theTree.insert(30, 1.5); theTree.insert(33, 1.5); theTree.insert(87, 1.5); theTree.insert(93, 1.5); theTree.insert(97, 1.5); while(true) { System.out.print("Enter first letter of show,isnert,find,delete,or traverse:"); int choice=getchar(); switch(choice){ case‘s‘: theTree.dispalyTree(); break; case ‘i‘: System.out.print("Enter value to insert:"); value=getInt(); theTree.insert(value, value+0.9); break; case ‘f‘: System.out.println("Enter value to find:"); value=getInt(); Node found=theTree.find(value); if(found!=null) { System.out.print("Found :"); found.displayNode(); System.out.println(); }else System.out.print("not"+value); break; case ‘d‘: System.out.print("Enter value todelete:"); value=getInt(); boolean didDelete=theTree.delete(value); if(didDelete)System.out.print("delete"+value); else System.out.print("not "+value); break; case ‘t‘: System.out.print("Enter 1,2 or 3:"); value=getInt(); theTree.traverse(value); break; default: System.out.println("无效的输入"); } } } public static String getString()throws IOException{ InputStreamReader isr=new InputStreamReader(System.in); BufferedReader br=new BufferedReader(isr); return br.readLine(); } public static char getchar() throws IOException{ return getString().charAt(0); } public static int getInt() throws IOException{ String s=getString(); return Integer.parseInt(s); } }
以上是关于树(二叉树的插入删除查找遍历)的主要内容,如果未能解决你的问题,请参考以下文章