前序遍历:
对于每一个节点,最先访问的是以此节点开始的最左路径。
对于每一个树,最先访问的右子树是在访问左路径是最后遇到的右子树。
左边的节点访问:自上而下
右边的节点访问:自下而上
利用“数据结构——栈”来实现迭代前序遍历
- 访问每一个节点开始的最左路径,访问到的每一个节点入栈
- 最左路径访问完成之后,获取栈顶元素,继续访问以栈顶元素的右子树为根的子结构,继续执行第一步
- 结束:栈为空 || 右子树为空
// C语言代码
// 力扣接口
typedef struct TreeNode* STDataType;
typedef struct Stack
{
STDataType* _a;
int _top; // 栈顶
int _capacity; // 容量
}Stack;
// 初始化栈
void StackInit(Stack* ps)
{
if (ps == NULL)
return;
ps->_top = 0;
ps->_capacity = 0;
ps->_a = NULL;
}
// 栈容量检测
void StackCheck(Stack* ps)
{
if(ps->_top==ps->_capacity)
{
int newcapacity = (ps->_capacity == 0 ? 1 : 2 * ps->_capacity);
ps->_a = (STDataType*)realloc(ps->_a, sizeof(STDataType) * newcapacity);
ps->_capacity = newcapacity;
}
}
// 入栈
void StackPush(Stack* ps, STDataType data)
{
StackCheck(ps);
ps->_a[ps->_top++] = data;
}
// 出栈
void StackPop(Stack* ps)
{
if (ps == NULL || ps->_top == 0)
return;
ps->_top--;
}
// 获取栈顶元素
STDataType StackTop(Stack* ps)
{
assert(ps);
if (ps->_top == 0)
return (STDataType)0;
return ps->_a[ps->_top - 1];
}
// 获取栈中有效元素个数
int StackSize(Stack* ps)
{
assert(ps);
return ps->_top;
}
// 检测栈是否为空,如果为空返回非零结果,如果不为空返回0
int StackEmpty(Stack* ps)
{
assert(ps);
return ps->_top == 0;
}
// 销毁栈
void StackDestroy(Stack* ps)
{
if (ps == NULL)
return;
if (ps->_a)
{
free(ps->_a);
ps->_a = NULL;
ps->_capacity = 0;
ps->_top = 0;
}
}
int BinaryTreeSize(struct TreeNode* root)
{
if (root == NULL)
return 0;
return BinaryTreeSize(root->left) + BinaryTreeSize(root->right) + 1;
}
// 迭代前序遍历
int* preorderTraversal(struct TreeNode* root, int* returnSize)
{
Stack st;
StackInit(&st);
int size=BinaryTreeSize(root);
int* ans=(int*)malloc(sizeof(int)*size);
int idx=0;
while(root || !StackEmpty(&st))
{
while(root)
{
ans[idx++]=root->val;
StackPush(&st, root);
root=root->left;
}
root=StackTop(&st);
StackPop(&st);
root=root->right;
}
StackDestroy(&st);
*returnSize=idx;
return ans;
}
中序遍历:
利用“数据结构——栈”来实现迭代中序遍历
- 以根节点开始,走最左路径,此路径上遇到的每一个节点首先入栈,但不访问
- 获取栈顶元素,访问栈顶元素
- 获取栈顶元素的右子树,继续执行第1步
- 结束:栈为空 || 右子树为空
// 迭代中序遍历
// 栈的代码同上
// 力扣接口
int* inorderTraversal(struct TreeNode* root, int* returnSize)
{
Stack st;
StackInit(&st);
int size=BinaryTreeSize(root);
int* ans=(int*)malloc(sizeof(int)*size);
int idx=0;
while(root || !StackEmpty(&st))
{
while(root)
{
StackPush(&st,root);
root=root->left;
}
root=StackTop(&st);
ans[idx++]=root->val;
StackPop(&st);
root=root->right;
}
StackDestroy(&st);
*returnSize=idx;
return ans;
}
后序遍历:
利用“数据结构——栈”来实现迭代后序遍历
- 以根节点开始,遍历最左路径,遇到的每一个节点,入栈
- 获取栈顶元素:
判断当前栈顶元素是否可以访问:
a. 没有右子树 || 右子树访问完成:可以访问 执行第1步
b. 有右子树但还没有访问完成:不能访问 首先访问右子树,再执行第1步 - 结束:栈为空 || 节点为空
// 迭代后序遍历
// 栈的代码同上
// 力扣接口
int* postorderTraversal(struct TreeNode* root, int* returnSize)
{
Stack st;
StackInit(&st);
int size=BinaryTreeSize(root);
int* ans=(int*)malloc(sizeof(int)*size);
int idx=0;
struct TreeNode* prev=NULL;
struct TreeNode* top=NULL;
while(root || !StackEmpty(&st))
{
while(root)
{
StackPush(&st,root);
root=root->left;
}
top=StackTop(&st);
if(top->right==prev || top->right==NULL)
{
ans[idx++]=top->val;
StackPop(&st);
prev=top;
}
else
root=top->right;
}
StackDestroy(&st);
*returnSize=idx;
return ans;
}
层序遍历:
利用“数据结构——队列”来实现迭代层序遍历
// 层序遍历
// 非力扣接口
void BinaryTreeLevelOrder(BTNode* root)
{
// 借助队列保存节点
Queue q;
QueueInit(&q);
// 根节点入队
if (root)
QueuePush(&q, root);
// 遍历队列中的每一个节点
while (!QueueEmpty(&q))
{
// 获取队头元素
BTNode* node = QueueFront(&q);
// 出队
QueuePop(&q);
printf("%c ", node->_data);
// 保存队头元素的左右孩子节点
if (node->_left)
QueuePush(&q, node->_left);
if (node->_right)
QueuePush(&q, node->_right);
}
printf("\n");
}