树遍历算法概述

您所在的位置:网站首页 树的遍历非递归算法 树遍历算法概述

树遍历算法概述

2024-03-05 23:27| 来源: 网络整理| 查看: 265

首先树是一种递归结构,因此递归算法很好写,关键是非递归算法。

而非递归算法中,树的四种非递归遍历方式又是核心。下面先介绍树的四种非递归遍历算法,再介绍其他的非递归算法。

1、层次遍历:

这大概是最简单的了,队列结构,先进根节点,然后循环:出队列头,然后分别进左,右子树节点。如此反复,直至队列为空。

2、先序遍历:

单栈即可。这个在三序遍历中最简单,因为栈只需要保存右子树节点,左子树直接访问。要点:访左存右。一层while循环即可搞定。

3、中序遍历:

单栈即可。这个要比先序难些,因为左右子树节点都要保存在栈中,因此分清父节点是否被访问过极为重要,不然就会无限循环。

怎么区分呢?可以这样区分:以tmp保存父节点,以tmp是否为空作为进栈条件(绝不可以tmp.left是否为空做为进栈条件,这样会分不清父节点是否访问过。不服可以写个试试),进栈后,tmp=tmp.left;出栈后,tmp=tmp.right。这样就可完美区分左右。

由于左节点要一次性进到底,所以总共需要两层while循环。要点:左路进到底,然后退一进右。如此反复。

4、后序遍历:

后序遍历就必须得用符号来标识左右了。实际上中序遍历不用符号已经令我很吃惊,不过中序右子树只保存一层,因此还可以区分左右。但后序左右子树均要保存多层,不用符号就无法区分左右。

实际上后序遍历和中序遍历很像,更实际上,三种遍历的顺序是一样的,先序因为先访问节点,所以不保存左子树,故和后两序差别较大。

因此我们可以仿照中序遍历的写法来写后序。只不过加上符号,标明左右。

会写中序非递归遍历,就会写后序非递归遍历。要点:左路进到底,判断符号,左则变号进右,右则退栈输出。如此反复。

 

另外切记:直接以tmp != null 而不是tmp.left != null 作为左子树递进条件。写循环的要点在于一次把一层写完,而不是一次写残缺多层。

另外:进栈时,我们是知道左右的,出栈时就不知道了。出栈想要防止重复访问,就需要特殊的访问技巧(中序)和特殊的标记符号(后序)。

 

其余还有一些琐碎算法,基本都是树的几种遍历算法的应用:

1、通过前序与中序确定二叉树。前序首节点是根节点,中序,根节点左右为左右子树。据此不断划分,递归构建即可。

2、n个节点二叉树的个数与n个元素的出栈顺序一样,均为卡特兰树。(1/(n+1)) * C(2n,n).

 

 

 

 

java代码如下:

package com.company; /** * Build a binary tree from a generalized list. * input is like this:A(B(D,E(G,)),C(,F))# */ public class TreeBuilder { private static class Node{ char value; Node left; Node right; } /** * Build a binary tree from a generalized list. * @param glist glist is a generalized list, for example: A(B(D,E(G,)),C(,F))# * @return the root node of tree */ public static Node creatTree(String glist){ if (glist.isEmpty()){ return null; } Node[] stack = new Node[glist.length()]; int pos = 0; int top = -1; Node root = new Node(); if ((glist.charAt(pos) + "").matches("[A-Z]")){ //if is upper character, push in stack root.value = glist.charAt(pos); stack[++top] = root; }else { return null; } while (glist.charAt(pos) != '#'){ char ch = glist.charAt(pos); if (ch == '('){ pos++; if ((glist.charAt(pos) + "").matches("[A-Z]")){ Node tmp = new Node(); tmp.value = glist.charAt(pos); stack[top].left = tmp; if (glist.charAt(pos+1) == '('){ // if has sub-tree, push in stack stack[++top] = tmp; } pos++; }else if (glist.charAt(pos) == ','){ stack[top].left = null; } }else if (glist.charAt(pos) == ','){ // after ',' is right sub-tree. pos++; if ((glist.charAt(pos) + "").matches("[A-Z]")){ Node tmp = new Node(); tmp.value = glist.charAt(pos); stack[top--].right = tmp; // pop stack if (glist.charAt(pos+1) == '('){ // if has sub-tree, push in stack stack[++top] = tmp; } pos++; }else { stack[top--].right = null; } }else { pos++; } } if (top == -1){ // test whether the result is true. System.out.println(true); } return root; } /** * Build a binary tree from a generalized list. * version 2, use switch grammar * @param glist glist is a generalized list, for example: A(B(D,E(G,)),C(,F))# * @return the root node of tree */ public static Node creatTree2(String glist){ if (glist.isEmpty()){ return null; } Node[] stack = new Node[glist.length()]; int top = -1; int flag = 0; // right sub-tree or left sub-tree int pos = 0; // char position Node root = null; Node tmp = null; while (glist.charAt(pos) != '#'){ char ch = glist.charAt(pos); switch (ch){ case '(': stack[++top] = tmp;// push in pos++; flag = 1; // left sub-tree break; case ',': pos++; flag = 2; // right sub-tree break; case ')': pos++; top--; // pop out break; default: tmp = new Node(); tmp.value = ch; if (root == null){ // link the root root = tmp; } if (flag == 1){ stack[top].left = tmp; }else if (flag == 2){ stack[top].right = tmp; } pos++; } } return root; } public static void printPreTree(Node root){ if (root != null){ System.out.print(root.value + " "); printPreTree(root.left); printPreTree(root.right); } } /** * the non-recursion pre traversal of tree * @param root */ public static void printPreTreeNonRecursion(Node root){ Node tmp = root; Node[] stack = new Node[20]; int top = -1; while (tmp != null || top != -1){ if (tmp != null){ System.out.printf(tmp.value + " "); if (tmp.right != null){ stack[++top] = tmp.right; } tmp = tmp.left; }else { tmp = stack[top--]; } } System.out.println(); } /** * the hierarchical traversal of tree * @param root */ public static void printHierarchical(Node root){ Node[] queen = new Node[20]; int head = 0; int tail = 0; Node tmp = root; queen[tail++%20] = tmp; while (tail != head){ tmp = queen[head++%20]; System.out.printf(tmp.value + " "); if (tmp.left != null){ queen[tail++%20] = tmp.left; } if(tmp.right != null){ queen[tail++%20] = tmp.right; } } System.out.println(); } /** * 树的中序非递归遍历 * the middle non-recursion traversal of tree * @param root */ public static void printMidTreeNonRecursion(Node root){ Node[] stack = new Node[20]; int top = -1; Node tmp = root; while (tmp != null || top != -1){ while (tmp != null){ stack[++top] = tmp; tmp = tmp.left; } if (top != -1){ tmp = stack[top--]; System.out.printf(tmp.value + " "); tmp = tmp.right; } } System.out.println(); } /** * 树的中序递归遍历 * the middle recursion traversal of tree * @param root */ public static void printMidTree(Node root){ if (root != null){ printMidTree(root.left); System.out.printf(root.value + " "); printMidTree(root.right); } } /** * 树的后序递归遍历 * the suffix recursion of traversal of tree */ public static void printSufTree(Node root){ if (root != null){ printSufTree(root.left); printSufTree(root.right); System.out.printf(root.value + " "); } } /** * the suffix non-recursion traversal of tree */ public static void printSufTreeNonRecursion(Node root){ class FlagNode{ Node node; int flag; } FlagNode[] stack = new FlagNode[20]; int top = -1; Node tmp = root; while (top != -1 || tmp != null){ while (tmp != null){ FlagNode flagNode = new FlagNode(); flagNode.node = tmp; flagNode.flag = 0; stack[++top] = flagNode; tmp = tmp.left; } if (top != -1){ if (stack[top].flag == 0){ stack[top].flag = 1; tmp = stack[top].node.right; }else { System.out.printf(stack[top--].node.value + " "); } } } System.out.println(); } /** * 以广义表的形式把树打印出来 * @param root */ public static void printGTree(Node root){ if(root != null){ System.out.printf(root.value + ""); if (root.left != null || root.right != null) { System.out.printf("("); printGTree(root.left); System.out.printf(","); printGTree(root.right); System.out.printf(")"); } } } public static void main(String[] args) { // write your code here Node root =creatTree("A(B(G,H(K,L)),C(D,E(F,)))#"); System.out.println("Pre traversal: "); printPreTree(root); System.out.println(); printPreTreeNonRecursion(root); System.out.println(" : "); printHierarchical(root); Node root2 =creatTree2("A(B(G(H(K(,J(,Z)),),I),M(,N)),C(D,E(F,)))#"); System.out.println("Mid traversal: "); printMidTree(root2); System.out.println(); printMidTreeNonRecursion(root2); System.out.println("Suf traversal: "); printSufTree(root2); System.out.println(); printSufTreeNonRecursion(root2); } }

 



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3