題目
給你一個二叉樹,請你返回其按 層序遍歷 得到的節點值。 (即逐層地,從左到右訪問所有節點)。
示例: 二叉樹:[3,9,20,null,null,15,7],
3 / \ 9 20 / \ 15 7
返回其層次遍歷結果:
[ [3], [9,20], [15,7] ]
來源:力扣(LeetCode)
鏈接:https://leetcode-cn.com/problems/binary-tree-level-order-traversal
著作權歸領釦網絡所有。商業轉載請聯繫官方授權,非商業轉載請註明出處。
分析
關於層序遍歷,可以設計一個隊列。
主要思路:首先進隊一個“隔板”,然後根節點入隊。然後出隊一個元素,若它是“隔板”就申請一個新的數組空間並進隊一個“隔板”。如果它有左右子節點就讓它子節點入隊。如此循環,直到隊列中連着兩次訪問到“隔板”。
代碼
#define ARRAY_MAX 1000
typedef struct QueueNode {
struct TreeNode *data;
struct QueueNode *next;
} QueueNode_t;
typedef struct LinkQueue {
int count;
QueueNode_t *front;
QueueNode_t *rear;
} LinkQueue_t;
int initQueue(LinkQueue_t *queue) {
queue->front = queue->rear = malloc(sizeof(QueueNode_t));
if (NULL == queue->front)
return -1;
queue->front->next = NULL;
queue->count = 0;
return 0;
}
int enqueue(LinkQueue_t *queue, struct TreeNode *data) {
QueueNode_t *newNode = malloc(sizeof(QueueNode_t));
if (NULL == newNode) {
return -1;
}
newNode->data = data;
newNode->next = NULL;
queue->rear->next = newNode;
queue->rear = newNode;
queue->count++;
return 0;
}
int dequeue(LinkQueue_t *queue, struct TreeNode **data) {
if (queue->front == queue->rear) {
return -1;
}
QueueNode_t *denode = queue->front->next;
*data = denode->data;
queue->front->next = denode->next;
if (denode == queue->rear) {
queue->rear = queue->front;
}
free(denode);
queue->count--;
return 0;
}
void destroyQueue(LinkQueue_t *queue) {
/*q->front 指向頭node, queue->rear指向下一個節點,這裏當臨時指針用*/
while (queue->front) {
queue->rear = queue->front->next;
free(queue->front);
queue->front = queue->rear;
}
}
int emptyQueue(LinkQueue_t *queue) {
return queue->front == queue->rear ? 1 : 0;
}
/**
* 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().
* 注:levelOrder返回的是一個指針數組,每個成員存儲指向當前下標所在層的所有節點(另一個數組)。returnSize爲levelOrder數組的大小。
* returnColumnSizes指向一個數組,每個成員對應levelOrder裏相同下標指向的一維數組的大小。
*/
int **levelOrder(struct TreeNode *root, int *returnSize, int **returnColumnSizes) {
if (NULL == root){
*returnSize = 0;
return NULL;
}
int level = 0, i = 0, cnt = 0;
int **retArray = malloc(ARRAY_MAX * sizeof(int *));
struct TreeNode *data = NULL;
*returnColumnSizes = malloc(ARRAY_MAX * sizeof(int));
LinkQueue_t queue;
initQueue(&queue);
enqueue(&queue, root);
while (!emptyQueue(&queue)) {
cnt = queue.count;
retArray[level] = malloc(sizeof(int) * cnt);
for (i = 0; i < cnt; i++) {
dequeue(&queue, &data);
retArray[level][i] = data->val;
if (data->left)
enqueue(&queue, data->left);
if (data->right)
enqueue(&queue, data->right);
}
(*returnColumnSizes)[level] = cnt;
level++;
}
*returnSize = level;
destroyQueue(&queue);
return retArray;
}
運行結果
作弊的代碼
當然也可以實現判斷一下樹總共有多少節點,不過這種做法有點像作弊。不是很推薦。
// 這樣寫死是不推薦的操作。可以用在開頭的時候計算這棵樹總共有多少個節點。
struct TreeNode* queue[10000] = {0};
int maxDepth(struct TreeNode* root){
//查找最深的節點,並返回層數
int left_depth = 0;
int right_depth = 0;
if (root == NULL) {
return 0;
}
left_depth = maxDepth(root->left);
right_depth = maxDepth(root->right);
return left_depth > right_depth ? left_depth + 1 : right_depth + 1;
}
/**
* 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** levelOrder(struct TreeNode* root, int* returnSize, int** returnColumnSizes){
int tail = 0;
int front = 0;
if (root == NULL) {
*returnSize = 0;
*returnColumnSizes = NULL;
return NULL;
}
int depth = maxDepth(root);
*returnSize = depth;
int* columarry = (int*)malloc(depth * sizeof(int));
int* columarrytmp = columarry;
int** result = (int**)malloc(depth * sizeof(int *));
int** resulttmp = result;
queue[tail] = root;
front += 1;
while (front != tail) {
int num = front - tail;
*(columarrytmp++) = num;
int * arry = malloc(num * sizeof(int));
int * arrytmp = arry;
for (int i = 0; i < num; i++) {
struct TreeNode* tmp = queue[tail];
*(arrytmp++) = tmp->val;
tail++;
if (tmp->left != NULL) {
queue[front] = tmp->left;
front++;
}
if (tmp->right != NULL) {
queue[front] = tmp->right;
front++;
}
}
*(resulttmp++) = arry;
}
*returnColumnSizes = columarry;
return result;
}
運行結果
這道題目我在阿里雲面試的時候遇到過類似的:利用非遞歸手段遍歷一棵二叉樹。當時我也是採用了隊列的方式。
我現在因爲馬上就要去阿里雲實習了,有好多東西是需要我惡補的。所以我打算暫時少更一點leetcode日記了,可能要從日更變成周更左右……不過影響不大嘿嘿。
我出於熟悉java的目的(沒錯我今天剛開始學習java,我會拿一些以前C做過過的題目練練手)。
感謝大家的瀏覽和點贊。