zoukankan      html  css  js  c++  java
  • 二叉树的递归与非递归

    二叉树的递归与非递归

    二叉树节点结构

    class Node<V>
    {
    	V value;//一个节点有自己的值
    	Node left;//指向左孩子的指针
    	Node right;//指向右孩子的指针
    }
    

    递归实现方法

    • 先序:先处理头,再处理左,最后处理右

      即按照递归顺序取第一次出现的数组成的序列

    • 中序:先处理左,再处理头,最后处理右

      即按照递归顺序取第二次出现的数组成的序列

    • 后序:先处理左,再处理右,最后处理头

      即按照递归顺序取第三次出现的数组成的序列

    image-20211002090134578

    非递归实现方法

    任何递归函数都可以改成非递归函数

    • 先序:

    每次:

    1. 从栈中弹出一个节点cur
    2. 打印(处理)cur
    3. 先右节点再左节点(如果有)
    4. 周而复始
    public static void preOrderUnRecur(Node head)
    {
    	if(head != null)
    	{
    		Stack<Node> stack = new Stack<Node>();
    		stack.add(head);
    		while(!stack.isEmpty())
    		{
    			head = stack.pop();
    			cout<<head.value<<" ";
    			if(head.right != null)
    				stack.push(head.right);
    			if(head.left != null)
    				stack,push(head.left)
    		}
    	}
    }
    
    • 中序

    每次:

    每棵子树,整个树左边界进栈,在依次弹出节点的过程中打印,并且对弹出节点的右数重复此操作

    image-20211002092536496

    public static void inOrderUnRecur(Node head)
    {
    	if(head != null)
    	{
    		Stack<Node> stack =new Stack<Node>();
    		while(!stack.isEmpty()	|| head != null)
    		{
    			if(head != null)//不停地把左边界进栈
    			{
    				stack.push(head);
    				head = head.left;
    			}
    			else//head往左走的时候,若走到空位置上,开始弹出节点,然后移动到它的右孩子上
    			{
                    head = stack.pop();
                    cout<<head.value<<" ";
                    head = head.right;
    			}
    		}
    	}
    }
    
    • 后序

    每次:

    ​ 准备两个栈

    1. 从栈中弹出一个节点cur
    2. 将cur放入收集栈后
    3. 先压左节点再压右节点(如果有)
    4. 周而复始

    因为为头右左,进一次新栈再出栈后顺序颠倒,为右左头

    public static void posOrderUnRecur1(Node head)
    {
    	if(head != null)
    	{
    	//准备两个栈
    		Stack<Node> s1 = new Stack<Node>();
    		Stack<Node> s2 = new Stack<Node>();
    		s1.push(head);
    		while(!s1.isEmpty())
    		{
    			head = s1.pop();
    			s2.push(head);
    			if(head.left != null)
    				s1.push(head.left);
    			if(head.right != null)
    				s1.push(head.right);
    		}
    	}
    	while(!s2.isEmpty())
    		cout<<s2.pop().value<<" ";
    }
    

    完成二叉树的宽度优先遍历(求一棵二叉树的宽度)

    思路:宽度遍历用队列,先进先出

    1. 先把头节点放入队列
    2. 弹出就打印
    3. 先放左再放右
    4. 周而复始
    public static void width(Node head)
    {
    	if(head == null)
    		return ;
    	Queue<Node> queue = new LinkedList<>();
    	queue.add(head);
    	//若还希望每一层的节点个数,遍历到某个节点能知道它是第几层
    	HAshMap<Node, Integer> levelMap = new HashMap<>();
    	levelMap.put(head,1);
    	int curLevel = 1;//当前在第几层
    	int curLevelNodes = 0;//当前层数的节点个数
    	int max = Integer.MIN_VALUE;//等于系统最小
    	while(!queue.isEmpty())
    	{
    		Node cur = queue.poll();
    		int curNodeLevel = levelMap,get(cur);
    		if(curNodeLevel == curLevel)//如果当前来到的这个层数正是正在统计节点的这个层数,则该层数的nodes就++
    		{
    			curLevelNodes++;
    		}
    		else//来到的节点已经来到下一层的节点了,说明上一层的节点已经++结束了,应结算
    		{
    			max = Math.max(max,curLevelNodes);
    			curLevel++;
    			curLevelNodes = 1;
    		}
    //		cout<<cur.value<<" ";
    		if(cur.left != null)
    		{
    			levelMAp.put(cur.left, curNodeLevel+1);
    			queue.add(cur.left);
    		}
    		if(cur.right != null)
    		{
    			levelMAp.put(cur.right, curNodeLevel+1);
    			queue.add(cur.right);
    		}
    	}
    }
    

    若不用哈希表但希望能知道它的层数

    设置几个变量

    Node Cur_end 当前弹出的节点所在层中的最后一个节点

    Node Next_end 当前弹出的节点的下一层中的最后一个节点

    int Cur_levelNode 该层有几个节点

    步骤

    1. Cur_end是最新弹出队列的节点
    2. Next_end是最新进队的节点
    3. 在一层结束后,Cur_end的值修改为Next_end的值,max与当前的Cur_levelNode做大小比较,Next_end标空
  • 相关阅读:
    SQL server 2005 创建数据库失败提示“Collation <服务器默认值> is not valid”解决方法
    ACM PKU 1011 Sticks 深度优先搜索
    pku1088 滑雪
    javascript 使用金山词霸网络翻译
    JQuery基础 document.ready
    遍历aspx页面中所有的指定控件
    DataTable,DataView和DataGrid中一些容易混淆的概念
    C#中的DBNull、Null、和String.Empty解释
    哈佛大学管训
    美国教育考试中心公布2010年托业考试时间表
  • 原文地址:https://www.cnblogs.com/fzujly/p/15361433.html
Copyright © 2011-2022 走看看