二叉树遍历操作

先序遍历:

void PreOrder(Node* t)
{
    if(t)//不为空
    {
        cout<<t->m_value<<" ";
        PreOrder(t->m_left);
        PreOrder(t->m_right);
    }
}

中序遍历:

void InOrder(Node* t)
{
    if(t)
    {
        InOrder(r->m_left);
        cout<<t->m-value<<" ";
        InOrder(r->m_right);
    }
}

后序遍历:

void PostOrder(Node* t)
{
    if(t)
    {
        PostOrder(t->m_left);
        PosrOrder(t->m_right);
        cout<<t->m_value<<" ";
    }
}

非递归层序遍历:

需要用队列,因为队列先进先出,按从上到下、从左到右的顺序入队列也就可以按此顺序出队列。

1、先入整棵树的第一个结点也就是根,队列不为空就用一个临时结点先保存队首元素,然后出队列,同时输出相应的值;

2、之后判断临时结点(也就是刚刚出队的结点)的左右结点,不为空就按左右顺序入队;

3、重复1,2直至队列为空。

注意:如果用栈,如果栈顶元素出栈时按左右顺序入栈,出栈时就不符合从左到右的层序遍历;如果按右左顺序入栈,下一次出栈时虽然左结点先出来了,但是此时要入该结点的左右结点,所以和该结点同层的右结点就会被压在下面,所以说不能用栈。

void LevelOrder(Node* t)
	{
		queue<Node*> qu;
		Node* front = NULL;
		if (t)
		{
			qu.push(t);
			while(!qu.empty())
			{
				front = qu.front();
				qu.pop();
				cout << front->m_value << " ";
				if (front->m_left != NULL)
				{
					qu.push(front->m_left);
				}
				if (front->m_right != NULL)
				{
					qu.push(front->m_right);
				}	
			}
		}
	}

非递归先序遍历:

需要使用栈,由于栈是先进后出,而先序遍历要求根左右,所以先入根结点,再出根结点,同时按右左顺序压入孩子结点。

1、先入整棵树的第一个结点也就是根,栈不为空就用一个临时结点先保存栈顶元素,然后出栈,同时输出相应的值;

2、之后判断临时结点(也就是刚刚出队的结点)的左右结点,不为空就按右左顺序入栈;

3、重复1,2直至栈为空。

注意:如果用队列,A出队后入BE,那么最终出队的顺序和层序一样;如果入B不入E,出B后入CD,但是最后找不到E;所以说不能用队列。  

void PreOrder_1(Node* t)
	{
		stack<Node*> st;
		if (t)
		{
			st.push(t);
			while (!st.empty())
			{
				Node* pre=st.top();
				st.pop();
				cout << pre->m_value << " ";
				if (pre->m_right != NULL)
				{
					st.push(pre->m_right);
				}
				if (pre->m_left != NULL)
				{
					st.push(pre->m_left);
				}
			}

		}
	}

非递归中序遍历:

需要用栈。

1、先将根结点及以下的所有左子树入栈;

2、判断栈是否为空,如果不为空获得栈顶出栈,同时用临时结点p 记住当前结点的右孩子并且入栈,如果没有就往上回归;

3、查看当前p是否有左子树,如果有,则继续执行1,2,3步骤,直到p为空或者栈为空为止。

注意:如果是一个根结点然后只有右孩子的单边情况,那么就是一直在做出栈保存右结点,入右结点,再出栈保存右结点,入右结点......

void InOrder_1(Node* t)
	{
		if (t != NULL)
		{
			stack<Node*> ss;
			Node* p = t;
			Node* top = NULL;
			while (p || !ss.empty())//如果仅仅只是栈非空,那么没有遍历右子树
			{
				while (p != NULL)
				{
					ss.push(p);
					p = p->m_left;
				}
				if (!ss.empty())
				{
					top = ss.top();
					ss.pop();
					cout << top->m_value << " ";
					p = top->m_right; //当前结点遍历完,记住右子树
				}
			}
		}
	}

 

非递归后续遍历:

需要用栈。

1、先将当前结点入栈,如果有左右孩子就一直按右左顺序入栈;

2、出栈分两种情况:

2.1、如果当前结点没有左右孩子直接出栈;

2.2、如果当前结点有左右孩子但是已经出栈,则出栈。

所以需要一个结点pre 来保存刚刚出栈的结点,然后在出下一个结点时比较pre 是否是自己的孩子结点,是才能出栈。

void PostOrder_1(Node* t)
	{
		if (t != NULL)
		{
			stack<Node*> ss;
			Node* top = NULL, * pre = NULL;
			ss.push(t);
			while (!ss.empty())
			{
				top = ss.top();
				if (top->m_left == NULL && top->m_right == NULL ||
					pre != NULL && top->m_left == pre || pre != NULL && top->m_right == pre)
				{
					ss.pop();
					cout << top->m_value << " ";
					pre = top;
				}
				else
				{
					if (top->m_right != NULL)
						ss.push(top->m_right);
					if (top->m_left != NULL)
						ss.push(top->m_left);
				}
			}
		}
	}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值