1. 程式人生 > >二叉樹轉換成雙向鏈表

二叉樹轉換成雙向鏈表

遞歸 out bsp root 進入 return 方式 sub AD

前言

  二叉樹我們都是知道,一個節點有兩個子節點,分別為左右子節點,樹形結構則分叉左右子樹。如何把二叉樹轉換成雙向鏈表,方式方法有許多,這裏主要介紹一種方法,直接在二叉樹本身的左右鏈上做文章,采用遞歸的方式。

  方法步驟如下:

    1. 先轉換做子樹為鏈式結構,其遞歸到做子樹最左邊的葉子節點;

2. 鏈表最初的頭節點為左子樹的最左葉子節點;

3. 轉換右子樹的鏈式結構;

    4. 記錄右子樹鏈式的尾節點;

    5. 合並左子樹和右子樹的鏈式結構,

  總之,遞歸深入到左葉子節點,從左子樹遞歸回退向上深入右子樹,最後合並鏈式的一個搗鼓過程;整個過程可以想象為:從最左下角開始,然後上升,接著進入局部右下角,最後合並,按照上述步驟搗鼓搗鼓直到山崩地裂。

編碼

#include <iostream>


struct tree_node_t {
    unsigned int value;
    tree_node_t *left;
    tree_node_t *right;
};



int tree_create( tree_node_t *&__root)
{
    int rc = 0;

    __root = nullptr;

    return rc;
}


int tree_push( tree_node_t *&__root, unsigned int __v)
{
    int rc = 0;

    if ( !__root) {
        __root = new tree_node_t();
        if ( nullptr != __root) {
            __root->value = __v;
            __root->left  = nullptr;
            __root->right = nullptr;

        } else { rc = -1; }
    } else {
        if ( __v < __root->value) {
            rc = tree_push( __root->left, __v);
        }

        if ( __v > __root->value) {
            rc = tree_push( __root->right, __v);
        }
    }

    return rc;
}


void tree_each( const tree_node_t *__root)
{
    if ( __root) {
        tree_each( __root->left);

        std::cout << __root->value << " ";

        tree_each( __root->right);
    }
}



void tree_to_list( tree_node_t *&__current, tree_node_t *&__head, tree_node_t *&__tail)
{
    if ( nullptr != __current) {
        tree_node_t *head  = nullptr;
        tree_node_t *tail  = nullptr;

        /** Link of a left subtree */
        if ( __current->left) {
            (void )tree_to_list( __current->left, head, tail); {
                __head          = head;
                __current->left = tail;
                tail->right     = __current;
            }
        } else {
            __head = __current;
        }

        /** Link of a right subtree */
        if ( __current->right) {
            (void )tree_to_list( __current->right, head, tail); {
                __tail            = tail;
                __current->right  = head;
                head->left        = __current;
            }
        } else {
            __tail = __current;
        }
    } else {
        __current = nullptr;
        __head    = nullptr;
        __tail    = nullptr;
    }

    __current = __head;
}


void tree_list_each( const tree_node_t *__head)
{
    if ( __head) {
        std::cout << __head->value << " ";

        tree_list_each( __head->right);
    }
}


int main( int argc, const char **argv)
{
    tree_node_t *root = nullptr;
    tree_create( root);

    srand( time( NULL));

    for ( unsigned int i = 0; i < 32; i++) {
        tree_push( root, rand() % 100);
    }

    std::cout << "\ntree_each:\n";
    tree_each( root);

    tree_node_t *tmp_head = nullptr;
    tree_node_t *tmp_tail = nullptr;
    tree_to_list( root, tmp_head, tmp_tail);

    std::cout << "\ntree_list_each:\n";
    tree_list_each( root);
    std::cout << "\n";

    return 0;
}

註:該代碼采用c++11實現,畢竟nullptr是c++11引入,編譯時加 -std=c++11 選項。

二叉樹轉換成雙向鏈表