给定一棵二叉树的头节点head,完成二叉的先序丶中序丶和后序遍历,如果二叉树的节点为N,要求时间复杂度为O(N),空间复杂度为O(1);
实际使用递归函数来完成遍历都是使用了栈函数,空间复杂度为O(h),h为二叉树的高度。那么我们应该怎么来解决空间复杂度问题呢?
答案就是使用Morris遍历。Morris实质上就是避免使用栈结构,而是下层到上层,下层的空闲指针指向上层的某个节点,从而完成了下层到上层的移动,首先以中序遍历举例
第1步:假设当前子节点的头节点为h,让h的左子树的最右节点的right指针指向h,然后h的左子树继续步骤1的处理过程,直到遇到一某一个节点没有左子树记为Node,进入步骤2
第2步:从node开始通过每个节点的right指针进行移动,并依次打印,假设移动到节点为cur,对每一个cur节点都判断cur的左子树中最右节点是否指向cur
2(1)如果是,让cur结点的左子树的最右结点的right指向空,然后打印,然后让cur的right指针移动到下一个节点(得到右节点)
2(2)如果不是,以cur为头的子树重回步骤1
1 using System;
2 using System.Collections.Generic;
3
4 namespace NetFramework
5 {
6 public class BiTree
7 {
8 public int value;
9 public BiTree left;
10 public BiTree right;
11
12 public BiTree(int data)
13 {
14 this.value = data;
15 }
16
17 /// <summary>
18 /// 中序遍历二叉树,空间复杂度O(1)
19 /// </summary>
20 /// <param name="head">头节点</param>
21 public void MorrishIn(BiTree head)
22 {
23 //如果头节点为空退出
24 if (head == null) return;
25 //记录头节点
26 BiTree cur1 = head;
27 //用来比较判断
28 BiTree cur2 = null;
29 //如果记录的节点不为空
30 while (cur1 != null)
31 {
32 //找到左孩子,记录起来
33 cur2 = cur1.left;
34 //如果左孩子有数据
35 if (cur2 != null)
36 {
37 //判断左孩子的右孩子不为空或指向的不是自己
38 while (cur2.right != null && cur2.right != cur1)
39 {
40 //这里就找到了头结点的左孩子的最右孩子
41 cur2 = cur2.right;
42 }
43 //如果右孩子的数据为空,证明已经是最右了
44 if (cur2.right == null)
45 {
46 //将这个最右的孩子的指针指回头节点
47 cur2.right = cur1;
48 //然后头节点向左孩子移动,这样是为了先找出最左的叶子节点
49 cur1 = cur1.left;
50 //退出继续进入步骤1
51 continue;
52 }
53 else
54 {
55 //将叶子节点的右节点置空
56 cur2.right = null;
57 }
58 }
59 //如果不符合以上条件证明已经找到要输出的节点,先输出
60 Console.Write(cur1.value + " ");
61 //然后移动右节点
62 cur1 = cur1.right;
63 }
64 }
65
66 }
67 }
打印输出了1234567,完成了中序遍历