C語言重構【107】 二叉樹的層次遍歷 II

所有題目源代碼:Git地址

題目

給定一個二叉樹,返回其節點值自底向上的層次遍歷。 (即按從葉子節點所在層到根節點所在的層,逐層從左向右遍歷)

例如:
給定二叉樹 [3,9,20,null,null,15,7],

    3
   / \
  9  20
    /  \
   15   7
返回其自底向上的層次遍歷爲:

[
  [15,7],
  [9,20],
  [3]
]

方案:

  • 思路同102,只需要吧數組倒過來存就行
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */

#define MAX_LEVEL 1000

//聲明隊列節點結構
struct QueueNode
{
    struct TreeNode *pTreeNode;  //隊列元素:二叉樹節點指針
    struct TreeNodeQueue *pNext; //隊列元素:下一個節點指針
};

//聲明隊列結構
struct TreeNodeQueue
{
    int iNum;                //隊列元素個數
    struct QueueNode *pHead; //隊列頭指針
    struct QueueNode *pTail; //隊列尾指針
};

//函數一:向隊列中增加元素
bool Push_Queue(struct TreeNodeQueue *pQueue, struct TreeNode *pTreeNode)
{
    struct QueueNode *pQueueNode = NULL;

    if (NULL == pQueue)
        return false;

    pQueueNode = (struct QueueNode *)malloc(sizeof(struct QueueNode));
    pQueueNode->pTreeNode = pTreeNode;
    pQueueNode->pNext = NULL;

    if (0 == pQueue->iNum)
    {
        pQueue->pHead = pQueueNode;
        pQueue->pTail = pQueueNode;
        pQueue->iNum += 1;
    }
    else
    {
        pQueue->pTail->pNext = pQueueNode;
        pQueue->pTail = pQueueNode;
        pQueue->iNum += 1;
    }

    return true;
}

//函數二:從隊列中取出元素
struct TreeNode *Pop_Queue(struct TreeNodeQueue *pQueue)
{
    struct TreeNode *pRet = NULL;
    struct QueueNode *pTmp = NULL;

    if ((NULL == pQueue) || (0 == pQueue->iNum))
        return NULL;

    pRet = pQueue->pHead->pTreeNode;

    pQueue->iNum -= 1;
    if (0 == pQueue->iNum)
    {
        free(pQueue->pHead);
        pQueue->pHead = NULL;
        pQueue->pTail = NULL;
    }
    else
    {
        pTmp = pQueue->pHead->pNext;
        free(pQueue->pHead);
        pQueue->pHead = pTmp;
    }

    return pRet;
}
/**
 * Return an array of arrays of size *returnSize.
 * The sizes of the arrays are returned as *returnColumnSizes array.
 * Note: Both returned array and *columnSizes array must be malloced, assume caller calls free().
 */
int** levelOrderBottom(struct TreeNode* root, int* returnSize, int** returnColumnSizes){
    int         iNum        = 0;
    int         iRetSize    = 0;
    int**       pRet        = NULL;
    int*        pRetCol     = NULL;
    struct TreeNodeQueue  strQueue;
    struct TreeNode* pTmpNode = NULL;

    //1,申請空間,並初始化
    pRet = (int**)malloc(sizeof(int*) * MAX_LEVEL);
    memset(pRet, 0x00, sizeof(int*) * MAX_LEVEL);
    pRetCol = (int*)malloc(sizeof(int) * MAX_LEVEL);
    memset(pRetCol, 0x00, sizeof(int) * MAX_LEVEL);
    memset(&strQueue, 0x00, sizeof(struct TreeNodeQueue));

    //2,特殊處理
    if(NULL == root)
    {
        *returnSize = iRetSize;
        *returnColumnSizes = pRetCol;
        return pRet;
    }

    //3,將二叉樹根節點加入隊列,並且加入空節點作爲每層的區分節點
    Push_Queue(&strQueue, root);
    pRet[MAX_LEVEL - iRetSize - 1] = (int*)malloc(sizeof(int) * strQueue.iNum);
    Push_Queue(&strQueue, NULL);

    //4,處理隊列中的二叉樹節點,直到隊列爲空
    while(strQueue.iNum != 0)
    {
        pTmpNode = Pop_Queue(&strQueue);
        if(NULL == pTmpNode)
        {
            if(0 != strQueue.iNum)
            {
                //6,當前層處理完,進入下一層
                iRetSize += 1;
                pRet[MAX_LEVEL - iRetSize - 1] = (int*)malloc(sizeof(int) * strQueue.iNum);

                Push_Queue(&strQueue, NULL);
            }
        }
        else
        {
            //5,處理當前層的節點,分別將左右支壓入隊列
            pRet[MAX_LEVEL - iRetSize - 1][pRetCol[MAX_LEVEL - iRetSize - 1]] = pTmpNode->val;
            pRetCol[MAX_LEVEL - iRetSize - 1] += 1;

            if(NULL != pTmpNode->left)
            {
                Push_Queue(&strQueue, pTmpNode->left);
            }
            if(NULL != pTmpNode->right)
            {
                Push_Queue(&strQueue, pTmpNode->right);
            }
        }
    }

    //7,返回
    *returnSize = iRetSize + 1;
    *returnColumnSizes = &pRetCol[MAX_LEVEL - iRetSize - 1];
    return &pRet[MAX_LEVEL - iRetSize - 1];
}

複雜度計算
  • 時間複雜度:O(n)
  • 空間複雜度:O(n)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章