剑指Offer——二叉树

举报
SHQ1874009 发表于 2020/12/30 00:15:06 2020/12/30
【摘要】 剑指Offer——二叉树 前言      数据结构通常是编程面试中考察的重点。在参加面试之前,应聘者需要熟练掌握链表、树、栈、队列和哈希表等数据结构,以及它们的操作。本片博文主要讲解二叉树操作的相关知识,主要包括二叉树的建立、遍历方法的循环和递归写法。      二叉树是树形结构的一个重要类型。许多实际问题抽象...

剑指Offer——二叉树

前言

     数据结构通常是编程面试中考察的重点。在参加面试之前,应聘者需要熟练掌握链表、树、栈、队列和哈希表等数据结构,以及它们的操作。本片博文主要讲解二叉树操作的相关知识,主要包括二叉树的建立、遍历方法的循环和递归写法。

     二叉树是树形结构的一个重要类型。许多实际问题抽象出来的数据结构往往是二叉树的形式,即使是一般的树也能简单地转换为二叉树,而且二叉树的存储结构及其算法都较为简单,因此二叉树显得特别重要。

二叉树的java实现

     首先创建一棵二叉树如下图,然后对这颗二叉树进行遍历操作(遍历操作的实现分为递归实现和非递归实现),同时还提供一些方法如获取双亲结点、获取左孩子、右孩子等。

 


      package cn.edu.ujn.nk;
      import java.util.Stack;
      /**
       * 二叉树的链式存储
       * @author WWX
       */
      public class BinaryTree {
       private TreeNode root=null;
       public BinaryTree(){
       root=new TreeNode(1,"rootNode(A)");
       }
       /**
       * 创建一棵二叉树
       * <pre>
       * A
       * B C
       *  D E F
       *  </pre>
       * @param root
       * @author WWX
       */
       public void createBinTree(TreeNode root){
       TreeNode newNodeB = new TreeNode(2,"B");
       TreeNode newNodeC = new TreeNode(3,"C");
       TreeNode newNodeD = new TreeNode(4,"D");
       TreeNode newNodeE = new TreeNode(5,"E");
       TreeNode newNodeF = new TreeNode(6,"F");
       root.leftChild=newNodeB;
       root.rightChild=newNodeC;
       root.leftChild.leftChild=newNodeD;
       root.leftChild.rightChild=newNodeE;
       root.rightChild.rightChild=newNodeF;
       }
       public boolean isEmpty(){
       return root==null;
       }
       //树的高度
       public int height(){
       return height(root);
       }
       //节点个数
       public int size(){
       return size(root);
       }
       private int height(TreeNode subTree){
       if(subTree == null)
       return 0;	// 递归结束:空树高度为0
       else{
       int i = height(subTree.leftChild);
       int j = height(subTree.rightChild);
       return (i < j) ? (j + 1) : (i + 1);
       }
       }
       private int size(TreeNode subTree){
       if(subTree == null){
       return 0;
       }else{
       return 1 + size(subTree.leftChild) + size(subTree.rightChild);
       }
       }
       //返回双亲结点
       public TreeNode parent(TreeNode element){
       return (root == null|| root == element) ? null : parent(root, element);
       }
       public TreeNode parent(TreeNode subTree,TreeNode element){
       if(subTree == null)
       return null;
       if(subTree.leftChild == element || subTree.rightChild == element)
       //返回父结点地址
       return subTree;
       TreeNode p;
       // 先在左子树中找,如果左子树中没有找到,才到右子树去找
       if((p = parent(subTree.leftChild, element)) != null)
       //递归在左子树中搜索
       return p;
       else
       //递归在右子树中搜索
       return parent(subTree.rightChild, element);
       }
       public TreeNode getLeftChildNode(TreeNode element){
       return (element != null) ? element.leftChild : null;
       }
       public TreeNode getRightChildNode(TreeNode element){
       return (element != null) ? element.rightChild : null;
       }
       public TreeNode getRoot(){
       return root;
       }
       //在释放某个结点时,该结点的左右子树都已经释放,
       //所以应该采用后续遍历,当访问某个结点时将该结点的存储空间释放
       public void destroy(TreeNode subTree){
       //删除根为subTree的子树
       if(subTree!=null){
       //删除左子树
       destroy(subTree.leftChild);
       //删除右子树
       destroy(subTree.rightChild);
       //删除根结点
       subTree=null;
       }
       }
       public void traverse(TreeNode subTree){
       System.out.println("key:"+subTree.key+"--name:"+subTree.data);;
       traverse(subTree.leftChild);
       traverse(subTree.rightChild);
       }
       //前序遍历
       public void preOrder(TreeNode subTree){
       if(subTree!=null){
       visted(subTree);
       preOrder(subTree.leftChild);
       preOrder(subTree.rightChild);
       }
       }
       //中序遍历
       public void inOrder(TreeNode subTree){
       if(subTree!=null){
       inOrder(subTree.leftChild);
       visted(subTree);
       inOrder(subTree.rightChild);
       }
       }
       //后续遍历
       public void postOrder(TreeNode subTree) {
       if (subTree != null) {
       postOrder(subTree.leftChild);
       postOrder(subTree.rightChild);
       visted(subTree);
       }
       }
       //前序遍历的非递归实现
       public void nonRecPreOrder(TreeNode p){
       Stack<TreeNode> stack=new Stack<TreeNode>();
       TreeNode node=p;
       while(node!=null||stack.size()>0){
       while(node!=null){
       visted(node);
       stack.push(node);
       node=node.leftChild;
       }
       while(stack.size()>0){
       node=stack.pop();
       node=node.rightChild;
       }
       }
       }
       //中序遍历的非递归实现
       public void nonRecInOrder(TreeNode p){
       Stack<TreeNode> stack =new Stack<BinaryTree.TreeNode>();
       TreeNode node =p;
       while(node!=null||stack.size()>0){
       //存在左子树
       while(node!=null){
       stack.push(node);
       node=node.leftChild;
       }
       //栈非空
       if(stack.size()>0){
       node=stack.pop();
       visted(node);
       node=node.rightChild;
       }
       }
       }
       //后序遍历的非递归实现
       public void noRecPostOrder(TreeNode p){
       Stack<TreeNode> stack=new Stack<BinaryTree.TreeNode>();
       TreeNode node =p;
       while(p!=null){
       //左子树入栈
       for(;p.leftChild!=null;p=p.leftChild){
       stack.push(p);
       }
       //当前结点无右子树或右子树已经输出
       while(p!=null&&(p.rightChild==null||p.rightChild==node)){
       visted(p);
       //纪录上一个已输出结点
       node =p;
       if(stack.empty())
       return;
       p=stack.pop();
       }
       //处理右子树
       stack.push(p);
       p=p.rightChild;
       }
       }
       public void visted(TreeNode subTree){
       subTree.isVisted=true;
       System.out.println("key:"+subTree.key+"--name:"+subTree.data);;
       }
       /**
       * 二叉树的节点数据结构
       * @author WWX
       */
       private class  TreeNode{
       private int key = 0;
       private String data = null;
       private boolean isVisted = false;
       private TreeNode leftChild = null;
       private TreeNode rightChild = null;
       public TreeNode(){}
       /**
       * @param key  层序编码
       * @param data 数据域
       */
       public TreeNode(int key,String data){
       this.key = key;
       this.data = data;
       this.leftChild = null;
       this.rightChild = null;
       }
       }
       //测试
       public static void main(String[] args) {
       BinaryTree bt = new BinaryTree();
       bt.createBinTree(bt.root);
       System.out.println("the size of the tree is " + bt.size());
       System.out.println("the height of the tree is " + bt.height());
       System.out.println("***递归实现****(前序遍历)[ABDECF]遍历*****************");
       bt.preOrder(bt.root);
       System.out.println("***递归实现****(中序遍历)[DBEACF]遍历*****************");
       bt.inOrder(bt.root);
       System.out.println("***递归实现****(后序遍历)[DEBFCA]遍历*****************");
       bt.postOrder(bt.root);
       System.out.println("***非递归实现****(前序遍历)[ABDECF]遍历*****************");
       bt.nonRecPreOrder(bt.root);
       System.out.println("***非递归实现****(中序遍历)[DBEACF]遍历*****************");
       bt.nonRecInOrder(bt.root);
       System.out.println("***非递归实现****(后序遍历)[DEBFCA]遍历*****************");
       bt.noRecPostOrder(bt.root);
       }
      }
  
 

 

美文美图

 

文章来源: shq5785.blog.csdn.net,作者:No Silver Bullet,版权归原作者所有,如需转载,请联系作者。

原文链接:shq5785.blog.csdn.net/article/details/52143212

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。