zoukankan      html  css  js  c++  java
  • 遍历二叉树的神级方法

    给定一棵二叉树的头节点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,完成了中序遍历

  • 相关阅读:
    Selenium + WebDriver 各浏览器驱动下载地址
    selenium之 文件上传所有方法整理总结【转】
    FakeUserAgentError('Maximum amount of retries reached') 彻底解决办法
    git关联远程仓库
    通过chrome console 快速获取网页连接
    【转】Selenium
    【转】fiddler抓包HTTPS请求
    【转】Wireshark和Fiddler分析Android中的TLS协议包数据(附带案例样本)
    php 通过 create user 和grant 命令无法创建数据库用户和授权的解决办法
    差等生也是需要交卷的
  • 原文地址:https://www.cnblogs.com/BigDong/p/8018981.html
Copyright © 2011-2022 走看看