[leetcode日记]102:二叉树层序遍历

题目

给你一个二叉树,请你返回其按 层序遍历 得到的节点值。 (即逐层地,从左到右访问所有节点)。

示例: 二叉树:[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做过过的题目练练手)。

感谢大家的浏览和点赞。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章