劍指offer之二叉搜索樹和雙向鏈表

1 問題

比如我們搜索二叉樹如下,我們需要變成雙向鏈表
 

 

 
2 分析

我們知道這個變成雙向鏈接的時候是按照樹的中序遍歷打印的,我們只需要在中序遍歷打印的時候操作該節(jié)點,我們可以用臨時變量保存這個節(jié)點,同時我們也需要單獨增加一個鏈表節(jié)點變量,我們需要保證這個節(jié)點的左邊指向是該鏈表節(jié)點,然后該鏈表節(jié)點的右指向是這個節(jié)點,然后我們再把這個節(jié)點賦值給這個鏈表節(jié)點,就這樣一直移動下去即可。

 

 
3 代碼實現(xiàn)

我這里以下面的搜索二叉樹進行操作的

     
                    4
               2         6
            1     3   5     7     

    #include <stdio.h>
    #include <stdlib.h>
     
    typedef struct Tree
    {
        int value;
        struct Tree* left;
        struct Tree* right;
    } Tree;
     
    /*
     * 把搜索二叉樹轉(zhuǎn)成雙向鏈表,我們按照中序遍歷
     */
    void convertNode(Tree* node, Tree** lastNodeList)
    {
        if (node == NULL)
            return;
        Tree* pCurrent = node;
        if (pCurrent->left != NULL)
        {
            convertNode(pCurrent->left, lastNodeList);
        }
        //這里就要進行我們每個節(jié)點的前后正確的指向了
        pCurrent->left = *lastNodeList;
        if (*lastNodeList != NULL)
        {
            (*lastNodeList)->right = pCurrent;
        }
        *lastNodeList = pCurrent;
     
        if (pCurrent->right != NULL)
        {
            convertNode(pCurrent->right, lastNodeList);
        }
    }
    
     
    /*
     * 把翻轉(zhuǎn)好的雙向鏈表尾巴節(jié)點移動到鏈表頭
     */
    Tree* convert(Tree* node, Tree* lastNodeList)
    {
        if (node == NULL || lastNodeList == NULL)
        {
            printf("node is NULL or lastNodeList is NULL\n");
            return NULL;
        }
        Tree* last = NULL;
        convertNode(node, &lastNodeList);
        //因為這個時候lastNodeList已經(jīng)到了雙向鏈表尾巴,我們需要移動到鏈表頭
        Tree* headNodeList = lastNodeList;
        while (headNodeList != NULL && headNodeList->left != NULL)
        {
            headNodeList = headNodeList -> left;
        }
        return headNodeList;
    }
     
    /*
     * 雙向鏈表從左到右打印
     */
    void printRightList(Tree* headNodeList)
    {
        if (headNodeList == NULL)
        {
            printf("headNodeList is NULL\n");
            return;
        }
        printf("we will print list from left to right\n");
        Tree* pCurrent = headNodeList;
        while (pCurrent != NULL)
        {
            printf("value is %d\n", pCurrent->value);
            pCurrent = pCurrent->right;
        }
    }
     
    /*
     * 雙向鏈表從右到左打印
     */
    void printLeftList(Tree* headNodeList)
    {
        if (headNodeList == NULL)
        {
            printf("headNodeList is NULL\n");
            return;
        }
        printf("we will print list from right to left\n");
        Tree* pCurrent = headNodeList;
        //先把鏈表頭結(jié)點移動為鏈表的尾巴
        while (pCurrent->right != NULL)
        {
            //printf("value is %d\n", pCurrent->value);
            pCurrent = pCurrent->right;
        }
        //pCurrent = pCurrent->left;
        
        while (pCurrent != NULL)
        {
            printf("value is %d\n", pCurrent->value);
            pCurrent = pCurrent->left;
        }
    }
     
     
    int main(void)
    {
        Tree *node1 , *node2 , *node3, *node4, *node5, *node6, *node7;
        node1 = (Tree *)malloc(sizeof(Tree));
        node2 = (Tree *)malloc(sizeof(Tree));
        node3 = (Tree *)malloc(sizeof(Tree));
        node4 = (Tree *)malloc(sizeof(Tree));
        node5 = (Tree *)malloc(sizeof(Tree));
        node6 = (Tree *)malloc(sizeof(Tree));
        node7 = (Tree *)malloc(sizeof(Tree));
        node1->value = 4;
        node2->value = 2;
        node3->value = 6;
        node4->value = 1;
        node5->value = 3;
        node6->value = 5;
        node7->value = 7;
        
        node1->left = node2;
        node1->right = node3;
        node2->left = node4;
        node2->right = node5;
        node3->left = node6;
        node3->right = node7;
        
        node4->left = NULL;
        node4->right = NULL;
        
        node5->left = NULL;
        node5->right = NULL;
     
        node6->left = NULL;
        node6->right = NULL;
        
        node7->left = NULL;
        node7->right = NULL;
        
        Tree* list = (Tree *)malloc(sizeof(Tree));
        if (!list)
        {
            printf("malloc list fail\n");
            return -1;
        }
        Tree* firstNodeList = NULL;
        //convertNode(node1, &list);
        firstNodeList = convert(node1, list);
        if (firstNodeList == NULL)
        {
            printf("firstNodeList is NULL\n");
            return -1;
        }
        printRightList(firstNodeList);
        printLeftList(firstNodeList);
        return 0;
    }

 

 
4 運行結(jié)果

    we will print list from left to right
    value is 0
    value is 1
    value is 2
    value is 3
    value is 4
    value is 5
    value is 6
    value is 7
    we will print list from right to left
    value is 7
    value is 6
    value is 5
    value is 4
    value is 3
    value is 2
    value is 1
    value is 0
     
     

 
 




 


作者:chen.yu
深信服三年半工作經(jīng)驗,目前就職游戲廠商,希望能和大家交流和學習,
微信公眾號:編程入門到禿頭 或掃描下面二維碼
零基礎(chǔ)入門進階人工智能(鏈接)