二叉树的遍历(递归非递归、先序中序后序层次遍历)

//遍历
#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&&currentNode->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

大佬的讲解视频

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值