数据结构——二叉树
2017-09-19 23:15
316 查看
二叉树是数据结构的一个重要内容之一,那么对于我们这些学习编程的人来说,掌握二叉树的各种遍历(递归遍历和非递归遍历)是必不可少的,下面我们就分析一下,二叉树的各种遍历方法:
1首先得建立一个二叉树:
1.二叉树节点struct BinaryTreeNode//二叉树节点 { BinaryTreeNode* _left; BinaryTreeNode* _right; T _data; BinaryTreeNode(const T data) :_left(NULL)//二叉树左孩子 ,_right(NULL)//右孩子 ,_data(data) { } };
2.造二叉树
BinaryTree(const T* a, size_t size, const T& invalid)//二叉树构造函数 :_root(NULL) { size_t index=0; _root=CreatBinaryTree(a,size,index,invalid); }
Node* CreatBinaryTree(const T* a,size_t size,size_t& index,const T& invalid)//制造二叉树(前序) { Node* root=NULL; if(a[index]!=invalid&&index<size) { root=new Node(a[index]);//new一个根节点,先造根节点 root->_left=CreatBinaryTree(a,size,++index,invalid);//再造左节点 root->_right=CreatBinaryTree(a,size,++index,invalid);//再造右节点 } return root; }
3.遍历二叉树(递归)
①前序遍历,前序遍历是1.遍历根节点、2.遍历左节点、3.遍历有节点
void PrevOrder()//前序遍历 { _PrevOrder(_root);//传根节点 cout<<endl; } void _PrevOrder(Node* T) { if(T==NULL) return; else { cout<<T->_data<<" ";//先访问根节点,在这里是直接输出 _PrevOrder(T->_left);//访问左节点 _PrevOrder(T->_right);//访问有节点 } }
②中序遍历(递归),中序遍历和前序遍历类似,只不过是将访问顺序变为1.左节点、2.根节点、3.有节点
void InOrder() { _InOrder(_root); cout<<endl; } void _InOrder(Node* T) { if(T==NULL) return; else { _InOrder(T->_left); cout<<T->_data<<" "; _InOrder(T->_right); } } void PostOrder() { _PostOrder(_root); cout<<endl; }
③后序遍历,也不例外,1.访问左节点、2.访问右节点、3.访问根节点
void PostOrder() { _PostOrder(_root); cout<<endl; } void _PostOrder(Node* T) { if(T==NULL) return; else { _PostOrder(T->_left);//访问左节点 _PostOrder(T->_right);//访问右节点 cout<<T->_data<<" ";//访问根节点 } }
4.非递归遍历二叉树
①前序序访问二叉树
前序采用栈来处理,如图所示,先压1,然后出1,压 2,3,这里先压3,后压2,是栈的特点,后进先出所以先出2,压 5、 4;然后出4,压9、 8;出 8,然后出9、出 5、出3;压 7 、6,出7,出6;
得到1,2,4,8,9,5,3,7,6;
void PrevOrder_NonR() { Node* T = _root; stack<Node*> s; while(T!=NULL||!s.empty()) { if(T!=NULL) { cout<<T->_data<<" "; s.push(T); T=T->_left; } else { T=s.top(); s.pop(); T=T->_right; } } cout<<endl; }
②中序遍历
中序遍历和前序是一样的采用栈来处理,只不过是先访问左节点,然后根节点、右节点
void InOrder_NonR() { Node* T = _root; stack<Node*> s; if(T==NULL) return; else { Node* temp=T; while(!s.empty()||temp!=NULL) { if(temp!=NULL) { s.push(temp);//先将所有的走节点压进去 temp=temp->_left; } else { temp=s.top();//访问节点 cout<<temp->_data<<" ";//记录 s.pop();//出栈 temp=temp->_right;//判断有节点; } } cout<<endl; } }
③后序访问
后序访问就比较复杂了,我解决他的办法是采用俩个栈,首先要说明的是:后序和前序是有关系的,来对比一下,前序:1.根节点、2.左节点、3.右节点后续:1.左节点、2、右节点、3.根节点。那么我们可以采用类似的方法:处理先以1.根节点、2.右节点、3.左节点 这种方式遍历并将遍历结果压入output栈中,然后出栈退栈,既得到1.左节点、2.右节点、3.根节点。
void PostOrder_NonR() { Node* T = _root; stack<Node*> s,output; while(T!=NULL||!s.empty()) { if(T!=NULL) { s.push(T);//先根节点 output.push(T);//入栈 T=T->_right;//右节点 } else { T=s.top(); s.pop(); T=T->_left;//走左节点 } } while(output.size()!=0) { Node* temp = output.top(); cout<<temp->_data<<" "; output.pop(); } cout<<endl; }
④层序访问二叉树
#下图是层序访问的结构图
有上述结构图可以看出这种访问方式,与队列是一模一样的,所以我们采用队列的方式解决。1.现将1入队,先记录1 然后出队(访问),通过1来使得2、3入队;然后2,记录后2出队,4 、5入队;然后3,记录后出队,6 、7入队….,就这样一直走下去直到队列为空为止。
void LevelOrder() { Node* root = _root; queue<Node*> q; if(root) q.push(root);//先使得第一个节点入队 while(q.size()!=0) { Node* temp=q.front();//记录 q.pop();//出队 cout<<temp->_data<<" "; if(temp->_left!=NULL)//先左 q.push(temp->_left); if(temp->_right!=NULL)//后右 q.push(temp->_right); } cout<<endl; }
相关文章推荐
- 数据结构之二叉树(遍历、建立、深度)
- 数据结构——二叉树的遍历
- 数据结构之查找二叉树
- 数据结构——二叉树的直径
- 数据结构实验之二叉树一:树的同构
- 数据结构之二叉树
- 数据结构实验之二叉树八:(中序后序)求二叉树的深度
- 数据结构与算法-二叉树
- 数据结构——二叉树的遍历
- 再回首,数据结构——树和二叉树的常用算法
- 数据结构3--树与二叉树
- 数据结构(13)二叉树的动态链表存储和遍历的实现
- 数据结构上机测试4.1:二叉树的遍历与应用1
- 数据结构之树和二叉树实现
- 数据结构实验之二叉树二:遍历二叉树
- 数据结构六:二叉树的先序建树与中序的非递归遍历算法
- 数据结构实验之二叉树的建立与遍历
- 数据结构——计算二叉树中二分结点的个数
- 数据结构——二叉树学习
- 二叉树的遍历:数据结构实验之二叉树二:遍历二叉树