二叉树必知必会-基础篇(补充)

前言:中序和后序遍历迭代算法比较难,对于初学者需要多花一点时间去理解,同时需要注意学习方式。我个人看代码喜欢把代码放到相关软件里面,比如这里我使用的是CodeBlocks,这样比较有感觉。其次,边画图边理解是一种非常好的方法。

二叉树必知必会-基础篇

一、前序遍历迭代算法

为了更好的说清楚遍历的迭代算法,决定用这张比较简单的图。
不同于递归算法,迭代算法需要自己构建栈。所以在学习迭代算法之前需要对栈的概念有所了解。那什么是栈呢?简单的说栈是一个线性表,栈里面的元素具有线性关系,进入栈的操作也称为压栈或者入栈。类似手枪的弹夹往里面压入子弹,当取出子弹时,最先压入弹夹的子弹肯定是最后一个取出,所以栈中元素进出栈有个特性,先进后出,后进先出。

二叉树必知必会-基础篇(补充)_第1张图片
前序遍历.jpg
//递归算法系统已经自己构建好了栈,迭代算法则需要我们自己构建栈。
public static void PreOrderTraverse(BiTree T){
          if(T == null)
              return;

          Stack stack = new Stack();
          stack.push(T);

          while(!stack.isEmpty()){
             BiTree cur = stack.pop();//取出栈顶元素
             System.out.println(cur.value + " ");
            //关键点:要先压入右孩子,再压入左孩子,这样在出栈时会先打印左孩子再打印右孩子(栈:先进后出)
            if(cur.right != null){
                stack.push(cur.right);
              }
            if(cur.left != null){
              stack.push(cur.left);
            }
      }

}

分析:新建一个栈 stack ,将上图A压入到了栈中,在循环中,首先取出了A,打印A,判断A是否有右孩子,将右孩子C压入栈中,继续判断A是否有左孩子,将左孩子B压入栈中,因为A在stack.pop()时已经弹栈了,所以现在栈里面有两个元素,最底层元素是C,倒数第二个元素是B。再次执行循环,取出栈顶元素(此时的栈顶元素就是B),打印B。同理,判断B是否有右孩子,发现B没有右孩子,无操作。继续判断B是否有左孩子,将D压入栈中(此时栈中还有两个元素,最底层的依然是C,倒数第二层的是D)。再次执行循环,取出了栈顶元素D,打印D。继续判断D是否有左右孩子,依次类推就可以打印出:ABDGHCEIF。

二、中序遍历迭代算法

二叉树必知必会-基础篇(补充)_第2张图片
中序遍历.jpg
 //中序遍历迭代算法
    void InOderTraverse(BiTree T){
        if(T==null)
            return;

        Stack  stack =  new Stack();
        BiTree cur = T;
        while(!stack.isEmpty || T!=null){
            if(cur != null){//循环遍历左子树
                stack.push(cur);//将结点压入栈中
                cur = cur.left;//指针指向本结点的左子树
            }else{
                cur = stack.pop();//取出栈顶元素
                System.out.println(cur.val+"");//打印cur的值
                cur = cur.right;
                }
            }

    }

解析:
while循环语句外cur已经被赋值,进入循环cur不等于null,执行if语句中的代码,将A压入栈中,并且修改cur指针。if执行完成以后再次循环cur仍然不等于null,就这样一直循环遍历左子树,左子树一直压栈,直到结点G时(此时栈中元素是ABDG),G没有左孩子,所以cur等于null,当再次进行while循环时,执行else中的语句,stack.pop()取出栈顶元素(栈先进后出,所以G是栈顶元素),此时就打印了第一个值G。cur.right发现G没有右孩子,所以cur还是null,再次循环又进入到else语句中,现在stack.pop()方法取出的是元素D。打印D,D是有右孩子的,所以此时的cur经过赋值以后是不为空的,下次循环将进入if语句中,会将H压入栈中。然后继续判断H是否有做孩子。以此类推,就实现了中序遍历。在本中实现的遍历方式只是比较常用的,实现方法也不止这一种!

三、后序遍历迭代算法

根据后序遍历的规则,可以知道后序遍历是左右中结构,例如G-H-D、还有E-F-C,最后遍历根结点。为了实现这种规则的遍历,新建了两个栈,详情写在了代码注释中。


二叉树必知必会-基础篇(补充)_第3张图片
后序遍历.jpg
void postorderTraversal(BiTree T){
         if(T== null)
              return;

          Stack stack = new Stack();//第一个stack用于添加结点和它的左右孩子。
          // 因为需要左右中输出,还要进行翻转,所以第一个栈是中左右压入。翻转之后就是中右左,最后取出就是左右中了。
          Stack outstack = new Stack();//第二个outstack用于翻转第一个stack输出

          stack.push(T);
          while( !stack .isEmpty()){//确保所有元素都被翻转转移到第二个stack
               BiTree cur = stack .pop();
               outstack .push(cur);//把栈顶元素添加到第二个stack

              if(cur.left != null){//把栈顶元素的左孩子添加入到第一个stack
                      stack .push(cur.left);
                    }
              if(cur.right != null){//把栈顶元素的右孩子添加入到第一个stack
                    stack .push(cur.right);
                    }
    }

          while( !outstack .isEmpty()){//遍历输出第二个stack,即为后序遍历
                  System.out.println(outstack .pop().val+"");
                }
}

分析:具体分析和上面的分析方法类似,不行你就画两个栈,一步步的来,多想想就OK了

四、层序遍历迭代算法

这里使用的是宽度优先遍历,什么是宽度优先遍历?是以离初状态的状态距离为序进行遍历。这是官方定义,我也一脸懵逼,宽度优先遍历说白了就是需要你自己维护一个队列。怎样维护的?好好体会下面例子。

二叉树必知必会-基础篇(补充)_第4张图片
层序遍历.jpg

       //层序遍历二叉树迭代
        public static void levelTraversal(BiTree T){
            if(T==null)
                 return;

             LinkedList stack = new LinkedList();
             stack.push(T)
             while(!stack.isEmpty){
                  TreeNode cur = stack.removeFirst();//removeFirst():移除此队列中的第一个元素并返回此列表的第一个元素。
                  System.out.print(cur.val+"");
                  if(cur.left != null){
                      stack.push(cur.left);
                    }
                  if(cur.right != null){
                      stack.push(cur.right);
                      }
                }

        }

分析:注意这里创建的是链表。(自己画图)注意removeFirst()方法的作用,经历了上面的洗礼,这里应该不难了,才对。

五、总结

到这里二叉树的基础部分就结束了,后面的内容多吗?多少并不重要,重要的是你已经在开始了。

  • 二叉树遍历(恭喜已经完成了)
  • 二叉搜索树
  • 二叉搜索树查找
  • 二叉搜索树插入和删除
  • AVL树
  • 二叉堆的实现
二叉树必知必会-基础篇(补充)_第5张图片
放过我吧,我还是个孩子

每月更新两篇,质量保证,点击关注!
听说点喜欢的人运气会一直很好!!!

你可能感兴趣的:(二叉树必知必会-基础篇(补充))