递归非递归方式实现二叉树的遍历以及应用
二叉树的递归遍历很好理解,话不多说,上代码
一、二叉树递归遍历的实现
#include<iostream>
#include <stdlib.h>
#include<stack>
#include<string.h>
using namespace std;
typedef struct TreeNode{
TreeNode *right;
TreeNode *left;
char e;
}TreeNode,*PTree;
void CreatTree(PTree &T){
char a;
scanf("%c",&a);
if(a=='#'){//ABDG##H###CE#I##F##
T=NULL;
}
else{
T = (PTree)malloc(sizeof(TreeNode));
T->e=a;
CreatTree(T->left);
CreatTree(T->right);
}
}
void PreOrderTravel(PTree T){
if(T==NULL)
return;
printf("%c ",T->e);
PreOrderTravel(T->left);
PreOrderTravel(T->right);
}
void InOrderTravel(PTree T){
if(T==NULL)
return;
InOrderTravel(T->left);
printf("%c ",T->e);
InOrderTravel(T->right);
}
void TailOrderTravel(PTree T){
if(T==NULL)
return;
TailOrderTravel(T->left);
TailOrderTravel(T->right);
printf("%c ",T->e);
}
void Prestacktravel(PTree T){
stack<TreeNode *> s;
if(T!=NULL)
s.push(T);
printf("非递归前序 ");
while(!s.empty()){
PTree p=s.top();
s.pop();
printf("%c ",p->e);
if(p->right!=NULL) s.push(p->right);
if(p->left!=NULL) s.push(p->left);
}
}
void Instacktravel(PTree T){
stack<TreeNode *> s;
PTree p=T;
printf("非递归中序 ");
while(!s.empty()||p!=NULL){
if(p!=NULL){
s.push(p);
p=p->left;
}else{
p=s.top();
s.pop();
printf("%c ",p->e);
p=p->right;
}
}
}
void Tailstacktravel(PTree T){
stack<TreeNode *> s;
PTree p=T,q=NULL;
printf("非递归后序 ");
do{
while(p!=NULL){
s.push(p);
p=p->left;
}
q=NULL;
while(!s.empty()){
p=s.top();
s.pop();
if(p->right==q){
printf("%c ",p->e);
q=p;
}else{
s.push(p);
p=p->right;
break;
}
}
}while(!s.empty());
}
int main(){
PTree T=NULL;
T = (PTree)malloc(sizeof(TreeNode));//此处不论是否为T申请内存都不影响最终结果,
// 但是这点使我很疑惑,如果此处申请内存,在creaTree函数中继续申请内存,不是重复了吗?或者说是空置了一个
//答:地址传递
CreatTree(T);
printf("前序递归");
PreOrderTravel(T);
printf("\n");
printf("中序递归");
InOrderTravel(T);
printf("\n");
printf("后序递归");
TailOrderTravel(T);
printf("\n");
Prestacktravel(T);
printf("\n");
Instacktravel(T);
printf("\n");
Tailstacktravel(T);
}
在void InOrderTravel(PTree T)和T = (PTree)malloc(sizeof(TreeNode));中,T的类型都应该是PTree而非TreeNode,因为TreeNode是二叉树中每个结点,在参数传递时T表示的是当前根结点的指针。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 | #include <stdlib.h> #include<stack> #include<string.h> #include<iostream> using namespace std; typedef struct Node{ //ABDG##H###CE#I##F## Node* left; Node* right; char data; }Node,*PNode; void create(PNode &T){ char c; scanf ( "%c" ,&c); if (c== '#' ) T=NULL; else { T=(PNode) malloc ( sizeof (Node)); //不要忘了申请地址 T->data=c; create(T->left); create(T->right); } } void pre1(PNode &T){ if (T) cout<<T->data<< " " ; if (T->left!=NULL) pre1(T->left); if (T->right!=NULL) pre1(T->right); } void pre2(PNode &T){ if (T==NULL) return ; stack<PNode>s; PNode p=T; while (!s.empty()||p){ while (p){ cout<<p->data<< " " ; s.push(p); p=p->left; } if (!s.empty()){ p=s.top(); s.pop(); p=p->right; } } } void In1(PNode &T){ if (T==NULL) return ; if (T->left!=NULL) In1(T->left); cout<<T->data<< " " ; if (T->right!=NULL) In1(T->right); } void In2(PNode &T){ if (T==NULL) return ; PNode p=T; stack<PNode>s; while (p||!s.empty()){ while (p){ s.push(p); p=p->left; } if (!s.empty()){ p=s.top(); s.pop(); cout<<p->data<< " " ; p=p->right; } } } void Post1(PNode &T){ if (T==NULL) return ; if (T->left!=NULL) Post1(T->left); if (T->right!=NULL) Post1(T->right); cout<<T->data<< " " ; } void Post2(PNode &T){ stack<PNode>s; PNode p=T,r=NULL; while (p||!s.empty()){ if (p){ s.push(p); p=p->left; } else { p=s.top(); if (p->right&&p->right!=r){ p=p->right; s.push(p); p=p->left; } else { s.pop(); cout<<p->data<< " " ; r=p; p=NULL; } } } } void Post22(PNode &T){ if (T == NULL) return ; stack<PNode> s; //pCur:当前访问节点,pLastVisit:上次访问节点 PNode pCur, pLastVisit; pCur = T; pLastVisit = NULL; //先把pCur移动到左子树最下边 while (pCur) { s.push(pCur); pCur = pCur->left; } while (!s.empty()) { //走到这里,pCur都是空,并已经遍历到左子树底端(看成扩充二叉树,则空,亦是某棵树的左孩子) pCur = s.top(); s.pop(); //一个根节点被访问的前提是:无右子树或右子树已被访问过 if (pCur->right == NULL || pCur->right == pLastVisit) { cout <<pCur->data<< " " ; //修改最近被访问的节点 pLastVisit = pCur; } /*这里的else语句可换成带条件的else if: else if (pCur->lchild == pLastVisit)//若左子树刚被访问过,则需先进入右子树(根节点需再次入栈) 因为:上面的条件没通过就一定是下面的条件满足。仔细想想! */ else { //根节点再次入栈 s.push(pCur); //进入右子树,且可肯定右子树一定不为空 pCur = pCur->right; while (pCur) { s.push(pCur); pCur = pCur->left; } } } cout << endl; } int main(){ PNode T; // T=(PNode) malloc(sizeof(Node)); create(T); printf ( "递归前序遍历\n" ); pre1(T); cout<< "\n非递归前序遍历" <<endl; pre2(T); cout<< "\n递归中序遍历\n" ; In1(T); cout<< "\n非递归中序遍历\n" ; In2(T); cout<< "\n递归后序遍历\n" ; Post1(T); cout<< "\n非递归后序遍历\n" ; Post2(T); return 0; } ////https://blog.csdn.net/z_ryan/article/details/80854233 //#include<iostream> //#include <stdlib.h> //#include<stack> //#include<string.h> //using namespace std; //typedef struct TreeNode{ // TreeNode *left,*right; // char c; //}TreeNode,*pNode; //void create(pNode &T){ // char h; // scanf("%c",&h); // if(h=='#') // T=NULL; // else{ // T=(pNode)malloc (sizeof(TreeNode)); // T->c=h; // create(T->left); // create(T->right); // } //} //void pre1(pNode &T){ // // printf("%c ",T->c); // if(T->left!=NULL) pre1(T->left); // if(T->right!=NULL) pre1(T->right); //} //void pre2(pNode &T){ // stack<pNode>s; // printf("\n非递归前序"); // if(T!=NULL) // s.push(T); // while(!s.empty()){ // pNode p=s.top(); // s.pop(); // printf("%c ",p->c); // if(p->right!=NULL) s.push(p->right); // if(p->left!=NULL) s.push(p->left); // } // //} //void In1(pNode &T){ // // if(T->left!=NULL) In1(T->left); // printf("%c ",T->c); // if(T->right!=NULL) In1(T->right); //} //void In2(pNode &T){ // stack<pNode>s; // printf("\n非递归中序"); // pNode p=T; // while(p!=NULL||!s.empty()){ // if(p!=NULL){ // s.push(p); // p=p->left; // }else{ // p=s.top(); // s.pop(); // printf("%c ",p->c); // p=p->right; // } // } //} //void Tail1(pNode &T){ // if(T->left!=NULL) Tail1(T->left); // if(T->right!=NULL) Tail1(T->right); // printf("%c ",T->c); //} //int main(){ // TreeNode *T;//ABDG##H###CE#I##F## // T=(pNode)malloc(sizeof(TreeNode)); // create(T); // printf("递归前序"); // pre1(T); // pre2(T); // printf("\n递归中序"); // In1(T); // In2(T); // printf("\n递归后序"); // Tail1(T); // return 0; //} |
接下来是对二叉树进行应用
求指定根节点的二叉树的节点数和深度,分别用了递归和非递归
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 | int Size1(PNode T){ if (T==NULL) return 0; else return 1+Size1(T->left)+Size1(T->right); } int Size2(PNode T){ if (T==NULL) return 0; PNode p=T; int i=0; stack<PNode>s; while (p||!s.empty()){ while (p){ i++; s.push(p); p=p->left; } if (!s.empty()){ p=s.top(); s.pop(); p=p->right; } } return i; } int height2(PNode T){ if (T==NULL) return 0; PNode p=T; int i=0,max=0; stack<PNode>s; while (p||!s.empty()){ while (p){ i++; if (i>max) max=i; s.push(p); p=p->left; } if (!s.empty()){ p=s.top(); s.pop(); i--; //出栈一个意味着深度减一 p=p->right; } } return max; } int height1(PNode T){ if (T==NULL) return 0; else { int i=height1(T->left); int j=height1(T->right); return (i>j)?i+1:j+1; } } |
接下来是利用递归实现二叉树的前序中序转后序以及中序后序转前序
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 | //9 //G H D B I E F C A //G D H B A E I C F //A B D G H C E I F //G D H B A E I C F #include <stdlib.h> #include<stack> #include<string> #include<iostream> #include<algorithm> using namespace std; typedef struct Node{ Node *right,*left; char e; }Node,*PNode; const int maxn=30; char pre[maxn],in[maxn],post[maxn]; int n; PNode CreatePre( int postl, int postr, int inl, int inr){ if (postl>postr) return NULL; PNode root=(PNode) malloc ( sizeof (Node)); root->e=post[postr]; int k; for (k=inl;k<=inr;k++){ if (in[k]==post[postr]) break ; } int numLeft=k-inl; root->left=CreatePre(postl,postl+numLeft-1,inl,k-1); root->right=CreatePre(postl+numLeft,postr-1,k+1,inr); return root; } PNode CreatePost( int prel, int prer, int inl, int inr){ if (prel>prer) return NULL; PNode root=(PNode) malloc ( sizeof (Node)); root->e=pre[prel]; int k; for (k=inl;k<=inr;k++){ if (in[k]==pre[prel]) break ; } int numleft=k-inl; root->left=CreatePost(prel+1,prel+numleft,inl,inl+numleft-1); root->right=CreatePost(prel+1+numleft,prer,inl+numleft+1,inr); return root; } void pre1(PNode &T){ if (T) cout<<T->e<< " " ; if (T->left!=NULL) pre1(T->left); if (T->right!=NULL) pre1(T->right); } void Post1(PNode &T){ if (T==NULL) return ; if (T->left!=NULL) Post1(T->left); if (T->right!=NULL) Post1(T->right); cout<<T->e<< " " ; } int main(){ cout<< "输入个数" <<endl; scanf ( "%d" ,&n); cout<< "输入后序" <<endl; for ( int i=0;i<n;i++) cin>>post[i]; cout<< "输入中序" <<endl; for ( int i=0;i<n;i++) cin>>in[i]; PNode root=CreatePre(0,n-1,0,n-1); cout<< "构建后输出前序为" <<endl; pre1(root); cout<< "\n输入前序" <<endl; for ( int i=0;i<n;i++) cin>>pre[i]; cout<< "输入中序" <<endl; for ( int i=0;i<n;i++) cin>>in[i]; PNode T=CreatePost(0,n-1,0,n-1); cout<< "构建后输出后序为" <<endl; Post1(T); return 0; } |
【推荐】还在用 ECharts 开发大屏?试试这款永久免费的开源 BI 工具!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步