二叉树的递归与非递归
二叉树的递归与非递归
二叉树节点结构
class Node<V>
{
V value;//一个节点有自己的值
Node left;//指向左孩子的指针
Node right;//指向右孩子的指针
}
递归实现方法
-
先序:先处理头,再处理左,最后处理右
即按照递归顺序取第一次出现的数组成的序列
-
中序:先处理左,再处理头,最后处理右
即按照递归顺序取第二次出现的数组成的序列
-
后序:先处理左,再处理右,最后处理头
即按照递归顺序取第三次出现的数组成的序列
非递归实现方法
任何递归函数都可以改成非递归函数
- 先序:
每次:
- 从栈中弹出一个节点cur
- 打印(处理)cur
- 先右节点再左节点(如果有)
- 周而复始
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)
}
}
}
- 中序
每次:
每棵子树,整个树左边界进栈,在依次弹出节点的过程中打印,并且对弹出节点的右数重复此操作
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;
}
}
}
}
- 后序
每次:
准备两个栈
- 从栈中弹出一个节点cur
- 将cur放入收集栈后
- 先压左节点再压右节点(如果有)
- 周而复始
因为为头右左,进一次新栈再出栈后顺序颠倒,为右左头
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<<" ";
}
完成二叉树的宽度优先遍历(求一棵二叉树的宽度)
思路:宽度遍历用队列,先进先出
- 先把头节点放入队列
- 弹出就打印
- 先放左再放右
- 周而复始
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 该层有几个节点
步骤
- Cur_end是最新弹出队列的节点
- Next_end是最新进队的节点
- 在一层结束后,Cur_end的值修改为Next_end的值,max与当前的Cur_levelNode做大小比较,Next_end标空