创建二叉搜索树,通过堆栈实现前序遍历、中序遍历和后续遍历
1. 需要掌握的知识
二叉搜索树、树的遍历、堆栈
2. 代码框架(重点)
2.1 采用的数据结构
结构体数组
typedef int ElementType; //通过typedef增加灵活性,树节点的元素类型若改变,修改typedef语句即可
typedef struct BinarySearchTree *PtrBST;
struct BinarySearchTree
{
ElementType data;
PtrBST LeftTree;
PtrBST RightTree;
};
2.2 各分支函数
- PreOrder()函数,通过堆栈实现树的前序遍历:根 左 右。
核心思路:
(1)无论是树的哪种遍历,其访问顺序都是一样的:从根节点出发,按箭头指引方向访问各节点,每个节点均要访问三次。对于先序,对应第一次访问时就打印,对应结点入栈
(2)通过堆栈模拟其访问顺序:先向左,边压栈边走,一直走到尽头,接下来,弹出栈顶元素并切换到其右子树,继续循环。这里比较抽象,建议多想一想
void PreOrder_Stack(PtrBST Tree)
{
stack<PtrBST> s; PtrBST T=Tree;
while(T || !s.empty())
{
while(T) //向左子树走,一直走到尽头
{
s.push(T);
cout<<T->data<<' ';
T=T->LeftTree;
}
if(!s.empty()) //弹出栈顶元素,并切换到右子树
{
T=s.top();
s.pop();
T=T->RightTree;
}
}
return;
}
- inOrder()函数,通过堆栈实现树的中序遍历:左 根 右
核心思路:对于中序,第二次访问时打印,对应弹出栈顶元素的时候。因此代码可以继承先序遍历,调整打印位置即可
void InOrder_Stack(PtrBST Tree)
{
stack<PtrBST> s; PtrBST T=Tree;
while(T || !s.empty())
{
while(T)
{
s.push(T);
T=T->LeftTree;
}
if(!s.empty())
{
T=s.top();
s.pop();
cout<<T->data<<' ';
T=T->RightTree;
}
}
return;
}
- PostOrder()函数,通过堆栈实现树的后序遍历:左 右 根
核心思路:
(1)后序对应第三次访问时打印
(2)后序遍历时,向左走到尽头,随后弹出栈顶元素,如果该节点没有右子树 或 右子树已访问,执行打印并将当前树赋值为空(避免再次切到右子树);否则,需要将该节点二次入栈并切换到其右子树,直到第二次弹出时再访问。代码有一定难度,需要结合实例仔细思考。
void PostOrder_Stack(PtrBST Tree)
{
stack<PtrBST> s; PtrBST LastVisited;
while(Tree || !s.empty())
{
while(Tree)
{
s.push(Tree);
LastVisited=Tree;
Tree=Tree->LeftTree;
}
Tree=s.top();
s.pop();
if(!Tree->RightTree || LastVisited==Tree->RightTree)
{
cout<<Tree->data<<' ';
LastVisited=Tree;
Tree=NULL;
}
else
{
s.push(Tree);
LastVisited=Tree;
Tree=Tree->RightTree;
}
}
return;
}
- 辅助函数 AddNode(),向树中添加结点
PtrBST AddNode(PtrBST Tree,ElementType value)
{
if(!Tree)
{
Tree=(PtrBST)malloc(sizeof(struct BinarySearchTree));
Tree->data=value;
Tree->LeftTree=NULL;
Tree->RightTree=NULL;
}
else
{
if(value < Tree->data)
Tree->LeftTree=AddNode(Tree->LeftTree,value);
else
Tree->RightTree=AddNode(Tree->RightTree,value);
}
return Tree;
}
- 辅助函数 CreateBST(),调用AddNode()完成二叉搜索树的建立
PtrBST CreateBST(PtrBST Tree,int NodeNumber)
{
ElementType value;
for(int i=0;i<NodeNumber;i++)
{
cin>>value;
Tree=AddNode(Tree,value);
}
return Tree;
}
3.完整编码
#include <stack>
#include <iostream>
#include <cstdlib>
using namespace std;
typedef int ElementType; //通过typedef增加灵活性,树节点的元素类型若改变,修改typedef语句即可
typedef struct BinarySearchTree *PtrBST;
struct BinarySearchTree
{
ElementType data;
PtrBST LeftTree;
PtrBST RightTree;
};
PtrBST AddNode(PtrBST Tree,ElementType value);
PtrBST CreateBST(PtrBST Tree,int NodeNumber);
void PreOrder(PtrBST Tree);
void PreOrder_Stack(PtrBST Tree);
void InOrder(PtrBST Tree);
void InOrder_Stack(PtrBST Tree);
void PostOrder(PtrBST Tree);
void PostOrder_Stack(PtrBST Tree);
int main()
{
int Nodes;
PtrBST BSTree=NULL;
cin>>Nodes;
BSTree=CreateBST(BSTree,Nodes);
//PreOrder(BSTree); cout<<endl;
//PreOrder_Stack(BSTree);
//InOrder(BSTree); cout<<endl;
//InOrder_Stack(BSTree);
PostOrder(BSTree); cout<<endl;
PostOrder_Stack(BSTree);
return 0;
}
void PostOrder_Stack(PtrBST Tree)
{
stack<PtrBST> s; PtrBST LastVisited;
while(Tree || !s.empty())
{
while(Tree)
{
s.push(Tree);
LastVisited=Tree;
Tree=Tree->LeftTree;
}
Tree=s.top();
s.pop();
if(!Tree->RightTree || LastVisited==Tree->RightTree)
{
cout<<Tree->data<<' ';
LastVisited=Tree;
Tree=NULL;
}
else
{
s.push(Tree);
LastVisited=Tree;
Tree=Tree->RightTree;
}
}
return;
}
void PostOrder(PtrBST Tree)
{
if(!Tree) return;
PostOrder(Tree->LeftTree);
PostOrder(Tree->RightTree);
cout<<Tree->data<<' ';
}
void InOrder_Stack(PtrBST Tree)
{
stack<PtrBST> s;
PtrBST T=Tree;
while(T || !s.empty())
{
while(T)
{
s.push(T);
T=T->LeftTree;
}
if(!s.empty())
{
T=s.top();
s.pop();
cout<<T->data<<' ';
T=T->RightTree;
}
}
return;
}
void InOrder(PtrBST Tree) //运用递归时一定要设定返回条件,否则会引起死循环
{
if(!Tree) return;
InOrder(Tree->LeftTree);
cout<<Tree->data<<' ';
InOrder(Tree->RightTree);
}
void PreOrder_Stack(PtrBST Tree)
{
stack<PtrBST> s; PtrBST T=Tree;
while(T || !s.empty())
{
while(T)
{
s.push(T);
cout<<T->data<<' ';
T=T->LeftTree;
}
if(!s.empty())
{
T=s.top();
s.pop();
T=T->RightTree;
}
}
return;
}
void PreOrder(PtrBST Tree)
{
if(!Tree) return;
cout<<Tree->data<<" ";
PreOrder(Tree->LeftTree);
PreOrder(Tree->RightTree);
}
PtrBST AddNode(PtrBST Tree,ElementType value)
{
if(!Tree)
{
//cout<<"Here is create the root!"<<endl;
Tree=(PtrBST)malloc(sizeof(struct BinarySearchTree));
Tree->data=value;
Tree->LeftTree=NULL;
Tree->RightTree=NULL;
}
else
{
//cout<<"Here is create the branch!"<<endl;
if(value < Tree->data)
Tree->LeftTree=AddNode(Tree->LeftTree,value);
else
Tree->RightTree=AddNode(Tree->RightTree,value);
}
return Tree;
}
PtrBST CreateBST(PtrBST Tree,int NodeNumber)
{
ElementType value;
for(int i=0;i<NodeNumber;i++)
{
cin>>value;
//cout<<"input value: "<<value<<endl;
Tree=AddNode(Tree,value);
}
return Tree;
}