二叉树的四种遍历的递归和非递归的实现
来源:互联网 发布:支付宝小程序源码 编辑:程序博客网 时间:2024/06/02 03:28
二叉树的三种遍历为:前序遍历,中序遍历和后序遍历。
遍历的实现可分为递归和非递归。递归法与二叉树的定义相似,非递归法采用栈去模拟实现。
一、前序遍历的次序为:根结点——左结点——右结点。
递归法实现:
//前序遍历的递归实现void preOrder1(BinaryTreeNode* pRoot){ if(pRoot==NULL) return; cout<<pRoot->value; if(pRoot->left!=NULL) preOrder1(pRoot->left); if(pRoot->right!=NULL) preOrder1(pRoot->right);}非递归的实现:
前序遍历的访问顺序为:根,左和右。对于任一结点,其可看做根结点,因此可直接访问。访问完后,若其左孩子不为空,则按照相同规则访问它的左子树;访问完左子树,再访问它的右子树。处理过程如下:
对于任一结点P:
step 1:访问结点p,并将结点p入栈。
step 2:判断结点p的左孩子是否为空。若为空,则取栈顶结点并出栈,将栈顶元素的右孩子设为当前的结点p,循环至step 1。
若不为空,则将p的左孩子设为当前结点p。
step 3:直到p为NULL,并且栈为空,则遍历结束。
//前序遍历的非递归遍历void preOrder2(BinaryTreeNode* pRoot){ stack<BinaryTreeNode*> s; BinaryTreeNode *p=pRoot; if(pRoot==NULL) return; while(p!=NULL||!s.empty()) { while(p!=NULL) { cout<<p->value<<" "; s.push(p); p=p->left; } if(!s.empty()) { p=s.top(); s.pop(); p=p->right; } }}二、中序遍历的次序为:左结点——根结点——右结点
递归法:
//中序遍历的递归法void inOrder1(BinaryTreeNode* pRoot){ if(pRoot==NULL) return; if(pRoot->left!=NULL) inOrder1(pRoot->left); cout<<pRoot->value; if(pRoot->right!=NULL) inOrder1(pRoot->right);}非递归法:
根据中序遍历的顺序,对于任一结点,先访问其左孩子。而左孩子又可以看做一个根结点,然后继续访问左孩子,直到遇到的左孩子结点为空,则停止访问。然后访问右孩子。
处理过程如下:
对于任一结点p:
step 1:若其左孩子不为空,则将p入栈,并将p的左孩子置为当前的p。然后对当前结点p再进行相同的处理。
step 2:若其左孩子为空,则取栈顶元素并进行出栈操作,访问该栈顶结点,然后将栈顶结点的右孩子置为当前的P结点。
step 3:直到p为NULL并且栈为空则遍历结束。
//中序遍历的非递归法void inOrder(BinaryTreeNode* pRoot){ stack<BinaryTreeNode*> s; BinaryTreeNode *p=pRoot; while(p!=NULL||!s.empty()) { while(p!=NULL) { s.push(p); p=p->left; } if(!s.empty()) { p=s.top(); cout<<p->value; s.pop(); p=p->right; } }}三、后序遍历
递归法:左结点——右结点——根结点。
//后序遍历的递归法void postOrder1(BinaryTreeNode* pRoot){ if(pRoot==NULL) return; postOrder1(pRoot->left); postOrder1(pRoot->right); cout<<pRoot->value<<" ";}非递归遍历:要保证根结点在左孩子和右孩子访问之后才能访问。因此对于任一结点p,先将其入栈。
若p不存在左孩子和右孩子,则可以直接访问它。或者p存在左孩子或者右孩子,但是左孩子和右孩子都已经被访问过了,则可以直接访问该结点。
若非上述两种情况,则将右孩子和左孩子依次入栈。这样可以保证每次取栈顶元素时,左孩子在右孩子前面被访问,根结点在左孩子和右孩子访问之后被访问。
//后序遍历的非递归法void postOrder(BinaryTreeNode* pRoot){ stack<BinaryTreeNode*> s; BinaryTreeNode *cur; BinaryTreeNode *pre=NULL; s.push(pRoot);//根结点入栈 while(!s.empty()) { cur=s.top(); if((cur->left==NULL&&cur->right==NULL)||(pre!=NULL&&(pre==cur->left||pre==cur->right))) { //左孩子和右孩子同时为空,或者当前结点的左孩子或右孩子已经遍历过了 cout<<cur->value<<" "; s.pop(); pre=cur; } else { if(cur->right!=NULL) s.push(cur->right); if(cur->left!=NULL) s.push(cur->left); } }}
四、层次遍历(剑指Offer上有涉及)
题目:从上到下打印二叉树的每个节点,同层的节点按照从左向右打印。
解析:即分层遍历二叉树。利用广度优先遍历的思想,遍历树或者有向图,都可在队列中完成。
step1:把起始节点放入队列。
step2:每次从队头取出节点,遍历(输出)。接下来,把从该节点能到达的节点(子树或者其他)都依次放入队列。
重复step2,直到队列中的节点为空。
void PrintFromTopToBottom(BinaryTreeNode* pRoot){ if(pRoot == NULL) return; std::deque<BinaryTreeNode *> dequeTreeNode; dequeTreeNode.push_back(pRoot); while(dequeTreeNode.size()) { BinaryTreeNode *pNode = dequeTreeNode.front(); dequeTreeNode.pop_front(); printf("%d ", pNode->m_nValue); if(pNode->m_pLeft) dequeTreeNode.push_back(pNode->m_pLeft); if(pNode->m_pRight) dequeTreeNode.push_back(pNode->m_pRight); }}
- 二叉树的四种遍历的递归和非递归的实现
- 四种遍历二叉树的方式(递归,非递归)
- 二叉树的四种遍历(递归、非递归)
- 二叉树的遍历:递归和非递归实现
- 二叉树遍历的递归和非递归实现
- 二叉树创建、遍历的递归和非递归实现
- 二叉树遍历输出的递归和非递归实现
- 二叉树的遍历(非递归和递归实现)
- 二叉树的前中后序遍历-递归和非递归实现
- 二叉树遍历的递归和非递归实现
- 二叉树的遍历实现(递归和非递归)
- 递归和非递归实现二叉树的后续遍历
- Python实现二叉树的递归和非递归遍历
- 二叉树的遍历---递归和非递归实现
- Tree(3)--二叉树的实现及四种遍历(递归/非递归)
- 二叉树的四种遍历方式(非递归和递归)
- 总结的四种二叉树遍历算法(递归和非递归)
- 二叉树的三种遍历方式的递归实现和非递归实现
- JNI笔记
- 1.6 五分钟学会OpenStack 基础知识
- hive大数据倾斜总结
- android Html5学习代码
- ubuntu下编译protobuf
- 二叉树的四种遍历的递归和非递归的实现
- Android 沉浸式工具栏把内容挡住
- Gradle学习系列之三——读懂Gradle语法
- Linux环境下安装MySQL|Linux下Mysql安装教程
- 1.7三分钟读懂Saas、Paas、IaaS的区别
- 安卓中的事件分发机制源码解析
- 计算机图形学基础(零) 介绍
- Oracle 海量数据处理- 索引的选择
- CentOS6.5虚拟机安装Caffe大致记录