BST树遍历O(n)时间复杂度+O(一)空间复杂度

BST树遍历O(n)时间复杂度+O(1)空间复杂度

问题描述

BST树的遍历问题常常遇到,前序、中序、后序等。如果用递归的话,是非常方便的,其时间复杂度是O(n),空间复杂度是O(log n)级别。PS:*问答网站上有一个问题指出,这类问题的复杂度不应该直接说是O(log n),因为编译器会进行一些优化,比如修改成尾递归等。不过我们这里暂时不考虑优化,从程序逻辑上来讲,BST递归遍历认为是O(log n)的复杂度。

OK,那么如果改进遍历方法,使得空间复杂度只有O(1)呢?

解决方案

解决方法中,是针对每个叶节点,将其右指针指向后继节点。这是核心思想。

         4
        /  \
       2    6
      / \  / \
     1   3 5  7

比如上述图中,将1的右指针指向2,将3的右指针指向4,5的右指针指向6. 具体代码如下

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cstring>
#include <string>
#include <cmath>

using namespace std;

struct Node {
    int value;
    Node *left, *right;
    Node(int v): value(v), left(NULL), right(NULL) {}
};

class Solution {
public:
    void solve() {
        // build up a BST tree
        Node *root = new Node(4);
        root->left = new Node(2);
        root->left->left = new Node(1);
        root->left->right = new Node(3);
        root->right = new Node(6);
        root->right->left = new Node(5);
        root->right->right = new Node(7);
        root->right->right->right = new Node(8);
        // in order traversal
        inorder_traversal(root);
    }
    // use o(lg n) time, use o(1) space
    void inorder_traversal(Node *root) {
        Node *curr = root;
        while (curr) {
            if (curr->left) {
                Node *p = curr->left;
                while (p->right != NULL && p->right != curr) p = p->right;
                if (p->right == NULL) {
                    // make new link, which is the key point!
                    p->right = curr;
                    curr = curr->left;
                } else {
                    // p->right == curr
                    printf("%d ", curr->value);
                    p->right = NULL;
                    curr = curr->right;
                }
            } else {
                // for the leaf nodes
                printf("%d ", curr->value);
                curr = curr->right;
            }
        }
    }
};

int main() {
    Solution solution;
    solution.solve();
    return 0;
}