码迷,mamicode.com
首页 > 其他好文 > 详细

LeetCode—— Binary Tree Traversal

时间:2015-07-23 20:02:57      阅读:113      评论:0      收藏:0      [点我收藏+]

标签:leetcode

二叉树遍历的三道题

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;
?
5.1 二叉树的遍历 91
?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 //最右子节点指根
            消除指根指针
            根节点右移

技术分享

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);
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

LeetCode—— Binary Tree Traversal

标签:leetcode

原文地址:http://blog.csdn.net/mennoa/article/details/47026065

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!