树同时具有链表和数组的优点,关于树的术语有:
根:树顶端的节点
父节点:当前节点与之相连的上一层的节点
子节点:与当前节点直接相连的下一层节点的所有节点
叶子节点:没有子节点的节点
这里写一下相关代码:
树那个节点所对应的数据结构
//节点对象类,包含数据
public class Node {
public int iData;//key value
public double dData;
public Node leftChild;//the Node's left child
public Node rightChild;//the Node's right child
public void displayNode(){
System.out.print('{');
System.out.print(iData);
System.out.print(",");
System.out.print(dData);
System.out.print("}");
}
}
public class Node {
public int iData;//key value
public double dData;
public Node leftChild;//the Node's left child
public Node rightChild;//the Node's right child
public void displayNode(){
System.out.print('{');
System.out.print(iData);
System.out.print(",");
System.out.print(dData);
System.out.print("}");
}
}
//将数据插到树中
public void inser(int id,double dd){
Node newNode=new Node();//创建一个新节点
newNode.iData=id;
newNode.dData=dd;
if(root==null)
root=newNode;
else{
Node current=root;
Node parent;
while(true){
parent=current;
if(id<current.iData){//查找左子树
current=current.leftChild;
if(current==null){
parent.leftChild=newNode;
return;
}
}else{
current=current.rightChild;
if(current==null){
parent.rightChild=newNode;
return;
}
}
}
}
}
Node newNode=new Node();//创建一个新节点
newNode.iData=id;
newNode.dData=dd;
if(root==null)
root=newNode;
else{
Node current=root;
Node parent;
while(true){
parent=current;
if(id<current.iData){//查找左子树
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) {//delete node with given key
Node current=root;//assume the tree isn't empty
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;
}
}
//found node to delete
//if there is no children,just delete it
if(current.leftChild==null&¤t.rightChild==null){
if(current==root){
root=null;
}else if(isLeftChild){
parent.leftChild=null;
}else{
parent.rightChild=null;
}
} else if(current.rightChild==null){//if no right child replace with left subtree
if(current==root){
root=null;
}else if(isLeftChild){
parent.leftChild=current.leftChild;
}else{
parent.rightChild=current.leftChild;
}
}else if(current.leftChild==null){//id no left child replace with right subtree
if(current==root){
root=null;
}else if(isLeftChild){
parent.leftChild=current.rightChild;
}else{
parent.rightChild=current.leftChild;
}
}else{//如果左节点和右节点都有
//get successor of node to delete
Node successor=getSuccessor(current);
if(current==root){
root=successor;
}else if(isLeftChild){
parent.leftChild=successor;
}else{
parent.rightChild=successor;
}
successor.leftChild=current.leftChild;
}
return true;
}
//找后继节点
private Node getSuccessor(Node deleteNode){
Node successorParent=deleteNode;
Node successor=deleteNode;
Node current=deleteNode.rightChild;
while(current!=null){
successorParent=successor;
successor=current;
current=current.leftChild;
}
if(successor!=deleteNode.rightChild){
successorParent.leftChild=successor.rightChild;
successor.rightChild=deleteNode.rightChild;
}
/*
* 当找到要替换的节点(该节点的左子节点是空的)以后,需要把该节点的右子节点给该节点的父节点的左子节点
* 然后因为要剩下的节点所对应的数值都比这个要替换的节点大,所以要把要删除节点的右子节点给找到的节点的右子节点
*/
return successor;
}
--接下来就是遍历,遍历有先序、后序、中序遍历可以通过递归直接遍历
public boolean delete(int key) {//delete node with given key
Node current=root;//assume the tree isn't empty
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;
}
}
//found node to delete
//if there is no children,just delete it
if(current.leftChild==null&¤t.rightChild==null){
if(current==root){
root=null;
}else if(isLeftChild){
parent.leftChild=null;
}else{
parent.rightChild=null;
}
} else if(current.rightChild==null){//if no right child replace with left subtree
if(current==root){
root=null;
}else if(isLeftChild){
parent.leftChild=current.leftChild;
}else{
parent.rightChild=current.leftChild;
}
}else if(current.leftChild==null){//id no left child replace with right subtree
if(current==root){
root=null;
}else if(isLeftChild){
parent.leftChild=current.rightChild;
}else{
parent.rightChild=current.leftChild;
}
}else{//如果左节点和右节点都有
//get successor of node to delete
Node successor=getSuccessor(current);
if(current==root){
root=successor;
}else if(isLeftChild){
parent.leftChild=successor;
}else{
parent.rightChild=successor;
}
successor.leftChild=current.leftChild;
}
return true;
}
//找后继节点
private Node getSuccessor(Node deleteNode){
Node successorParent=deleteNode;
Node successor=deleteNode;
Node current=deleteNode.rightChild;
while(current!=null){
successorParent=successor;
successor=current;
current=current.leftChild;
}
if(successor!=deleteNode.rightChild){
successorParent.leftChild=successor.rightChild;
successor.rightChild=deleteNode.rightChild;
}
/*
* 当找到要替换的节点(该节点的左子节点是空的)以后,需要把该节点的右子节点给该节点的父节点的左子节点
* 然后因为要剩下的节点所对应的数值都比这个要替换的节点大,所以要把要删除节点的右子节点给找到的节点的右子节点
*/
return successor;
}
--接下来就是遍历,遍历有先序、后序、中序遍历可以通过递归直接遍历
public void traverse(int traverseType){
switch(traverseType){
case 1: System.out.println("Preorder traversal:");
preOrder(root);
break;
case 2: System.out.println("Inorder traversal");
inOrder(root);
break;
case 3: System.out.println("postorder traversal");
postOrder(root);
break;
}
}
//先序遍历
private void preOrder(Node localRoot){
if(localRoot!=null){
System.out.println(localRoot.iData+ " ");
preOrder(localRoot.leftChild);
preOrder(localRoot.rightChild);
}
}
//中序遍历
private void inOrder(Node localRoot){
if(localRoot!=null){
inOrder(localRoot.leftChild);
System.out.println(localRoot.iData+" ");
inOrder(localRoot.rightChild);
}
}
//后序遍历
private void postOrder(Node localRoot){
if(localRoot!=null){
postOrder(localRoot.leftChild);
postOrder(localRoot.rightChild);
System.out.println(localRoot.iData+" ");
}
}
switch(traverseType){
case 1: System.out.println("Preorder traversal:");
preOrder(root);
break;
case 2: System.out.println("Inorder traversal");
inOrder(root);
break;
case 3: System.out.println("postorder traversal");
postOrder(root);
break;
}
}
//先序遍历
private void preOrder(Node localRoot){
if(localRoot!=null){
System.out.println(localRoot.iData+ " ");
preOrder(localRoot.leftChild);
preOrder(localRoot.rightChild);
}
}
//中序遍历
private void inOrder(Node localRoot){
if(localRoot!=null){
inOrder(localRoot.leftChild);
System.out.println(localRoot.iData+" ");
inOrder(localRoot.rightChild);
}
}
//后序遍历
private void postOrder(Node localRoot){
if(localRoot!=null){
postOrder(localRoot.leftChild);
postOrder(localRoot.rightChild);
System.out.println(localRoot.iData+" ");
}
}