二叉搜索树后序遍历序列
这是一种递归的算法思想,后续再优化
持续更新。。
#include<iostream>
using namespace std;
struct BiTree{
int NodeData = 0;
struct BiTree *pLeft = nullptr;
struct BiTree *pRight = nullptr;
};
//二叉搜索树是指所有左子树的节点值均小于根节点值
//所有右子树的节点值均大于根节点值
//现在已知二叉搜索树后序遍历序列[2,4,3,6,8,7,5]
//根据后序遍历规则,最后一个数即是根节点,假设位置是r
//再根据搜索二叉树的规律,找出左边区间[0,r-1]小于根节点的区间
//这个区间就是左子树,再对左子树递归上述
//同理,比根节点大的值就是右子树的区间,对右子树递归
BiTree* process(BiTree* root, int postArry[], int left, int right){
if(left>right){
return nullptr;
}
root = new BiTree;
root->NodeData = postArry[right];
if(left==right){//当序列只有一个数
return root;
}
//注意体会此处m的初始值
//是为了当存在极端情况,比如只有左子树或只有右子树
//那么序列里就全是小于根节点的数或者是全部大于根节点的数
//在这种情况下考虑m的值
int m=left-1;
for(int i=left; i<right; i++){
if(postArry[i]<postArry[right]){
m=i;
}
}
root->pLeft = process(root->pLeft, postArry, left, m);
root->pRight = process(root->pRight, postArry, m+1, right-1);
return root;
}
int main(){
int arry[] = {2,4,3,6,8,7,5};
int len = sizeof(arry)/sizeof(arry[0]);
BiTree* re = nullptr;
re = process(re, arry, 0, len-1);
cout<<re->NodeData;
return 0;
}
非递归遍历二叉树
#include<iostream>
#include<vector>
#include<stack>
using namespace std;
struct BiTree{
int NodeData = 0;
struct BiTree *pLeft = nullptr;
struct BiTree *pRight = nullptr;
};
//二叉搜索树是指所有左子树的节点值均小于根节点值
//所有右子树的节点值均大于根节点值
//现在已知二叉搜索树后序遍历序列[2,4,3,6,8,7,5]
//根据后序遍历规则,最后一个数即是根节点,假设位置是r
//再根据搜索二叉树的规律,找出左边区间[0,r-1]小于根节点的区间
//这个区间就是左子树,再对左子树递归上述
//同理,比根节点大的值就是右子树的区间,对右子树递归
BiTree* process(BiTree* root, int postArry[], int left, int right){
if(left>right){
return nullptr;
}
root = new BiTree;
root->NodeData = postArry[right];
if(left==right){//当序列只有一个数
return root;
}
//注意体会此处m的初始值
//是为了当存在极端情况,比如只有左子树或只有右子树
//那么序列里就全是小于根节点的数或者是全部大于根节点的数
//在这种情况下考虑m的值
int m=left-1;
for(int i=left; i<right; i++){
if(postArry[i]<postArry[right]){
m=i;
}
}
root->pLeft = process(root->pLeft, postArry, left, m);
root->pRight = process(root->pRight, postArry, m+1, right-1);
return root;
}
//对重建出来的二叉树前序中序后序遍历(递归)
//前序,中序,后序递归模式一样,此处只做前序示例
void preorder(BiTree* root, vector<int>&re){
if(root){
re.push_back(root->NodeData);
cout<<root->NodeData<<" ";
if(root->pLeft){
preorder(root->pLeft, re);
}
if(root->pRight){
preorder(root->pRight, re);
}
}
}
vector<int> show1(BiTree* root){
vector<int>re;
preorder(root,re);
return re;
}
//非递归前序遍历
void preorder2(BiTree* root){
stack<BiTree*>s;
BiTree *p=root;
while(p!=nullptr||!s.empty()){
while(p!=nullptr){
cout<<p->NodeData<<" ";
s.push(p);
p=p->pLeft;
}
p=s.top();
s.pop();
p=p->pRight;
}
}
//非递归中序遍历
void inorder(BiTree* root){
stack<BiTree*>s;//存放着二叉树节点的栈
BiTree *p=root;
while(p!=nullptr||!s.empty()){
while(p!=nullptr){
s.push(p);
p=p->pLeft;
}
p=s.top();
cout<<p->NodeData<<" ";
s.pop();
p=p->pRight;
}
}
//非递归后序遍历
//保证根节点在左孩子和右孩子之后访问,因此对于任一结点P,先将其入栈
//如果P不存在左孩子和右孩子,则可以直接访问它;
//或者P存在左孩子或者右孩子,但左孩子和右孩子都已访问,则同样可以直接访问该结点
//若非上述两种情况,则将P的右孩子和左孩子依次入栈
void postorder(BiTree* root){
stack<BiTree*>s;
BiTree *pre=nullptr;//记录前一次访问的节点
BiTree *cur;//当前节点
s.push(root);//先将根节点入栈
while(!s.empty()){
cur=s.top();
if(cur->pLeft==nullptr&cur->pRight==nullptr||
(pre!=nullptr&&(pre==cur->pLeft||pre==cur->pRight))){
cout<<cur->NodeData<<" ";
s.pop();
pre=cur;//更新记录
}
else{
//先让右子树节点入栈再左子树节点入栈
//保证最后是左子树节点先被访问
if(cur->pRight!=nullptr){
s.push(cur->pRight);
}
if(cur->pLeft!=nullptr){
s.push(cur->pLeft);
}
}
}
}
int main(){
int arry[] = {2,4,3,6,8,7,5};
int len = sizeof(arry)/sizeof(arry[0]);
BiTree* re = nullptr;
re = process(re, arry, 0, len-1);
//cout<<re->pLeft<<endl;
cout<<"递归前序遍历:";
show1(re);//前序遍历调用
cout<<endl<<"非递归中序遍历:";
inorder(re);
cout<<endl<<"非递归前序遍历:";
preorder2(re);
cout<<endl<<"非递归后序遍历:";
postorder(re);
return 0;
}