1. 程式人生 > >二叉樹的非遞迴遍歷 (leetcode)

二叉樹的非遞迴遍歷 (leetcode)

利用資料結構-棧,佇列, 加上相應思路等完成。

leetcode練習,隔段時間敲幾次程式碼

非遞迴先序

#include <cstdlib>
#include <iostream>
#include <stack>
using namespace std;

typedef struct node{
    int data;
    struct node *left, *right;
    node(int _data = 0){
        data = _data;
        left = NULL;
        right = NULL;
    }
}Bnode;

Bnode* insert(Bnode* root, int
data) { if (root == NULL) root = new node(data); else{ if (data < root->data) root->left = insert(root->left, data); else root->right = insert(root->right, data); } return root; } /**非遞迴前序遍歷 * * 每次取棧頂節點 * 再將其 右子樹 先入棧, 然後是 左子樹 入棧 * 這樣可以確保每次都是左子樹 比 右子樹先取出來 */
void pre(Bnode* root) { stack<Bnode*> sta; sta.push(root); while (!sta.empty()) { Bnode* top = sta.top(); sta.pop(); printf("%d\t", top->data); if (top->right != NULL) sta.push(top->right); if (top->left != NULL) sta.push(top->left); } } int
main() { int a[] = { 5, 3, 7, 1, 2, 6, 4 }; int n = 7; int i; Bnode *root = NULL; for (i = 0; i < n; i++) { root = insert(root, a[i]); } /* 5 / \ 3 7 / \ / 1 4 6 \ 2 */ pre(root); return 0; }

非遞迴中序

#include <cstdlib>
#include <iostream>
#include <stack>
using namespace std;

typedef struct node{
    int data;
    struct node *left, *right;
    node(int _data = 0){
        data = _data;
        left = NULL;
        right = NULL;
    }
}Bnode;

Bnode* insert(Bnode* root, int data)
{
    if (root == NULL)
        root = new node(data);
    else{
        if (data < root->data)
            root->left = insert(root->left, data);
        else
            root->right = insert(root->right, data);
    }
    return root;
}

/** 中序非遞迴
 每次取棧頂
 而棧的順序是 從根到最左,取出該節點列印並出棧
    如果取出的節點沒有右子樹
        則pLeft = pLeft->right;為NULL,下一次取出其父節點
    如果右子樹不為空
        則 pLeft = pLeft->right;後下一次會往棧中新增右子樹,但是根是在這之前入棧的

    操作確保了一定是 左 根 右 的順序
 */

void inorder(Bnode* root)
{
    stack<Bnode*> sta;
    sta.push(root);
    Bnode *pLeft = root->left;

    while (!sta.empty() || pLeft != NULL) //注意這裡的判斷條件
    {
        while (pLeft != NULL) // 找到最左的節點
        {
            sta.push(pLeft);
            pLeft = pLeft->left;
        }

        pLeft = sta.top(); //取棧頂
        printf("%d\t", pLeft->data);
        sta.pop();

        pLeft = pLeft->right; // 轉向 右子樹
    }
}

//void inorder(Bnode* root)
//{
//  if (root != NULL)
//  {
//      inorder(root->left);
//      printf("%d\t", root->data);
//      inorder(root->right);
//  }
//}

int main()
{
    int a[] = { 5, 3, 7, 2, 1, 6, 4 };
    int n = 7;
    int i;
    Bnode *root = NULL;
    for (i = 0; i < n; i++)
    {
        root = insert(root, a[i]);
    }
    inorder(root);
    return 0;
}

非遞迴後序

#include <cstdlib>
#include <iostream>
#include <stack>
using namespace std;

typedef struct node{
    int data;
    struct node *left, *right;
    node(int _data = 0){
        data = _data;
        left = NULL;
        right = NULL;
    }
}Bnode;

Bnode* insert(Bnode* root, int data)
{
    if (root == NULL)
        root = new node(data);
    else{
        if (data < root->data)
            root->left = insert(root->left, data);
        else
            root->right = insert(root->right, data);
    }
    return root;
}

/**
    訪問根之前,要確保根的右子樹為空 或者 右子樹已經訪問過
           否則要先把右子樹訪問到
 */
void postorder(Bnode* root)
{
    stack<Bnode*> sta;
    sta.push(root);

    Bnode* preVisist = NULL;
    Bnode* pLeft = root->left;

    while (!sta.empty() || pLeft != NULL)
    {
        while (pLeft != NULL)
        {
            sta.push(pLeft);
            pLeft = pLeft->left;
        }

        Bnode* top = sta.top();
        if (top->right == NULL || preVisist == top->right) // 右子數為空 或者 右子數已經訪問過,再訪問根
        {
            printf("%d\n", top->data);
            sta.pop();
            preVisist = top;
            pLeft = NULL;
        }
        else{
            pLeft = top->right;
        }
    }// while
}

int main()
{
    int a[] = { 5, 3, 7, 1, 2, 6, 4 };
    int n = 7;
    int i;
    Bnode *root = NULL;
    for (i = 0; i < n; i++)
    {
        root = insert(root, a[i]);
    }
    postorder(root);
    return 0;
}

使用二叉樹非遞迴遍歷的一些題目

230. Kth Smallest Element in a BST

ac程式碼如下;

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    int kthSmallest(TreeNode* root, int k) {

        if (root == NULL)
            return 0;

        stack<TreeNode*> sta;
        sta.push(root);
        TreeNode* pLeft = root->left;

        int outTh = 1;

        while (!sta.empty() || pLeft != NULL)
        {
            while (pLeft != NULL)
            {
                sta.push(pLeft);
                pLeft = pLeft->left;
            }

            TreeNode* top = sta.top();
            sta.pop();

            if (outTh == k)
            {
                return top->val;
            }
            outTh++;
            //cout << top->val;

            if (top->right != NULL) 
                pLeft = top->right;
        }

        return 0;
    }
};

114. Flatten Binary Tree to Linked List

For example,
Given

     1
    / \
   2   5
  / \   \
 3   4   6

The flattened tree should look like:

  1
    \
     2
      \
       3
        \
         4
          \
           5
            \
             6

採用非遞迴的先序遍歷,逐個節點設定

ac程式碼如下:

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:

    void flatten(TreeNode* root) {
        if (root == NULL)
            return;

        stack<TreeNode*> sta;
        sta.push(root);

        TreeNode* lastNode = NULL;
        while (!sta.empty())
        {
            TreeNode* top = sta.top();
            sta.pop();

            if (top->right != NULL)
                sta.push(top->right);

            if (top->left != NULL)
                sta.push(top->left);

            if (lastNode != NULL){
                lastNode->left = NULL;
                lastNode->right = top;
            }
            lastNode = top;
        }
        return;
    }
};

採用遞迴方法求解的ac程式碼如下, 需要判斷仔細,考慮各種情況

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:

    void dfs(TreeNode* root)
    {
        if (root == NULL)
            return;
        else if (root->left == NULL && root->right == NULL)
            return;
        else if (root->left != NULL && root->right == NULL){
            TreeNode* rootL = root->left;
            dfs(rootL);
            root->left = NULL;
            root->right = rootL;
            return;
        }
        else if (root->left == NULL && root->right != NULL)
        {
            TreeNode* rootR = root->right;
            dfs(rootR);
            root->right = rootR;
            return ;
        }
        else{
            TreeNode* rootL = root->left;
            TreeNode* rootR = root->right;

            dfs(rootL);
            dfs(rootR);

            root->right = rootL;
            root->left = NULL;

            TreeNode* pre = NULL;
            TreeNode* t = rootL;
            while (t != NULL){
                pre = t;
                t = t->right;
            }
            pre->right = rootR;
        }
    }

    void flatten(TreeNode* root) {
        if (root == NULL)
            return;

        dfs(root);

        return;
    }
};