java-二叉树的四种遍历的递归与非递归实现

首先我们需要了解二叉树的基本性质:
1.每一个节点最多有两个孩子节点
2.左孩子<根节点<右孩子

四种遍历思路:
前序遍历:根结点 —> 左子树 —> 右子树

中序遍历:左子树—> 根结点 —> 右子树

后序遍历:左子树 —> 右子树 —> 根结点

层次遍历:仅仅需按层次遍历就可以义目录标题)
在这里插入图片描述
而刚好由于这种性质,我们利用递归可以很简单的完成遍历
前序遍历递归实现:
public void preOrder() {
System.out.print(“递归前序遍历:”);
preOrder(this.root);
System.out.println();
}

/**
 * 前序遍历BST树的递归操作 VLR
 *
 * @param root
 */
private void preOrder(BSTNode<T> root) {
    if (root != null) {
        System.out.print(root.getData() + " ");
        preOrder(root.getLeft());
        preOrder(root.getRight());
    }
}

中序遍历的递归实现:
public void inOrder() {
System.out.print(“递归中序遍历:”);
inOrder(this.root);
System.out.println();
}

/**
 * 中序遍历BST树的递归操作 LVR
 *
 * @param root
 */
private void inOrder(BSTNode<T> root) {
    if (root != null) {
        inOrder(root.getLeft());
        System.out.print(root.getData() + " ");
        inOrder(root.getRight());
    }
}	

后序遍历的递归实现:
public void postOrder() {
System.out.print(“递归后序遍历:”);
postOrder(this.root);
System.out.println();
}

/**
 * 中序遍历BST树的递归操作 LRV
 *
 * @param root
 */
private void postOrder(BSTNode<T> root) {
    if (root != null) {
        postOrder(root.getLeft());
        postOrder(root.getRight());
        System.out.print(root.getData() + " ");
    }
}

层序遍历的递归实现:
public void levelOrder() {
System.out.print(“递归层序遍历:”);
int hight = level();
for (int i = 0; i < hight; i++) {
levelOrder(this.root, i);
}
System.out.println();
}

/**
 * 层序遍历的递归实现
 *
 * @param root
 * @param i
 */
private void levelOrder(BSTNode<T> root, int i) {
    if (root != null) {
        if (i == 0) {
            System.out.print(root.getData() + " ");
            return;
        }
        levelOrder(root.getLeft(), i - 1);
        levelOrder(root.getRight(), i - 1);
    }
}

这里也使用了非递归实现方式:
前序遍历的非递归实现:
public void preOrderTraverse2(TreeNode root) {
Stack stack = new Stack<>();
TreeNode pNode = root;
while (pNode != null || !stack.isEmpty()) {
if (pNode != null) {
System.out.print(pNode.val+" “);
stack.push(pNode);
pNode = pNode.left;
} else { //pNode == null && !stack.isEmpty()
TreeNode node = stack.pop();
pNode = node.right;
}
}
}
中序遍历的非递归实现:
public void inOrderTraverse2(TreeNode root) {
Stack stack = new Stack<>();
TreeNode pNode = root;
while (pNode != null || !stack.isEmpty()) {
if (pNode != null) {
stack.push(pNode);
pNode = pNode.left;
} else { //pNode == null && !stack.isEmpty()
TreeNode node = stack.pop();
System.out.print(node.val+” “);
pNode = node.right;
}
}
}
后序遍历的非递归实现:
第一种思路:对于任一结点P,将其入栈,然后沿其左子树一直往下搜索。直到搜索到没有左孩子的结点,
此时该结点出如今栈顶,可是此时不能将其出栈并訪问,因此其右孩子还为被訪问。
void postOrder2(BinTree root) //非递归后序遍历
{
stack<BTNode
> s;
BinTree *p=root;
BTNode *temp;
while(p!=NULL||!s.empty())
{
while(p!=NULL) //沿左子树一直往下搜索。直至出现没有左子树的结点
{
BTNode *btn=(BTNode *)malloc(sizeof(BTNode));
btn->btnode=p;
btn->isFirst=true;
s.push(btn);
p=p->lchild;
}
if(!s.empty())
{
temp=s.top();
s.pop();
if(temp->isFirst==true) //表示是第一次出如今栈顶
{
temp->isFirst=false;
s.push(temp);
p=temp->btnode->rchild;
}
else //第二次出如今栈顶
{
cout<btnode->data<<” ";
p=NULL;
}
}
}
}

所以接下来依照同样的规则对其右子树进行同样的处理,当訪问完其右孩子时。该结点又出如今栈顶
,此时能够将其出栈并訪问。这样就保证了正确的訪问顺序。能够看出,在这个过程中,每一个结点都两次出如今栈顶,
仅仅有在第二次出如今栈顶时,才干訪问它。因此须要多设置一个变量标识该结点是否是第一次出如今栈顶。
第二种思路:要保证根结点在左孩子和右孩子訪问之后才干訪问,因此对于任一结点P。先将其入栈。假设P不存在左孩子和右孩子。
则能够直接訪问它;或者P存在左孩子或者右孩子。可是其左孩子和右孩子都已被訪问过了。则相同能够直接訪问该结点。
若非上述两种情况。则将P的右孩子和左孩子依次入栈。这样就保证了每次取栈顶元素的时候,左孩子在右孩子前面被訪问。左孩子和右孩子都在根结点前面被訪问。
void postOrder3(BinTree root) //非递归后序遍历
{
stack<BinTree
> s;
BinTree *cur; //当前结点
BinTree *pre=NULL; //前一次訪问的结点
s.push(root);
while(!s.empty())
{
cur=s.top();
if((cur->lchildNULL&&cur->rchildNULL)||
(pre!=NULL&&(precur->lchild||precur->rchild)))
{
cout<data<<" “; //假设当前结点没有孩子结点或者孩子节点都已被訪问过
s.pop();
pre=cur;
}
else
{
if(cur->rchild!=NULL)
s.push(cur->rchild);
if(cur->lchild!=NULL)
s.push(cur->lchild);
}
}
}
层序遍历的非递归实现:层次遍历的代码比較简单。仅仅须要一个队列就可以。先在队列中增加根结点。之后对于随意一个结点来说。
在其出队列的时候,訪问之。同一时候假设左孩子和右孩子有不为空的。入队列。
public void levelTraverse(TreeNode root) {
if (root == null) {
return;
}
LinkedList queue = new LinkedList<>();
queue.offer(root);
while (!queue.isEmpty()) {
TreeNode node = queue.poll();
System.out.print(node.val+” ");
if (node.left != null) {
queue.offer(node.left);
}
if (node.right != null) {
queue.offer(node.right);
}
}
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
无限级树(Java递归) 2007-02-08 10:26 这几天,用java写了一个无限极的树,递归写的,可能代码不够简洁,性能不够好,不过也算是练习,这几天再不断改进。前面几个小图标的判断,搞死我了。 package com.nickol.servlet; import java.io.IOException; import java.io.PrintWriter; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.util.ArrayList; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import com.nickol.utility.DB; public class category extends HttpServlet { /** * The doGet method of the servlet. * * This method is called when a form has its tag value method equals to get. * * @param request the request send by the client to the server * @param response the response send by the server to the client * @throws ServletException if an error occurred * @throws IOException if an error occurred */ public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setCharacterEncoding("utf-8"); response.setContentType("text/html"); PrintWriter out = response.getWriter(); out .println(""); out.println(""); out.println(" Category" + "" + "body{font-size:12px;}" + "" + "" + ""); out.println(" "); out.println(showCategory(0,0,new ArrayList(),"0")); out.println(" "); out.println(""); out.flush(); out.close(); } public String showCategory(int i,int n,ArrayList frontIcon,String countCurrent){ int countChild = 0; n++; String webContent = new String(); ArrayList temp = new ArrayList(); try{ Connection conn = DB.GetConn(); PreparedStatement ps = DB.GetPs("select * from category where pid = ?", conn); ps.setInt(1, i); ResultSet rs = DB.GetRs(ps); if(n==1){ if(rs.next()){ webContent += "";//插入结尾的减号 temp.add(new Integer(0)); } webContent += " ";//插入站点图标 webContent += rs.getString("cname"); webContent += "\n"; webContent += showCategory(Integer.parseInt(rs.getString("cid")),n,temp,"0"); } if(n==2){ webContent += "\n"; }else{ webContent += "\n"; } while(rs.next()){ for(int k=0;k<frontIcon.size();k++){ int iconStatic = ((Integer)frontIcon.get(k)).intValue(); if(iconStatic == 0){ webContent += "";//插入空白 }else if(iconStatic == 1){ webContent += "";//插入竖线 } } if(rs.isLast()){ if(checkChild(Integer.parseInt(rs.getString("cid")))){ webContent += "";//插入结尾的减号 temp = (ArrayList)frontIcon.clone(); temp.add(new Integer(0)); }else{ webContent += "";//插入结尾的直角 } }else{ if(checkChild(Integer.parseInt(rs.getString("cid")))){ webContent += "";//插入未结尾的减号 temp = (ArrayList)frontIcon.clone(); temp.add(new Integer(1)); }else{ webContent += "";//插入三叉线 } } if(checkChild(Integer.parseInt(rs.getString("cid")))){ webContent += " ";//插入文件夹图标 }else{ webContent += " ";//插入文件图标 } webContent += rs.getString("cname"); webContent += "\n"; webContent += showCategory(Integer.parseInt(rs.getString("cid")),n,temp,countCurrent+countChild); countChild++; } webContent += "\n"; DB.CloseRs(rs); DB.ClosePs(ps); DB.CloseConn(conn); }catch(Exception e){ e.printStackTrace(); } return webContent; } public boolean checkChild(int i){ boolean child = false; try{ Connection conn = DB.GetConn(); PreparedStatement ps = DB.GetPs("select * from category where pid = ?", conn); ps.setInt(1, i); ResultSet rs = DB.GetRs(ps); if(rs.next()){ child = true; } DB.CloseRs(rs); DB.ClosePs(ps); DB.CloseConn(conn); }catch(Exception e){ e.printStackTrace(); } return child; } } --------------------------------------------------------------------- tree.js文件 function changeState(countCurrent,countChild){ var object = document.getElementById("level" + countCurrent + countChild); if(object.style.display=='none'){ object.style.display='block'; }else{ object.style.display='none'; } var cursor = document.getElementById("cursor" + countCurrent + countChild); if(cursor.src.indexOf("images/tree_minus.gif")>=0) {cursor.src="images/tree_plus.gif";} else if(cursor.src.indexOf("images/tree_minusbottom.gif")>=0) {cursor.src="images/tree_plusbottom.gif";} else if(cursor.src.indexOf("images/tree_plus.gif")>=0) {cursor.src="images/tree_minus.gif";} else {cursor.src="images/tree_minusbottom.gif";} var folder = document.getElementById("folder" + countCurrent + countChild); if(folder.src.indexOf("images/icon_folder_channel_normal.gif")>=0){ folder.src = "images/icon_folder_channel_open.gif"; }else{ folder.src = "images/icon_folder_channel_normal.gif"; }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值