递归非递归方式实现二叉树的遍历以及应用

二叉树的递归遍历很好理解,话不多说,上代码

一、二叉树递归遍历的实现

复制代码

#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;
}

  

 

 https://blog.csdn.net/z_ryan/article/details/80854233很经典

posted on   妄想症T  阅读(1759)  评论(0编辑  收藏  举报

导航

< 2025年3月 >
23 24 25 26 27 28 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 1 2 3 4 5
点击右上角即可分享
微信分享提示