144. 二叉树的前序遍历
题目
给你二叉树的根节点 root
,返回它节点值的 前序 遍历。
解题思路
递归
代码
/*** Definition for a binary tree node.* struct TreeNode {* int val;* struct TreeNode *left;* struct TreeNode *right;* };*/
/*** Note: The returned array must be malloced, assume caller calls free().*/// 辅助函数:递归前序遍历
void preorderHelper(struct TreeNode* root, int* result, int* index) {if (root == NULL) {return;}// 前序遍历顺序:根-左-右result[(*index)++] = root->val; // 访问根节点preorderHelper(root->left, result, index); // 递归遍历左子树preorderHelper(root->right, result, index); // 递归遍历右子树
}// 获取树的节点数量
int getTreeSize(struct TreeNode* root) {if (root == NULL) {return 0;}return 1 + getTreeSize(root->left) + getTreeSize(root->right);
}int* preorderTraversal(struct TreeNode* root, int* returnSize) {// 处理空树情况if (root == NULL) {*returnSize = 0;return NULL;}// 计算树的节点数量int size = getTreeSize(root);// 分配结果数组内存int* result = (int*)malloc(size * sizeof(int));if (result == NULL) {*returnSize = 0;return NULL;}// 初始化索引int index = 0;// 递归进行前序遍历preorderHelper(root, result, &index);// 设置返回数组大小*returnSize = size;return result;
}
改进代码
递归会有爆栈的风险,而且递归一次是一次函数调用 涉及到栈帧的增加和减少会额外增加开销,递归的好处是代码比较简洁
迭代算法
迭代实现的核心是使用显式的栈结构来模拟递归过程中的系统调用栈。
算法步骤
- 创建一个栈,将根节点压入栈中
- 当栈不为空时,循环执行以下操作:
- 弹出栈顶节点,访问它(即记录其值)
- 将该节点的右子节点压入栈(如果存在)
- 将该节点的左子节点压入栈(如果存在)
- 当栈为空时,遍历完成
/*** Definition for a binary tree node.* struct TreeNode {* int val;* struct TreeNode *left;* struct TreeNode *right;* };*/
/*** Note: The returned array must be malloced, assume caller calls free().*/// 迭代方式计算二叉树节点数量
int getTreeSizeIterative(struct TreeNode* root) {if (root == NULL) {return 0;}int count = 0;// 使用栈存储待访问的节点struct TreeNode** stack = (struct TreeNode**)malloc(10000 * sizeof(struct TreeNode*));if (stack == NULL) {return 0; // 内存分配失败}// 初始化栈int top = -1;stack[++top] = root;while (top >= 0) {// 弹出节点struct TreeNode* node = stack[top--];count++; // 记录节点数// 注意:由于栈是后进先出,所以要先将右子节点入栈,再将左子节点入栈// 这样才能保证左子节点先于右子节点被处理if (node->right != NULL) {stack[++top] = node->right;}if (node->left != NULL) {stack[++top] = node->left;}}free(stack);return count;
}int* preorderTraversal(struct TreeNode* root, int* returnSize) {if(root == NULL){*returnSize = 0;return NULL;}// 得到节点数*returnSize = getTreeSizeIterative(root);// 为结果分配内存 int* result = (int*) malloc(sizeof(int) * (*returnSize));// 使用栈存储待访问的节点struct TreeNode** stack = (struct TreeNode**)malloc((*returnSize) * sizeof(struct TreeNode*));// 初始化栈int top = -1;stack[++top] = root;int count = 0;while (top >= 0) {// 节点出栈,并记录值struct TreeNode* node = stack[top--];result[count++] = node->val;// 注意:由于栈是后进先出,所以要先将右子节点入栈,再将左子节点入栈// 这样才能保证左子节点先于右子节点被处理if (node->right != NULL) {stack[++top] = node->right;}if (node->left != NULL) {stack[++top] = node->left;}}free(stack);return result;
}