文章目录
【0】遍历法则
我们来简单了解一下二叉树的前中后序和层序的遍历法则
层序遍历
层序遍历是最简单的,顾名思义就是一层一层从左往右一个一个打印,不难理解。
前序遍历
例:
输出结果:ABDEGCF
中序遍历
例:
输出结果:DBGEACF
后序遍历
例:
输出结果:DGEBFCA
【1】非递归前序遍历
//非递归实现前序遍历需要通过辅助栈存父结点来完成所有的操作
//从根节点压栈,然后接下来进行一个大循环
//只要栈里边还有元素,就将栈顶元素输出并且出栈
//将栈顶元素的右孩子结点和左孩子结点依次压栈
//(因为出栈和入栈的顺序是相反的,所以先压右孩子,再压左孩子)
//直到栈空为止
void NonPre_Post()
{
cout << "非递归实现前序遍历:";
if (_root == nullptr)
{
return;
}
stack<BSTNode*>s;
s.push(_root);
while(!s.empty())
{
BSTNode*top = s.top();
s.pop();
cout << top->_data << " ";
if (top->_right != nullptr)
{
s.push(top->_right);
}
if (top->_left != nullptr)
{
s.push(top->_left);
}
}
cout << endl;
}
递归版本前序遍历
//递归实现树的前序遍历
//首先访问根节点,输出根节点的值,此后需要判断递归遍历的每个根节点是否存在
//然后再按照如上方法递归遍历根节点的左子树
//再递归遍历根节点的右子树
void Pre_out()
{
cout << "递归实现前序遍历:";
Pre_out(_root);
cout << endl;
}
void Pre_out(BSTNode *node)
{
if (node != nullptr)
{
cout << node->_data << " ";
Pre_out(node->_left);
Pre_out(node->_right);
}
}
【2】非递归中序遍历
需要一个辅助栈,从根节点开始,一直向左子树遍历
将结点压入栈,直到结点为空,然后打印该结点并且出栈该结点
这时将栈顶结点的右子树按照如上方法继续进行。
//非递归实现中序遍历
void NonMid_Post()
{
cout << "非递归实现中序遍历:";
if (_root == nullptr)
{
return;
}
stack<BSTNode*>s;
BSTNode*cur = _root;
while (!s.empty() || cur != nullptr)
{
if (cur != nullptr)
{
s.push(cur);
cur = cur->_left;
}
else
{
BSTNode*top = s.top();
s.pop();
cout << top->_data << " ";
cur = top->_right;
}
}
cout << endl;
}
递归版本中序遍历
//递归实现树的中序遍历
//从根结点开始,先访问结点的左孩子,再输出该结点的值,再访问结点的右孩子
//按照上述方式进行递归
void Mid_out()
{
cout << "递归实现中序遍历:";
Mid_out(_root);
cout << endl;
}
void Mid_out(BSTNode *node)
{
if (node != nullptr)
{
Mid_out(node->_left);
cout << node->_data << " ";
Mid_out(node->_right);
}
}
【3】非递归后序遍历
非递归的后序遍历需要两个栈进行辅助操作
用一个栈存放父结点,一个栈用于存放结果
注意压栈顺序,本来我们应该先压右孩子,再压左孩子。但是我们使用另一个结果栈 来存储结果集,辅助栈中的元素最终是出栈并压入结果栈的,因此,我们程序中 应该先压入左孩子,再压入右孩子。 然后每次循环将栈顶元素出栈并压入结果栈中。 最后,结果栈中所存储的就是我们所需的后序遍历结果集。最后打印出结果栈。
void NonLast_Post()
{
cout << "非递归实现后序遍历:";
if (_root == nullptr)
{
return;
}
stack<BSTNode*>sa;
stack<BSTNode*>sb;
sa.push(_root);
while (!sa.empty())
{
BSTNode* top = sa.top();
sa.pop();
sb.push(top);
if (top->_left != nullptr)
{
sa.push(top->_left);
}
if (top->_right != nullptr)
{
sa.push(top->_right);
}
}
while (!sb.empty())
{
cout << sb.top()->_data << " ";
sb.pop();
}
cout << endl;
}
递归版本后序遍历
//递归实现树的后序遍历
//从根节点开始,先遍历左孩子,再遍历右孩子
//再打印该结点的值
//按照上述方式一直递归
void Last_out()
{
cout << "递归实现后序遍历:";
Last_out(_root);
cout << endl;
}
void Last_out(BSTNode *node)
{
if (node != nullptr)
{
Last_out(node->_left);
Last_out(node->_right);
cout << node->_data << " ";
}
}
【4】非递归层序遍历
//非递归层序遍历需要借助一个队列进行操作
//原因是层序遍历是一个广度优先的遍历操作,需要从左至右,从上至下每一层逐个打印
//首先把根结点入队
//然后进行一个大循环,判断队列是否为空
//只要队列不为空,则说明上一层的元素还没有打印完
//将队头出队,打印队头元素,将队头的左孩子和右孩子依次从队尾入队
//直到队内空,则说明遍历完成。
void NonLeavlshow()
{
cout << "非递归实现层序遍历:";
if (_root == nullptr)
{
return;
}
queue<BSTNode*>myqueue;
myqueue.push(_root);
while (!myqueue.empty())
{
if (myqueue.front()->_left)
{
myqueue.push(myqueue.front()->_left);
}
if (myqueue.front()->_right)
{
myqueue.push(myqueue.front()->_right);
}
cout << myqueue.front()->_data << " ";
myqueue.pop();
}
cout << endl;
}
递归版本层序遍历
//递归实现层序遍历
//由于层序遍历是一种广度优先的遍历,所以我们需要通过层数控制整个函数的运行
//每轮循环传入要输出的层数
//然后当层数不等于0时,向下递归,每次递归层数减一
//当层数等于0的时候,则说明已经到达了要输出的那一层,递归的结束条件就满足了,直接输出值即可
void leavlOrder()
{
cout << "递归实现层序遍历:";
int l = leavl(_root);
for(int i = 0; i < l; ++i)
{
leavlOrder(_root, i);
}
cout << endl;
}
void leavlOrder(BSTNode *node, int l)
{
if (node != nullptr)
{
if(l==0)
{
cout << node->_data << " ";
return;
}
leavlOrder(node->_left, l - 1);
leavlOrder(node->_right, l - 1);
}
}
【5】测试代码
int main()
{
// 40
// 20 65
// 10 25 45 70
// 99
//建树
BSTree<int>bst;
bst.noninsert(40);
bst.noninsert(20);
bst.noninsert(65);
bst.noninsert(25);
bst.noninsert(45);
bst.noninsert(70);
bst.noninsert(10);
bst.noninsert(99);
//前序
bst.Pre_out();
bst.NonPre_Post();
cout << endl;
//中序
bst.Mid_out();
bst.NonMid_Post();
cout << endl;
//后序
bst.Last_out();
bst.NonLast_Post();
cout << endl;
//层序
bst.leavlOrder();
bst.NonLevelOrder();
cout << endl;
return 0;
}