//遍历
#include<bits/stdc++.h>
using namespace std;
typedef struct treeNode{
int data;
treeNode *left,*right;
}treeNode;
// 由数组生成二叉树
treeNode *createTreeFromArray(int[], int);
// 创建节点
treeNode *createTreeNode(int);
treeNode* createTreeNode(int data)
{
treeNode* node = (treeNode*)malloc(sizeof(treeNode));
node->data = data;
node->left = NULL;
node->right = NULL;
return node;
}
/**
* @brief 由数组生成二叉树
*
* @param arr 二叉树的数组表示, 第一个元素为根节点, 负数表示节点不存在
* @param len 数组长度
* @return treeNode* 根节点的指针
*/
treeNode* createTreeFromArray(int arr[], int len)
{
// 数组为空
if (len < 1) return NULL;
// 用指针数组保存每个节点的地址,初始化NULL
treeNode** nodesArr = (treeNode**)malloc(sizeof(treeNode*) * len);
memset(nodesArr, 0, sizeof(treeNode*) * len);
// 分配根节点
nodesArr[0] = createTreeNode(arr[0]);
// 扫描数组创建整棵二叉树
for (int i = 0; i < len; i++)
{
int leftIdx = 2 * i + 1; // 当前节点的左孩子下标
int rightIdx = 2 * i + 2; // 当前节点的右孩子下标
if (leftIdx < len && arr[leftIdx] >= 0)
{
nodesArr[leftIdx] = createTreeNode(arr[leftIdx]); // 创建左孩子,并存入数据
nodesArr[i]->left = nodesArr[leftIdx]; // 设置节点i的左孩子
}
if (rightIdx < len && arr[rightIdx] >= 0)
{
nodesArr[rightIdx] = createTreeNode(arr[rightIdx]); // 创建右孩子,并存入数据
nodesArr[i]->right = nodesArr[rightIdx]; //设置节点i的右孩子
}
}
// 返回根节点
return nodesArr[0];
}
//先序遍历-递归
void preOrderRecursive(treeNode *root)
{
if (NULL == root) return; // root不为NULL才继续访问
printf("%d ", root->data); // 对数据进行访问
preOrderRecursive(root->left); // 访问左子树
preOrderRecursive(root->right); // 访问右子树
}
//中序遍历-递归
void inOrderRecursive(treeNode *root)
{
if (NULL == root) return; // root不为NULL才继续访问
inOrderRecursive(root->left); // 访问左子树
printf("%d ", root->data); // 对数据进行访问
inOrderRecursive(root->right); // 访问右子树
}
//后序遍历-递归
void postOrderRecursive(treeNode *root)
{
if (NULL == root) return; // root不为NULL才继续访问
postOrderRecursive(root->left); // 访问左子树
postOrderRecursive(root->right); // 访问右子树
printf("%d ", root->data); // 对数据进行访问
}
//先序遍历-非递归
void preOrder(treeNode *root)
{
if(NULL==root) return;
stack<treeNode*> nodeStack;
nodeStack.push(root); //根节点入栈
while(!nodeStack.empty()) //栈非空时迭代处理
{
treeNode *node=nodeStack.top(); //保存栈顶结点
printf("%d ",node->data); //访问节点数据
nodeStack.pop(); //栈顶结点出栈
//子节点入栈
if(node->right) nodeStack.push(node->right);
if(node->left) nodeStack.push(node->left);
}
}
//中序遍历-非递归
void inOrder(treeNode *root)
{
if(NULL==root) return;//空树
stack<treeNode*> nodeStack; //创建一个栈保存
treeNode *currentNode=root; //维护一个当前结点指针
//当前结点非空,或栈非空时迭代处理
while(currentNode||!nodeStack.empty())
{
//当前结点非空,沿着左子树方向入栈
while(currentNode)
{
nodeStack.push(currentNode);
currentNode=currentNode->left;
}
//当前栈顶结点没有左子树,或已经访问完左子树
currentNode=nodeStack.top(); //读取栈顶结点
printf("%d ",currentNode->data); //访问结点数据
nodeStack.pop(); //出栈
currentNode=currentNode->right;//讲当前结点设为右子节点
}
}
//后序遍历-非递归
void postOrder(treeNode *root)
{
if(NULL==root) return;
stack<treeNode*> nodeStack;//创建一个栈保存结点
treeNode *currentNode=root;//维护一个当前结点指针
treeNode *visitedNode=root;//保存上次访问的结点,初始化为root是利用二叉树是无环图
//当前节点非空,或栈非空时迭代处理
while(currentNode||!nodeStack.empty())
{
//当前节点非空,沿着左子树方向入栈
while(currentNode)
{
nodeStack.push(currentNode);
currentNode=currentNode->left;
}
currentNode=nodeStack.top();//取栈顶元素
//如果栈顶元素有右子树,且未被访问
if(currentNode->right&¤tNode->right!=visitedNode)
{
currentNode=currentNode->right;
}
else//子树为空或被访问过
{
printf("%d ",currentNode->data); //访问节点数据
visitedNode=currentNode; //记录当前访问的节点
currentNode=NULL; //当前节点置为NULL,防止重复访问左子树
nodeStack.pop(); //出栈
}
}
}
//层次遍历
void level(treeNode *root)
{
if(NULL==root) return;//空树
queue<treeNode*> nodeQueue;//创建一个队列保存节点
nodeQueue.push(root); //将根节点入队
//队非空时进行访问
while(!nodeQueue.empty())
{
treeNode *node=nodeQueue.front(); //取头结点
printf("%d ",node->data); //访问节点数据
if(node->left) nodeQueue.push(node->left);//左子节点入队
if(node->right) nodeQueue.push(node->right);//右节点入队
nodeQueue.pop();//头结点出队
}
}
// 测试函数是否工作正常
void test()
{
// 由数组创建二叉树, -1表示节点不存在
int arr[] = {1, 2, 3, -1, 4, 5, 6, -1, -1, 7};
// int arr[] = {1, 2, 3, 4, 5, 6, 7};
int len = sizeof(arr) / sizeof(arr [0]);
treeNode *root = createTreeFromArray(arr, len);
// 测试4种遍历方法
printf("先序:");
preOrder(root);
putchar('\n');
printf("中序:");
inOrder(root);
putchar('\n');
printf("后序:");
postOrder(root);
putchar('\n');
printf("层次:");
level(root);
putchar('\n');
}
int main(int argc, char const *argv[])
{
test();
return 0;
}
二叉树遍历-后序(非递归)【图解+代码】_哔哩哔哩_bilibili
大佬的讲解视频