二叉树

一、定义一个二叉树节点。

 

一个二叉数节点包含数据域、指向二叉树左右孩子的指针。

1 typedef struct BiTNode
2 {
3     ElemType data;//结点数据
4     struct BiTNode *lchild, *rchild;//指向左右孩子的指针
5 }BiTNode, *BiTree;

 

二、二叉树的遍历。

递归遍历实现。

1、先序遍历。

先序遍历二叉树的操作定义如下:

若二叉树为空,则空操作;否则

(1)访问根节点。

(2)先序遍历左子树。

(3)先序遍历右子树。

 1 //前序遍历二叉树(递归)
 2 void preOrderTraverse(BiTree T, int level)
 3 {
 4     if(T)//二叉树非空
 5     {
 6         visit(T->data, level+1);//访问根节点
 7         preOrderTraverse(T->lchild, level+1);//先序遍历左指数
 8         preOrderTraverse(T->rchild, level+1);//先序遍历右指数
 9     }
10 }

2、中序遍历。

中序遍历二叉树的操作定义如下:

若二叉树为空,则空操作;否则

(1)中序遍历左子树。

(2)访问根节点。

(3)中序遍历右子树。

 1 //中序遍历二叉树(递归)
 2 void InOrderTraverse(BiTree T, int level)
 3 {
 4     if(T)//二叉树非空
 5     {
 6         
 7         InOrderTraverse(T->lchild, level+1);//中序遍历左指数
 8         visit(T->data, level+1);//访问根节点
 9         InOrderTraverse(T->rchild, level+1);//中序遍历右指数
10     }
11 }

3、后序遍历。

若二叉树为空,则空操作;否则

(1)后序遍历左子树。

(2)后序遍历右子树。

(3)访问根节点。

 1 //后序遍历二叉树(递归)
 2 void PostOrderTraverse(BiTree T, int level)
 3 {
 4     if(T)//二叉树非空
 5     {
 6         
 7         PostOrderTraverse(T->lchild, level+1);//后序遍历左指数
 8         PostOrderTraverse(T->rchild, level+1);//后序遍历右指数
 9         visit(T->data, level+1);//访问根节点
10     }
11     
12 }

非递归遍历实现。

层次遍历二叉树。

层次遍历二叉树要用到队列来实现,我这里用c++中的STL中的queue容器来实现。(记得头文件#include<queue>)

 1 //层次遍历二叉树
 2 void LevelOrderTraverse(BiTree T)
 3 {
 4     queue<BiTree > s;//定义一个队列
 5     BiTree p;//节点指针
 6     BiTree q;
 7     
 8     p = T;
 9     if(p == NULL)//树空返回函数结束
10     {
11         printf("tree is empty!!");
12         return ;
13     }
14     
15     s.push(p);//将根节点入队
16     while(!s.empty())
17     {
18         p = s.front();//出队
19         s.pop();
20         
21         if(NULL != p->lchild)//如果左节点不为空  左节点入队
22         {
23             q = p->lchild;
24             s.push(q);
25             
26         }
27         if(NULL != p->rchild)//如果右节点不为空  右节点入队
28         {
29             q = p->rchild;
30             s.push(q);
31             
32         }
33         cout<<p->data<<ends;
34         
35     }
36     
37     
38 }

前序遍历。

前序遍历二叉树要用到栈来实现,我这里用c++中的STL中的stack容器来实现。(记得头文件#include<stack>)

【算法步骤】

(1)初始化一个空栈S,指针p指向根节点。

(2)当p非空或者栈S非空,循环执行以操作:

      ●如果p非空,输出(根)节点,将p进栈,p指向该节点的左孩子。

   ●如果p为空,这弹出栈顶元素,将p指向该结点的右孩子。

 

 1 void preOrderTraverse(BiTree T)     //非递归前序遍历  
 2 {
 3     stack<BiTree> s;  //申请一个存储二叉树指针的栈
 4     BiTree p=T;      //指向二叉树的指针 指向树的根节点
 5     while(p!=NULL||!s.empty())//当指针不为空 或者栈不为空 
 6     {
 7         while(p!=NULL)//指针不为空循环  指针指向最左端的一个节点
 8         {
 9             cout<<p->data<<" ";//输出根节点
10             s.push(p);//节点存入栈中
11             p=p->lchild;//p指向左孩子
12         }
13         if(!s.empty())//当栈不为空
14         {
15             p=s.top();//栈顶元素赋值给p
16             s.pop();//弹栈
17             p=p->rchild;//p指向右孩子
18         }
19     }
20 }

中序遍历。

非递归中序遍历二叉树也要用到栈来实现,我这里用c++中的STL中的stack容器来实现。

【算法步骤】

(1)初始化一个空栈S,指针p指向根节点。

(2)当p非空或者栈S非空,循环执行以操作:

      ●如果p非空,则将p进栈,p指向该节点的左孩子。

    ●如果p为空,这弹出栈顶元素并访问,将p指向该结点的右孩子。

 1 void InOrderTraverse(BiTree T)      //非递归中序遍历 
 2 {
 3     stack<BiTree> s;
 4     BiTree p = T;
 5     while(p!=NULL||!s.empty())
 6     {
 7         while(p!=NULL)
 8         {
 9             s.push(p);
10             p=p->lchild;
11         }
12         if(!s.empty())
13         {
14             p=s.top();
15             cout<<p->data<<" ";
16             s.pop();
17             p=p->rchild;
18         }
19     }    
20 } 

总代码:

  1 #include<iostream>
  2 #include<stack>//栈的头文件
  3 #include<queue>//队列的头文件
  4 typedef  char ElemType;
  5 using namespace std;
  6 
  7 //二叉树节点的定义
  8 typedef struct BiTNode
  9 {
 10     ElemType data;//结点数据
 11     struct BiTNode *lchild, *rchild;//指向左右孩子的指针
 12 }BiTNode, *BiTree;
 13 
 14 
 15 //创建一颗二叉树,y约定用户遵照前序遍历的方式输入数据
 16 void CreatBiTree(BiTree &T)
 17 {
 18     char c;
 19     cin>>c;
 20     if( '#' == c )
 21     {
 22         T = NULL;
 23     }
 24     else
 25     {
 26         T = new BiTNode;
 27         T->data = c;
 28         CreatBiTree(T->lchild);//创建一个左指数
 29         CreatBiTree(T->rchild);//创建一个右指数
 30     }
 31 }
 32 
 33 
 34 //访问二叉树的具体节点的具体操作
 35 void visit(char c,int level)
 36 {
 37     printf("%c 位于第 %d 层\n" ,c,level);
 38 }
 39 
 40 
 41 
 42 //前序遍历二叉树(递归)
 43 void preOrderTraverse(BiTree T, int level)
 44 {
 45     if(T)//二叉树非空
 46     {
 47         visit(T->data, level+1);//访问根节点
 48         preOrderTraverse(T->lchild, level+1);//先序遍历左指数
 49         preOrderTraverse(T->rchild, level+1);//先序遍历右指数
 50     }
 51 }
 52 
 53 //中序遍历二叉树(递归)
 54 void InOrderTraverse(BiTree T, int level)
 55 {
 56     if(T)//二叉树非空
 57     {
 58         
 59         InOrderTraverse(T->lchild, level+1);//中序遍历左指数
 60         visit(T->data, level+1);//访问根节点(我这里写了一个输出函数也可以直接输出)
 61         InOrderTraverse(T->rchild, level+1);//中序遍历右指数
 62     }
 63 }
 64 
 65 //后序遍历二叉树(递归)
 66 void PostOrderTraverse(BiTree T, int level)
 67 {
 68     if(T)//二叉树非空
 69     {
 70         
 71         PostOrderTraverse(T->lchild, level+1);//后序遍历左指数
 72         PostOrderTraverse(T->rchild, level+1);//后序遍历右指数
 73         visit(T->data, level+1);//访问根节点
 74     }
 75     
 76 }
 77 
 78 //层次遍历二叉树
 79 void LevelOrderTraverse(BiTree T)
 80 {
 81     queue<BiTree > s;//定义一个队列
 82     BiTree p;//节点指针
 83     BiTree q;
 84     
 85     p = T;
 86     if(p == NULL)//树空返回函数结束
 87     {
 88         printf("tree is empty!!");
 89         return ;
 90     }
 91     
 92     s.push(p);//将根节点入队
 93     while(!s.empty())
 94     {
 95         p = s.front();//出队
 96         s.pop();
 97         
 98         if(NULL != p->lchild)//如果左节点不为空  左节点入队
 99         {
100             q = p->lchild;
101             s.push(q);
102             
103         }
104         if(NULL != p->rchild)//如果右节点不为空  右节点入队
105         {
106             q = p->rchild;
107             s.push(q);
108             
109         }
110         cout<<p->data<<ends;
111         
112     }
113     
114     
115 }
116 
117 void preOrderTraverse(BiTree T)     //非递归前序遍历  
118 {
119     stack<BiTree> s;  //申请一个存储二叉树指针的栈
120     BiTree p=T;      //指向二叉树的指针 指向树的根节点
121     while(p!=NULL||!s.empty())//当指针不为空 或者栈不为空 
122     {
123         while(p!=NULL)//指针不为空循环  指针指向最左端的一个节点
124         {
125             cout<<p->data<<" ";//输出根节点
126             s.push(p);//节点存入栈中
127             p=p->lchild;//p指向左孩子
128         }
129         if(!s.empty())//当栈不为空
130         {
131             p=s.top();//栈顶元素赋值给p
132             s.pop();//弹栈
133             p=p->rchild;//p指向右孩子
134         }
135     }
136 }
137 
138 void InOrderTraverse(BiTree T)      //非递归中序遍历 
139 {
140     stack<BiTree> s;
141     BiTree p = T;
142     while(p!=NULL||!s.empty())
143     {
144         while(p!=NULL)
145         {
146             s.push(p);
147             p=p->lchild;
148         }
149         if(!s.empty())
150         {
151             p=s.top();
152             cout<<p->data<<" ";
153             s.pop();
154             p=p->rchild;
155         }
156     }    
157 }
158 
159 
160 
161 
162 void main()
163 {
164 
165     //ABDH##I##E#J##CF#K##G###//
166     BiTree tree;//创建一个二叉树指针
167     cout<<"请输入建立二叉链表的序列:\n";
168     CreatBiTree(tree);
169 
170     cout<<endl<<"前序遍历的结果为(递归):\n";
171     preOrderTraverse(tree,1);
172     cout<<"前序遍历的结果为(非递归):\n";
173     preOrderTraverse(tree);
174 
175     cout<<"中序遍历的结果为(递归):\n";
176     InOrderTraverse(tree,1);
177     cout<<"中序遍历的结果为(非递归):\n";
178     InOrderTraverse(tree);
179 
180         
181     cout<<endl<<"后序遍历的结果为(递归):\n";
182     PostOrderTraverse(tree,1);
183     
184     cout<<endl<<"层次遍历的结果为:\n";
185     LevelOrderTraverse(tree);
186 
187     
188 
189     
190     cout<<endl;
191 }

注:在递归遍历中我写了一个输出函数(visit),你可以不用写直接输出结点(记得把递归遍历中的第二个参数level删除)。

【效果如下】

 

posted @ 2018-06-03 13:16  底层码农  阅读(1166)  评论(1编辑  收藏  举报