二叉树遍历

二叉树的操作有前序递归遍历,前序非递归遍历,中序递归遍历,中序非递归遍历,后序递归遍历,后序非递归遍历,层序遍历,

递归打印叶子结点,非递归打印叶子结点。

 

若一棵树的结构如下,它的前序遍历是ABD##E#F##CG###

则对树的操作代码如下:

类BiTree, 则bitree.h的代码如下:

 

 1 #ifndef BITREE_H
 2 #define BITREE_H
 3 
 4 const int MaxSize = 100;
 5 
 6 template <class T>
 7 struct BiNode   //二叉树的结点结构
 8 {
 9   T data;
10   BiNode<T> *lchild, *rchild;
11 };
12 
13 template<class T>
14 struct element         //二叉树的结点结构,用于后序非递归遍历时
15 {
16     BiNode<T>* ptr;
17     int flag;
18 };
19 
20 template <class T>
21 class BiTree
22 {
23 public:
24     BiTree( );                             //构造函数,初始化一棵二叉树,其前序序列由键盘输入
25     ~BiTree(void);                        //析构函数,释放二叉链表中各结点的存储空间
26     BiNode<T>* Getroot();                //获得指向根结点的指针
27     void PreOrder(BiNode<T> *root);     //递归前序遍历二叉树
28     void NoPreOrder(BiNode<T>* root);   //非递归前序遍历二叉树
29     void InOrder(BiNode<T> *root);      //中序遍历二叉树
30     void NoInOrder(BiNode<T>* root);    //非递归中序遍历二叉树
31     void PostOrder(BiNode<T> *root);    //后序遍历二叉树
32     void NoPostOrder(BiNode<T>* root);  //非递归后序遍历二叉树
33     void LeverOrder(BiNode<T> *root);   //层序遍历二叉树
34     void CountLeaf(BiNode<T> *root);    //递归求二叉树的叶子结点个数
35     void NoCountLeaf(BiNode<T> *root);  //非递归求二叉树的叶子结点个数
36     int getCount();
37 private:
38     BiNode<T> *root;         //指向根结点的头指针
39     BiNode<T> *Creat( );     //有参构造函数调用
40     void Release(BiNode<T> *root);   //析构函数调用
41     int count;
42 };
43 
44 #endif // BITREE_H
View Code

 

对二叉树的操作,bitree.cpp

  1 #include<iostream>
  2 #include<string>
  3 #include"bitree.h"
  4 using namespace std;
  5 
  6 template<class T>
  7 BiTree<T>::BiTree( )
  8 {
  9     this->root = Creat( );
 10     count=0;
 11 }
 12 
 13 template<class T>
 14 BiTree<T>::~BiTree(void)
 15 {
 16     Release(root);
 17 }
 18 
 19 template<class T>
 20 BiNode<T>* BiTree<T>::Getroot( )
 21 {
 22     return root;
 23 }
 24 
 25 
 26 template<class T>
 27 void BiTree<T>::PreOrder(BiNode<T> *root)
 28 {
 29     if(root==NULL)  return;
 30     else{
 31         cout<<root->data<<" ";
 32         PreOrder(root->lchild);
 33         PreOrder(root->rchild);
 34     }
 35 }
 36 
 37 template<class T>
 38 void BiTree<T>::NoPreOrder(BiNode<T>*root)
 39 {
 40     BiNode<T> *s[MaxSize];
 41     int top=-1;
 42     while(root!=NULL||top!=-1)
 43     {
 44         while(root!=NULL)
 45         {
 46             cout<<root->data<<" ";
 47             s[++top]=root;
 48             root=root->lchild;
 49         }
 50         if(top!=-1)
 51         {
 52             root=s[top--];              //此处为s[top--],意思是当栈顶结点没有左子树时,返回得到栈顶结点
 53             root=root->rchild;         //判断此栈顶结点有没有右子树
 54         }
 55     }
 56 
 57 }
 58 
 59 template<class T>
 60 void BiTree<T>::NoInOrder(BiNode<T> *root)
 61 {
 62     int top=-1;
 63     BiNode<T> *s[MaxSize];
 64 
 65     while(root!=NULL||top!=-1)
 66     {
 67         while(root!=NULL)
 68         {
 69             s[++top]=root;
 70             root=root->lchild;
 71         }
 72 
 73         if(top!=-1)
 74         {
 75             root=s[top--];
 76             cout<<root->data<<" ";
 77             root=root->rchild;
 78         }
 79     }
 80 
 81 }
 82 
 83 template <class T>
 84 void BiTree<T>::InOrder (BiNode<T> *root)
 85 {
 86     if (root==NULL)  return;      //递归调用的结束条件
 87     else{
 88         InOrder(root->lchild);    //中序递归遍历root的左子树
 89         cout<<root->data<<" ";    //访问根结点的数据域
 90         InOrder(root->rchild);    //中序递归遍历root的右子树
 91     }
 92 }
 93 
 94 
 95 template <class T>
 96 void BiTree<T>::PostOrder(BiNode<T> *root)
 97 {
 98     if (root==NULL)   return;       //递归调用的结束条件
 99     else{
100         PostOrder(root->lchild);    //后序递归遍历root的左子树
101         PostOrder(root->rchild);    //后序递归遍历root的右子树
102         cout<<root->data<<" ";      //访问根结点的数据域
103     }
104 }
105 
106 
107 
108 //后序非递归遍历与前序和中序不同,在后序
109 //遍历中结点要两次入栈, 两次出栈,
110 
111 //第一次出栈:只遍历完左子树,尚未遍历右子
112 //树,则该结点不出栈,利用栈顶找到右子树
113 
114 //第二次出栈,遍历完右子树,将该结点出栈
115 //该结点可以访问
116 //
117 
118 template<class T>
119 void BiTree<T>::NoPostOrder(BiNode<T> *root)
120 {
121     int top=-1;
122     element<T> s[MaxSize];
123     while(root!=NULL||top!=-1)
124     {
125         while(root!=NULL)
126         {
127             top++;
128             s[top].ptr=root;
129             s[top].flag=1;
130             root=root->lchild;
131         }
132         while(top!=-1 &&s[top].flag==2)
133         {
134             root=s[top--].ptr;
135             cout<<root->data<<" ";
136             root=NULL;              /*若缺少这一句,导致死循环,即在top=-1时,此时的root却并不为空而是整棵树的根结点*/
137         }
138         if(top!=-1)
139         {
140             s[top].flag=2;
141             root=s[top].ptr->rchild;
142         }
143     }
144 }
145 
146 
147 template <class T>
148 void BiTree<T>::LeverOrder(BiNode<T> *root)
149 {
150     int front = 0;
151     int rear = 0;  //采用顺序队列,并假定不会发生上溢
152 
153     BiNode<T>* Q[MaxSize];
154     BiNode<T>* q;
155 
156     if (root==NULL) return;
157     else{
158         Q[rear++] = root;
159         while (front != rear)
160         {
161             q = Q[front++];
162             cout<<q->data<<" ";
163             if (q->lchild != NULL)    Q[rear++] = q->lchild;
164             if (q->rchild != NULL)    Q[rear++] = q->rchild;
165         }
166     }
167 }
168 
169 template<class T>
170 void BiTree<T>::NoCountLeaf(BiNode<T> *root)
171 {
172     int front, rear;
173     front = rear = 0;
174     BiNode<T> *Q[MaxSize];
175     BiNode<T> *q;
176     if(root == NULL) return;
177     else
178     {
179         Q[rear++] = root;
180         while(rear != front)
181         {
182             q = Q[front++];
183             if(q->lchild != NULL) Q[rear++] = q->lchild;
184             if(q->rchild != NULL) Q[rear++] = q->rchild;
185             if(!q->lchild && !q->rchild)
186             {
187                 cout << q->data << " ";
188             }
189         }
190     }
191 }
192 
193 template <class T>
194 BiNode<T>* BiTree<T>::Creat( )
195 {
196     BiNode<T>* root;
197     T ch;
198     cout<<"请输入创建一棵二叉树的结点数据"<<endl;
199     cin>>ch;
200     if (ch=="#") root = NULL;
201     else{
202         root = new BiNode<T>;       //生成一个结点
203         root->data=ch;
204         root->lchild = Creat( );    //递归建立左子树
205         root->rchild = Creat( );    //递归建立右子树
206     }
207     return root;
208 }
209 
210 
211 template<class T>
212 void BiTree<T>::Release(BiNode<T>* root)
213 {
214     if (root != NULL){
215         Release(root->lchild);   //释放左子树
216         Release(root->rchild);   //释放右子树
217         delete root;
218     }
219 }
220 
221 
222 /*递归求二叉树的叶子结点的个数,如果要非递归求二叉树的叶子结点,
223 //只需在前序、中序、后序的遍历中,加上一个判断语句,判断该结点的左右子树是否为空,若是则count++*/
224 template<class T>
225 void BiTree<T>::CountLeaf(BiNode<T> *root)
226 {
227     if(root!=NULL)
228     {
229         if(root->lchild==NULL&& root->rchild==NULL)
230         {
231             count++;
232             cout<<root->data<<" ";
233         }
234         CountLeaf(root->lchild);
235         CountLeaf(root->rchild);
236     }
237 }
238 
239 
240 //返回叶子结点的个数
241 template<class T>
242 int BiTree<T>::getCount()
243 {
244     return count;
245 }
View Code

对二叉树操作的测试,main.cpp

 1 //#include<iostream>
 2 //#include<string>
 3 #include"bitree.cpp"
 4 
 5 //using namespace std;
 6 
 7 int main()
 8 {
 9     BiTree<string> bt; //创建一棵树
10     BiNode<string>* root = bt.Getroot( );  //获取指向根结点的指针
11 
12     cout<<"------递归前序遍历------ "<<endl;
13     bt.PreOrder(root);
14     cout<<endl;
15 
16     cout<<"------非递归前序遍历------"<<endl;
17     bt.NoPreOrder(root);
18     cout<<endl;
19 
20     cout<<"------递归中序遍历------ "<<endl;
21     bt.InOrder(root);
22     cout<<endl;
23 
24     cout<<"------非递归中序遍历------ "<<endl;
25     bt.NoInOrder(root);
26     cout<<endl;
27 
28     cout<<"------递归后序遍历------ "<<endl;
29     bt.PostOrder(root);
30     cout<<endl;
31 
32     cout<<"------非递归后序遍历------ "<<endl;
33     bt.NoPostOrder(root);
34     cout<<endl;
35 
36     cout<<"------层序遍历------ "<<endl;
37     bt.LeverOrder(root);
38     cout<<endl;
39 
40     cout<<"----递归求二叉树的叶子结点----"<<endl;
41     bt.CountLeaf(root);
42     cout<<endl;
43 
44     cout<<"----非递归求二叉要的叶子结点--"<<endl;
45     bt.NoCountLeaf(root);
46     cout << endl;
47 
48     cout<<"-----叶子结点的个数是-------"<<endl;
49     cout<<bt.getCount();
50     cout<<endl;
51 
52     return 0;
53 }
54 
55 /*
56  * main.cpp中文件头所需要的头文件,如果是下面这样:
57  * #include<iostream>
58  * #include<string>
59  * #include<bitree.h>
60  * using namespace std;
61  * 这样会出错。因为BiTree<T>是一个模板,BiTree<string>是一个实例,从BiTree到BiTree<string>的过程是实例化的过程
62  * 按照传统编译方式时,编译器在bitree.h中看到了模板的声明,但没有看到模板的定义,故而会错。
63  *
64  *更改方式:
65  *1. 直接在main.cpp的文件头中包含 #include "bitree.cpp"即可
66  *
67  *2. 将bitree.h和bitree.cpp合并,将函数的实现写在bitree.h
68  *
69  *
70  *
71  *
72 */
View Code

 

 

posted @ 2013-11-04 12:54  关雎天下  阅读(586)  评论(0编辑  收藏  举报