风也温柔

计算机科学知识库

遍历二叉树java算法 java循环树_【Java】 二叉树的遍历(递归与循环+层序遍历)

  在【Java】 大话数据结构(9) 树(二叉树、线索二叉树)一文中,已经实现了采用递归方法的前、中、后序遍历,本文补充了采用循环的实现方法、以及层序遍历并进行了一个总结。

  递归实现

  /*

  * 前序遍历

  */

   void () {

  (root);

  .out.();

  }

   void ( node) {

  if(node==null)

  ;

  .out.print(node.data);

  (node.);

  (node.);

  }

  /*

  * 中序遍历

  */

   void () {

  (root);

  .out.();

  }

   void ( node) {

  if(node==null)

  ;

  (node.);

  .out.print(node.data);

  (node.);

  }

  /*

  * 后序遍历

  */

   void () {

  (root);

  .out.();

  }

   void ( node) {

  if(node==null)

  ;

  (node.);

  (node.);

  .out.print(node.data);

  }

  非递归实现(迭代)

  非递归实现,需要先创建一个栈,利用其特性来进行储存和输出。

  前序遍历,先输出当前点的值遍历二叉树java算法,一直沿着左子树进行读取,没左子树就在右子树重复上述过程。

  中序遍历与前序遍历基本一致,只是输出值的代码位置不同。

  后序遍历由于要左右子树输出完后才能输出根结点,所以增加一个栈进行标记是否完成左右子树的输出,其余思想基本类似。

  下面代码中,要注意node的结点位置和stack.peek()的位置关系。

  此外,在后序非递归遍历的过程中遍历二叉树java算法 java循环树_【Java】 二叉树的遍历(递归与循环+层序遍历),栈中保留的是当前结点的所有祖先。这是和先序及中序遍历不同的。在某些和祖先有关的算法中,此算法很有价值。

  /**

  * 前序遍历(非递归)

  */

   void () {

  (root);

  .out.();

  }

   void ( node) {

  Stack stack = new Stack();

  while(node!=null||!stack.()) {

  while(node!=null) {

  .out.print(node.data);

  stack.push(node);

  node=node.;

  }

  node=stack.pop().;

  }

  }

  /**

  * 中序遍历

  */

   void () {

  (root);

  .out.();

  }

   void ( node) {

  Stack stack = new Stack();

  while(node!=null||!stack.()) {

  while(node!=null) {

  stack.push(node);

  node=node.;

  }

  node=stack.pop();

  .out.print(node.data);

  node=node.;

  }

  }

  /**

  * 后序遍历

  */

   void () {

  (root);

  .out.();

  }

   void ( node) {

  Stack stack = new Stack();

  Stack tag = new Stack();

  //下面这段注释也能实现,与后面未注释部分基本一致。代表了自己的思考过程,就不删除了

  //while(node!=null||!stack.()) {

  //while(node!=null){

  //stack.push(node);

  //tag.push(0);

  //node=node.;

  //}

  //注释中的tag用于标记当前结点是否完成左右子结点遍历(所以用0,1表示)

  //while(!tag.()&&tag.peek()==1) { //栈顶节点的左右子结点已完成遍历

  //.out.print(stack.pop().data);

  //tag.pop();

  //}

  //if(!tag.()) { //上面和这里的 !flag.() 不可省略,不然会出错。

  //tag.pop();

  //tag.push(1);

  //node=stack.peek().;

  //}

  //}

  /*后序遍历时,分别从左子树和右子树共两次返回根结点(用tag表示次数),

  * 只有从右子树返回时才访问根结点,所以增加一个栈标记到达结点的次序。

  */

  while(node!=null||!stack.()) {

  if(node!=null){

  stack.push(node);

  tag.push(1); //第一次访问

  node=node.;

  }else {

  if(tag.peek()==2) {

  .out.print(stack.pop().data);

  tag.pop();

  }else {

  tag.pop();

  tag.push(2); //第二次访问

  node=stack.peek().;

  }

  }

  }

  }

  :前序和后序的非递归遍历还可以合理利用栈的性质来实现,与上面的稍有不同。

  前序:

   List ( root) {

   list = new ();

  Stack stk = new Stack();

  stk.push(root);

  while(!stk.()){

   node = stk.pop();

  if(node==null)

  ;

  list.add(node.val);

  stk.push(node.right);

  stk.push(node.left);

  }

   list;

  }

  后序:

   List ( root) {

   list = new ();

  Stack stk = new Stack();

  stk.push(root);

  while(!stk.()){

   node = stk.pop();

  if(node==null)

  ;

  list.(node.val); //'s . If using here,then using '.(list)'' in the end;

  stk.push(node.left);

  stk.push(node.right);

  }

   list;

  }

  层序遍历

  合理利用队列的性质即可。

   void () {

   node =root;

  > list = new ();

  list.add(node);

  while(!list.()) {

  node=list.poll();

  .out.print(node.data);

  if(node.!=null)

  list.offer(node.);

  if(node.!=null)

  list.offer(node.);

  }

  }

  完整代码(含测试代码)

   ;

   java.util.;

   java.util.Stack;

  class {

  E data;

   ,;

   (E data) {

  this.data=data;

  this.=null;

  this.=null;

  }

  }

   class {

   root;

   () {

  //root=new (null, null, null);

  root=null;

  }

  /*

  * 前序遍历

  */

   void () {

  (root);

  .out.();

  }

   void ( node) {

  if(node==null)

  ;

  .out.print(node.data);

  (node.);

  (node.);

  }

  /*

  * 中序遍历

  */

   void () {

  (root);

  .out.();

  }

   void ( node) {

  if(node==null)

  ;

  (node.);

  .out.print(node.data);

  (node.);

  }

  /*

  * 后序遍历

  */

   void () {

  (root);

  .out.();

  }

   void ( node) {

  if(node==null)

  ;

  (node.);

  (node.);

  .out.print(node.data);

  }

  //===============循环遍历===============

  /**

  * 前序遍历(非递归)

  */

   void () {

  (root);

  .out.();

  }

   void ( node) {

  Stack stack = new Stack();

  while(node!=null||!stack.()) {

  while(node!=null) {

  .out.print(node.data);

  stack.push(node);

  node=node.;

  }

  node=stack.pop().;

  }

  }

  /**

  * 中序遍历

  */

   void () {

  (root);

  .out.();

  }

   void ( node) {

  Stack stack = new Stack();

  while(node!=null||!stack.()) {

  while(node!=null) {

  stack.push(node);

  node=node.;

  }

  node=stack.pop();

  .out.print(node.data);

  node=node.;

  }

  }

  /**

  * 后序遍历

  */

   void () {

  (root);

  .out.();

  }

   void ( node) {

  Stack stack = new Stack();

  Stack tag = new Stack();

  //while(node!=null||!stack.()) {

  //while(node!=null){

  //stack.push(node);

  //tag.push(0);

  //node=node.;

  //}

  //这里的tag用于标记当前结点是否完成左右子结点遍历(所以用0,1表示)

  //while(!tag.()&&tag.peek()==1) { //栈顶节点的左右子结点已完成遍历

  //.out.print(stack.pop().data);

  //tag.pop();

  //}

  //if(!tag.()) { //上面和这里的 !flag.() 不可省略,不然会出错。

  //tag.pop();

  //tag.push(1);

  //node=stack.peek().;

  //}

  //}

  /*后序遍历时遍历二叉树java算法,分别从左子树和右子树共两次返回根结点(用tag表示次数),

  * 只有从右子树返回时才访问根结点,所以增加一个栈标记到达结点的次序。

  */

  while(node!=null||!stack.()) {

  if(node!=null){

  stack.push(node);

  tag.push(1); //第一次访问

  node=node.;

  }else {

  if(tag.peek()==2) {

  .out.print(stack.pop().data);

  tag.pop();

  }else {

  tag.pop();

  tag.push(2); //第二次访问

  node=stack.peek().;

  }

  }

  }

  }

  //=========层序遍历============

   void () {

   node =root;

  > list = new ();

  list.add(node);

  while(!list.()) {

  node=list.poll();

  .out.print(node.data);

  if(node.!=null)

  list.offer(node.);

  if(node.!=null)

  list.offer(node.);

  }

  }

   void main([] args) {

   = new ();

  .root=new ("A");

  .root.=new ("B");

  .root.=new ("C");

  .root..=new ("D");

  // = new ();

  //.root=new ("A");

  //.root.=new ("B");

  //.root..=new ("C");

  //.root...=new ("D");

  //.root..=new ("E");

  //.root...=new ("F");

  //.root....=new ("G");

  //.root.....=new ("H");

  .out.("————前序————");

  .();

  .();

  .out.("————中序————");

  .();

  .();

  .out.("————后序————");

  .();

  .();

  .out.("————层序遍历————");

  .();

  }

  }

  ————前序————

  ABDC

  ABDC

  ————中序————

  BDAC

  BDAC

  ————后序————

  DBCA

  DBCA

  ————层序遍历————

  ABCD

  遍历结果

  文章来源:https://blog.csdn.net/weixin_29444613/article/details/114086135