题目
给你一个二叉树,请你返回其按 层序遍历 得到的节点值。 (即逐层地,从左到右访问所有节点)。
示例: 二叉树:[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做过过的题目练练手)。
感谢大家的浏览和点赞。