二叉树的操作及三种遍历递归非递归

本文介绍了二叉搜索树的基本性质,包括左子节点值小于根节点、右子节点值大于根节点等。讨论了如何用链表表示二叉树,并详细阐述了二叉树的插入操作,包括递归方法。此外,还讲解了非递归遍历二叉树的堆栈方法,查找元素的迭代过程,以及查找最大和最小元素的方法。最后,探讨了二叉树节点删除的三种情况,包括删除叶节点、单子节点和双子节点的情况。
摘要由CSDN通过智能技术生成

二叉搜索树

二叉搜索树的性质

1.若任意节点的左子树不空,则左子树上所有节点的值均小于它的根节点的值;
2.若任意节点的右子树不空,则右子树上所有节点的值均大于它的根节点的值;
3.任意节点的左,右子树也分别为二叉搜索树;
4. 没有键值相等的节点。

代码表示二叉树

使用链表来存储二叉树

public class BinTree
{ // 二叉树类
    public bintree left;
    public bintree right;
    public bintree root;
       //    数据域
    private Object data;
       
    }



    

二叉树的函数

创建插入
 public void insert(int key)
    {    
        Node p=new Node(); //待插入的节点
        p.data=key;
        
        if(root==null)
        {
            root=p;
        }
        else
        {
            Node parent=new Node();
            Node current=root;
            while(true)
            {
                parent=current;
                if(key>current.data)    
                {
                    current=current.right; // 右子树
                    if(current==null)
                    {
                        parent.right=p;
                        break;
                    }
                }
                else //本程序没有做key出现相等情况的处理,暂且假设用户插入的节点值都不同
                {
                    current=current.left; // 左子树
                    if(current==null)
                    {
                        parent.left=p;
                        return;
                    }
                }
            }
        }
    }
递归的方法 二叉树的插入

有返回的类型,返回的是一个 插入后的树


pubilc BinTree Insert(int key,BinTree BST){
    
     if(BST==null){
     //是空树的话创建一个新的树并返回
            BST=new BinTree();
            BST.data=key;
            BST.left=BST.right=null;
      }
      else{
             if(key<BST.data)
                    BST.left=Insert(key, BST.left);
             else if(key>BST.data)
                    BST.right=Insert(key, BST.right);
               //else  key相等,就什么也不做
            }
       return BST;
二叉树的遍历
// 用递归的方法进行先序遍历
    public void xinaxuDigui(TreeNode treeNode) {
        if (treeNode != null) {
            System.out.printf(treeNode.data)
            xinaxuDigui(treeNode.left); 
            xinaxuDigui(treeNode.right);
        }
    }

    // 用递归的方法进行中序遍历
    public void zhongxuDigui(TreeNode treeNode) {
        if (treeNode!= null) {
            zhongxuDigui(treeNode.left);
        
         System.out.printf(treeNode.data)
      
            zhongxuDigui(treeNode.right);
        }
    }

    // 用递归的方法进行后序遍历
    public void houxuDigui(TreeNode treeNode) {
        if (treeNode != null) {
            houxuDigui(treeNode.left);
     
            houxuDigui(treeNode.right);
        
         System.out.printf(treeNode.data)
         }
    }

非递归的遍历
使用堆栈

// 用非递归的方法进行先序遍历
    public void qinaxuFeiDigui(TreeNode treeNode) {
        Stack<TreeNode> stack = new Stack<TreeNode>();
        while (treeNode != null || !stack.isEmpty()) {
            while (treeNode != null) {
                 System.out.printf(treeNode.data);
                stack.push(treeNode);
                treeNode = treeNode.left;
            }
            if(!stack.isEmpty()){
                treeNode = stack.pop();
                treeNode = treeNode.right;
            }
        }
    }

    // 用非递归的方法进行中序遍历
    public void zhongxuFeiDigui(TreeNode treeNode) {
        Stack<TreeNode> stack = new Stack<TreeNode>();
        while (treeNode != null || !stack.isEmpty()) {
            while (treeNode != null) {
                stack.push(treeNode);
                treeNode = treeNode.left;
            }
            if (!stack.isEmpty()) {
                treeNode = stack.pop();
                 System.out.printf(treeNode.data);
                treeNode = treeNode.right;
            }
        }
    }

    // 用非递归的方法进行后序遍历
    public void houxuFeiDigui(TreeNode treeNode) {
        Stack<TreeNode> stack = new Stack<TreeNode>();
        while (treeNode != null || !stack.isEmpty()) {
            while (treeNode != null) {
                stack.push(treeNode);
                treeNode = treeNode.left;
            }
            boolean tag = true;
            TreeNode preNode = null;  // 前驱节点
            while (!stack.isEmpty() && tag == true) {
                treeNode = stack.peek();
                if (treeNode.right == preNode) { // 之前访问的为空节点或是栈顶节点的右子节点
                    treeNode = stack.pop();
                     System.out.printf(treeNode.data)if (stack.isEmpty()) {
                        return;
                    } else {
                        preNode = treeNode;
                    }
                } else {
                    treeNode = treeNode.right;
                    tag = false;
                }
            }
        }
    }
非递归的另一种模板遍历
     while( 栈非空 || p 非空){

               if( p 非空){
               
               }else{

               }
     }

中序遍历
class Solution {
    public List<Integer> inorderTraversal(TreeNode root) {
      List<Integer> a = new ArrayList<>();
      Stack<TreeNode> stack = new  Stack<>();
      if(root == null)
          return a;
      while(!stack.isEmpty() || root != null){
          if(root != null){
              stack.push(root);
               root = root.left;
           }
          else{   
               root = stack.pop();
               a.add(root.val);
               root = root.right;  
            } 
          } 
        return a;   
      }
    
}

后序遍历
class Solution {
  public List<Integer> postorderTraversal(TreeNode root) {
  List<Integer> res = new ArrayList<>();
          if(root ==  null)
             return res;
          Stack<TreeNode> stack = new Stack<>();
           TreeNode r = null;   //标记结点的右子树是否访问过
          while(!stack.isEmpty() || root != null){
                  if (root != null) { //这里一直while循环到最左边结点
                     stack.push(root);
                     root = root.left;
                   }else{
                       
                       root = stack.peek();
                       if(root.right == null || root.right == r){//判断结点右子树状态,是空或者已经访问过,满足就可以访问根结点。
                           res.add(root.val);
                           stack.pop();
                           r = root;
                           root = null;
                       }else
                          root = root.right;
                   }               
           }
           return res;
    }   
}
二叉树的查找

在二叉查找树中查找x的过程如下

  • 若二叉树是空树,则查找失败。

  • 若x等于根结点的数据,则查找成功。

  • 若x小于根结点的数据,则递归查找其左子树,否则,递归查找其右子树。

public Bintree Find(int x,BinTree BST){
       if(BST==null)  return null;
       if(x>BST.data)   return  Find(x,BST.right);
       else if(x<BST.data)  return Finf(x,BST,left);
       else(x==BST.data)  return BST;
    }
    //返回的是找到结点的所在地址

迭代查找

public Bintree Find(int x,BinTree BST){
    while(BST!=null){
          if(x>BST.data)
                 BST=BST.right;
          else if(x<BST.data)
                 BST=BST.left;
           else
                 return  BST;
          }
     rerutn null;
  }
查找最大最小元素
public Node FindMax(BinTree T){
           if(T==null)  return null;
           else if(T.right==null)  return T;
           else   return FindMax(T.right);
}



public Node FindMin(BinTree T){
     if(T!=null){
            while(T.left!=null)     T=T.left;
            return T;     
     }esle    return null;
  }
二叉树的删除

考虑三种情况
1.删除的是叶节点
直接删除也叶结点,然后修改其父结点的 指针 为null。
2.删除的是只有一个儿子的节点
将其父结点的指针指向要删除结点的孩子结点
3.删除的是有俩个儿子的节点。
用右子树的最小元素或左子树的最大元素来替换掉这个结点。

用非递归方法


public boolean delete(int key,Bintree root) {
//俩个变量,一个是代表删除的那个结点,一个代表删除结点的父节点
 Node current = root;
 Node parent = root;
 boolean isLeftChild = false;
 //判别结点是左儿子还是右儿子
 while(current.data != key){
     parent = current;
     if(current.data > key){
         isLeftChild = true;
         current = current.leftChild;
     }else{
         isLeftChild = false;
         current = current.rightChild;
     }
     if(current == null){
         return false;
     }
     return true;
 }   
 这就找到了删除的那个结点 current
 
 //如果当前节点没有子节点
 if(current.leftChild == null && current.rightChild == null){
 //检查是否为根结点
     if(current == root){
         root = null;
     }else if(isLeftChild){
         parent.leftChild = null;
     }else{
         parent.rightChild = null;
     }
     return true;
 }
 return false;
} 





//当前节点有一个子节点

if(current.leftChild == null && current.rightChild != null){

 if(current == root){

     root = current.rightChild;

 }else if(isLeftChild){

     parent.leftChild = current.rightChild;

 }else{

     parent.rightChild = current.rightChild;

 }

 return true;

}else{

 //current.leftChild != null && current.rightChild == null

 if(current == root){

     root = current.leftChild;

 }else if(isLeftChild){

     parent.leftChild = current.leftChild;

 }else{

     parent.rightChild = current.leftChild;

 }

 return true;

}

递归方法

public Bintree Delete(int x, Bintree T){
     
     if(T==null)  
          System.out.println("未找到元素");
     else if(x<T.data)
            T.left=Delete(x, T.left);
     else if (x>T.data)
            T.right=Delete(x,T.right);
     else (x==T.data){
            if(T.left!=null && T.right!=null){  //俩个孩子结点
                   T.data=FindMin(T.rihgt).data;
                    T.right=Delete(T.data, T.right);
            }else {    //一个孩子结点或者无孩子结点
                     
                if(T.left==null)
                      T=T.right;
                 else(T.right==null)
                      T=T.left
              }
     }
     return T;
 } 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值