C語言重構【102】二叉樹的層序遍歷

所有題目源代碼:Git地址

題目

給你一個二叉樹,請你返回其按 層序遍歷 得到的節點值。 (即逐層地,從左到右訪問所有節點)。

 

示例:
二叉樹:[3,9,20,null,null,15,7],

    3
   / \
  9  20
    /  \
   15   7
返回其層次遍歷結果:

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

方案:隊列

  • 用隊列實現的,思路同Java版一模一樣,只不過隊列還得手撕實現~
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */

/**
 * 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().
 */


//1,構建隊列,實現壓入和彈出函數 Push_Queue 和 Pop_Queue
//2,利用隊列先進先出的特性實現二叉樹的層序遍歷
//3,將二叉樹根 root 壓入隊列,並將 NULL 作爲每層的區分節點也壓入隊列
//4,從隊列中讀出節點,保存當前節點的值,並且將左右支分別壓入隊列
//5,遇到層的區分節點則處理下一層,直到隊列爲空
#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;
}

int **levelOrder(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[iRetSize] = (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[iRetSize] = (int *)malloc(sizeof(int) * strQueue.iNum);

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

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