二叉树的递归与非递归

二叉树的递归与非递归

二叉树节点结构

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标空
posted @ 2021-10-02 10:19  小滢小滢考第一名  阅读(78)  评论(0编辑  收藏  举报