数据结构和算法--二叉树学习

本文介绍了二叉树的遍历概念,包括先根遍历、中根遍历和后根遍历,并提供了对应的示例及算法代码实现,强调了中序遍历的常见应用。此外,还给出了遍历的时间复杂度分析。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

二叉树的遍历

对于二叉树来讲最主要、最基本的运算是遍历。
    遍历二叉树 是指以一定的次序访问二叉树中的每个结点。所谓 访问结点 是指对结点进行各种操作的简称。例如,查询结点数据域的内容,或输出它的值,或找出结点位置,或是执行对结点的其他操作。遍历二叉树的过程实质是把二叉树的结点进行线性排列的过程。假设遍历二叉树时访问结点的操作就是输出结点数据域的值,那么遍历的结果得到一个线性序列。

从二叉树的递归定义可知,一棵非空的二叉树由根结点及左、右子树这三个基本部分组成。因此,在任一给定结点上,可以按某种次序执行三个操作:
     (1)访问结点本身(N),
     (2)遍历该结点的左子树(L),
     (3)遍历该结点的右子树(R)。
以上三种操作有六种执行次序:
     NLR、LNR、LRN、NRL、RNL、RLN。
注意:
    前三种次序与后三种次序对称,故只讨论先左后右的前三种次序。

  由于被访问的结点必是某子树的根,所以N(Node)、L(Left subtlee)和R(Right subtree)又可解释为根、根的左子树和根的右子树。NLR、LNR和LRN分别又称为先根遍历、中根遍历和后根遍历。

树执行查找、删除、插入的时间复杂度都是O(logN)

举例:


 System.out.println("*******(前序遍历)[ABDECF]遍历*****************");  

 System.out.println("*******(中序遍历)[DBEACF]遍历*****************");  

 System.out.println("*******(后序遍历)[DEBFCA]遍历*****************");  



  1. 先序遍历:  
  2. 1 2 4 8 9 5 3 6 7   
  3. 中序遍历:  
  4. 8 4 9 2 5 1 6 3 7   
  5. 后序遍历:  
  6. 8 9 4 5 2 6 7 3 1   

算法代码实现

定义一个节点类,使节点与二叉树操作分离

class Node {
    int  value;
    Node leftChild;
    Node rightChild;
     
    Node(int value) {
        this.value = value;
    }
     
    public void display() {
        System.out.print(this.value + "\t");
    }
 
    @Override
    public String toString() {
        // TODO Auto-generated method stub
        return String.valueOf(value);
    }
}
需要实现的二叉树操作

class BinaryTree {
    private Node root = null;
     
    BinaryTree(int value) {
        root = new Node(value);
        root.leftChild  = null;
        root.rightChild = null;
    }
    public Node findKey(int value) {}   //查找
        public String insert(int value) {}  //插入
        public void inOrderTraverse() {}    //中序遍历
        public void preOrderTraverse() {}   //前序遍历
        public void postOrderTraverse() {}  //后序遍历
        public int getMinValue() {}         //得到最小(大)值
        public boolean delete(int value) {} //删除
}
查找数据:

public Node findKey(int value) {
      Node current = root;
      while (true) {
          if (value == current.value) {
              return current;
          } else if (value < current.value) {
              current = current.leftChild;
          } else if (value > current.value) {
              current = current.rightChild;
          }
           
          if (current == null) {
              return null;
          }
      }
  }

插入数据:与查找数据类似,不同点在于当节点为空时,不是返回而是插入

public String insert(int value) {
      String error = null;
       
      Node node = new Node(value);
      if (root == null) {
          root = node;
          root.leftChild  = null;
          root.rightChild = null;
      } else {
          Node current = root;
          Node parent = null;
          while (true) {
              if (value < current.value) {
                  parent = current;
                  current = current.leftChild;
                  if (current == null) {
                      parent.leftChild = node;
                      break;
                  }
              } else if (value > current.value) {
                  parent = current;
                  current = current.rightChild;
                  if (current == null) {
                      parent.rightChild = node;
                      break;
                  }
              } else {
                  error = "having same value in binary tree";
              }   
          } // end of while
      }
      return error;
  }
遍历数据:

 

1)中序遍历:最常用的一种遍历方法

/**
   * //中序遍历(递归):
   *    1、调用自身来遍历节点的左子树
   *    2、访问这个节点
   *    3、调用自身来遍历节点的右子树
   */
  public void inOrderTraverse() {
      System.out.print("中序遍历:");
      inOrderTraverse(root);
      System.out.println();
  }
   
  private void inOrderTraverse(Node node) {
      if (node == null) 
          return ;
       
      inOrderTraverse(node.leftChild);
      node.display();
      inOrderTraverse(node.rightChild);
  }

2)前序遍历:

/**
   * //前序遍历(递归):
   *    1、访问这个节点
   *    2、调用自身来遍历节点的左子树
   *    3、调用自身来遍历节点的右子树
   */
  public void preOrderTraverse() {
      System.out.print("前序遍历:");
      preOrderTraverse(root);
      System.out.println();
  }
   
  private void preOrderTraverse(Node node) {
      if (node == null) 
          return ;
       
      node.display();
      preOrderTraverse(node.leftChild);
      preOrderTraverse(node.rightChild);
  }
3)后序遍历:

**
   * //后序遍历(递归):
   *    1、调用自身来遍历节点的左子树
   *    2、调用自身来遍历节点的右子树
   *    3、访问这个节点
   */
  public void postOrderTraverse() {
      System.out.print("后序遍历:");
      postOrderTraverse(root);
      System.out.println();
  }
   
  private void postOrderTraverse(Node node) {
      if (node == null) 
          return ;
       
      postOrderTraverse(node.leftChild);
      postOrderTraverse(node.rightChild);
      node.display();
  }

得到最小(大)值:依次向左(右)直到空为之

public int getMinValue() {
      Node current = root;
      while (true) {
          if (current.leftChild == null)
              return current.value;
           
          current = current.leftChild;
      }
  }

参考文章:http://ocaicai.iteye.com/blog/1047397

         http://blog.youkuaiyun.com/wuwenxiang91322/article/details/12231657

        http://www.2cto.com/kf/201608/541695.html

面试参考:http://blog.youkuaiyun.com/luckyxiaoqiang/article/details/7518888/




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值