LeetCode—— Binary Tree Traversal

二叉树遍历的三道题

Binary Tree Preorder Traversal

Binary Tree Inorder Traversal

Binary Tree Postorder Traversal

LeetCode 上二叉树的节点定义如下:

// 树的节点 struct TreeNode {
      int val;
      TreeNode *left;
      TreeNode *right;
      TreeNode(int x) : val(x), left(nullptr), right(nullptr) { }
};

常规递归算法

/**
 * 递归先序遍历
 */
void preOrder_traverse_recur(BiTree T) {
  if(T == NULL) {
    return;
  } else {
    printf("%d", T->val);
    preOrder_traverse_recur(T->left);
    preOrder_traverse_recur(T->right);
  }
}

/**
 * 递归中序遍历
 */
void inOrder_traverse_recur(BiTree T) {
  if(T == NULL) {
    return;
  } else {
    inOrder_traverse_recur(T->left);
    printf("%d", T->val);
    inOrder_traverse_recur(T->right);
  }
}

/**
 * 递归后序遍历
 */
void postOrder_traverse_recur(BiTree T) {
  if(T == NULL) {
    return;
  } else {
    postOrder_traverse_recur(T->left);
    postOrder_traverse_recur(T->right);
    printf("%d", T->val);
  }
}

栈 算法

时间复杂度 O(n),空间复杂度 O(n)

// LeetCode, Binary Tree Preorder Traversal 
class Solution {
public:
      vector<int> preorderTraversal(TreeNode *root) {
          vector<int> result;
          const TreeNode *p;
          stack<const TreeNode *> s;
          p = root;
          if (p != nullptr) s.push(p);
          while (!s.empty()) {
              p = s.top();
              s.pop();
              result.push_back(p->val);
              if (p->right != nullptr) s.push(p->right);
              if (p->left != nullptr) s.push(p->left);
          }
          return result;
      }
};
// LeetCode, Binary Tree Inorder Traversal 
class Solution {
public:
      vector<int> inorderTraversal(TreeNode *root) {
          vector<int> result;
          const TreeNode *p = root;
          stack<const TreeNode *> s;
          while (!s.empty() || p != nullptr) {
              if (p != nullptr) {
                  s.push(p);
                  p = p->left;
              } else {
                  p = s.top();
                  s.pop();
                  result.push_back(p->val);
                  p = p->right;
} }
          return result;
      }
};
// LeetCode, Binary Tree Postorder Traversal
class Solution {
public:
vector<int> postorderTraversal(TreeNode *root) { vector<int> result;
    /* p,正在访问的结点,q,刚刚访问过的结点 */ 
    const TreeNode *p, *q;
    stack<const TreeNode *> s;
    p = root;
    do {
        while (p != nullptr) { /* 往左下走 */
            s.push(p);
            p = p->left; 
        }
        q = nullptr;
        while (!s.empty()) {
            p = s.top();
            s.pop();
            /* 右孩子不存在或已被访问,访问之 */ 
            if (p->right == q) {
                result.push_back(p->val);
                q = p; /* 保存刚访问过的结点 */ 
            } else {
                /* 当前结点不能访问,需第二次进栈 */ 
                s.push(p);
                /* 先处理右子树 */
                p = p->right;
                break; 
            }
        }
    } while (!s.empty());
    return result;
    }
};

Morris算法

时间复杂度 O(n),空间复杂度 O(1)

参考:http://www.tuicool.com/articles/zA7NJbj

算法伪码(Morris InOrder) :

while 节点非空
   if 当前节点没有左子树
     访问该节点
     转向右节点
   else
     找到左子树的最右节点
        if 最右子节点指空
            最右节点的右指针指向根
            转向左子树节点
        else //最右子节点指根
            消除指根指针
            根节点右移

bitree_mirros

C++实现:

Morris 中序遍历

void morris_inorder(TreeNode *root) {  
   TreeNode *p = root, *tmp;
   while (p) {  
       if (p->left == NULL) {  
           printf("%d ", p->key);  
           p = p->right;  
       }  
       else {  
           tmp = p->left;  
           while (tmp->right != NULL && tmp->right != p)  
               tmp = tmp->right;  
           if (tmp->right == NULL) {  
               tmp->right = p;  
               p = p->left;  
           } else {  
               printf("%d ", p->key);  
               tmp->right = NULL;  
               p = p->right;  
           }  
       }  
   }  
}
Morris 先序遍历

void morris_preorder(TreeNode *root) {
    TreeNode *p = root, *tmp;
    while (p) {
        if (p->left == NULL) {
            printf("%d ",p->key);
            p = p->right;
        } else {
            tmp = p->left;
            while (tmp->right != NULL && tmp->right != p) {
                tmp = tmp->right;
            }
            if (tmp->right == NULL){
                print("%d ",p->key);
                tmp->right = p;
                p = p->left;
            } else {
                tmp->right = NULL;
                p = p->right;
            }
        }
    }
}

Morris后序遍历二叉树的算法与上面的算法思想一致,只是在遍历前,增加了一个类似头节点的节点作为整个遍历过程的起始节点。

/**
 * morris后序遍历算法 
 */
void morris_postOrder(BiTree T) {
  BNode *dump = malloc(sizeof(BNode));
  BNode *p, *temp;
  dump->left = T;
  p = dump;
  while(p) {
    if(p->left == NULL) {
      p = p->right;
    } else {
      temp = p->left;
      while(temp->right != NULL && temp->right != p) {
        temp = temp->right;
      }
      if(temp->right == NULL) {
        temp->right = p;
        p = p->left;
      } else {
        printReverse(p->left, temp);
        temp->right = NULL;
        p = p->right;
      }
    }
  }
  free(dump);
}

代码中的printReverse()函数就是逆序遍历从p->left到temp这条路径上的节点的过程;
printReverse函数先将从from节点到to节点的这条路径反转,再输出,最后还原.

/**
 * 相当于单链表的反转
 */
void reverse(BNode *from, BNode *to) {
  BNode *x, *y, *z;
  if(from == to) {
    return;
  }
  x = from;
  y = from->right;
  while(x != to) {
    z = y->right;
    y->right = x;
    x = y;
    y = z;
  }
}

void printReverse(BNode *from , BNode *to) {
  BNode *p;
  reverse(from, to);
  p = to;
  while(1) {
    printf("%4c", p->ch);
    if(p == from) {
      break;
    }
    p = p->right;
  }
  reverse(to, from);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值