C语言强化(十一)二叉树镜像变化 | 要求:不使用递归
来源:互联网 发布:淘宝更换手机号 编辑:程序博客网 时间:2024/05/18 01:55
用了这么久的递归,现在不让用递归了,你行么?
通过这道题,你可以学会
- 如何镜像变化一棵二叉树
- 什么是递归的本质
- 如何巧妙地使用辅助栈
题目:
输入一颗二元查找树,将该树转换为它的镜像,
即在转换后的二元查找树中,左子树的结点都大于右子树的结点。
要求:
不使用递归
例如输入:
输出:
将二叉树镜像变化的方法很简单,只要把所有节点的左右节点对调就行了,使用递归可以非常容易的实现。
如下为递归方法实现镜像变化的函数
/**二叉树镜像变化——递归方法实现*/void Revertsetree_Recursion(BTreeNode *root){if(!root)return;BTreeNode *p;p=root->leftNode;root->leftNode=root->rightNode;root->rightNode=p;if(root->leftNode)Revertsetree_Recursion(root->leftNode);if(root->rightNode)Revertsetree_Recursion(root->rightNode);}
现在问题来了,不使用递归,怎么办?
思路:
递归的本质是存储元素为函数的栈,
所以完成同样任务时最简单的办法就是用一个辅助栈来模拟递归,辅之以循环语句
- 首先,把树的头结点放入栈中
- 在循环中,只要栈不为空,弹出栈的栈顶结点,交换它的左右子树
- 如果它有左子树,把它的左子树压入栈中
- 如果它有右子树,把它的右子树压入栈中
- 在下次循环中交换它儿子结点的左右子树
如下为使用循环语句实现镜像变化的函数
/**二叉树镜像变化——循环方法实现*/void Revertsetree_Circle(BTreeNode *phead){if(!phead)return;stack<BTreeNode*> stacklist;stacklist.push(phead); //首先把树的头结点放入栈中。while(stacklist.size())//在循环中,只要栈不为空,弹出栈的栈顶结点,交换它的左右子树{BTreeNode* pnode=stacklist.top();stacklist.pop();BTreeNode *ptemp;ptemp=pnode->leftNode;pnode->leftNode=pnode->rightNode;pnode->rightNode=ptemp;if(pnode->leftNode)stacklist.push(pnode->leftNode); //若有左子树,把它的左子树压入栈中if(pnode->rightNode)stacklist.push(pnode->rightNode); //若有右子树,把它的右子树压入栈中}}
源代码
/**题目:输入一颗二元查找树,将该树转换为它的镜像,即在转换后的二元查找树中,左子树的结点都大于右子树的结点。要求:不使用用递归思路把所有节点的左右节点对调使用递归可以很简单的实现由于递归的本质是编译器生成了一个函数调用的栈,因此用循环来完成同样任务时最简单的办法就是用一个辅助栈来模拟递归首先我们把树的头结点放入栈中。在循环中,只要栈不为空,弹出栈的栈顶结点,交换它的左右子树。如果它有左子树,把它的左子树压入栈中;如果它有右子树,把它的右子树压入栈中。这样在下次循环中就能交换它儿子结点的左右子树了*/#include<stdlib.h>#include <iostream>#include<sstream>#include <vector>#include<stack>using namespace std;//创建二叉树结构体struct BTreeNode{int value;BTreeNode *leftNode;BTreeNode *rightNode;};/*二叉树构造函数按照二叉排序的算法插入(左小右大)node二叉树的根结点value要插入的结点的值 */void insertToBTree(BTreeNode * &node,int value){//结点为空,插入结点为根结点if(NULL==node){BTreeNode * btNode=new BTreeNode();btNode->value=value;btNode->leftNode=NULL;btNode->leftNode=NULL;node=btNode;}else{//结点非空//值小于根结点,递归左结点if((node->value)>value)insertToBTree(node->leftNode,value);//值大于根结点,递归右结点else if(value>(node->value))insertToBTree(node->rightNode,value);//值与已有结点值相等,提示错误elseprintf("结点已经存在,不可以再次插入!");}}/*前序遍历二叉排序树btNode 二叉树根结点*/void goThroughBTree(BTreeNode * btNode){//结点为空,返回if(NULL==btNode)return;cout<<btNode->value<<endl;//左结点不为空,继续向左深入if(NULL!=btNode->leftNode)goThroughBTree(btNode->leftNode);//右不为空,向右深入if(NULL!=btNode->rightNode){goThroughBTree(btNode->rightNode);}}/**二叉树镜像变化——递归方法实现*/void Revertsetree_Recursion(BTreeNode *root){if(!root)return;BTreeNode *p;p=root->leftNode;root->leftNode=root->rightNode;root->rightNode=p;if(root->leftNode)Revertsetree_Recursion(root->leftNode);if(root->rightNode)Revertsetree_Recursion(root->rightNode);}/**二叉树镜像变化——循环方法实现*/void Revertsetree_Circle(BTreeNode *phead){if(!phead)return;stack<BTreeNode*> stacklist;stacklist.push(phead); //首先把树的头结点放入栈中。while(stacklist.size())//在循环中,只要栈不为空,弹出栈的栈顶结点,交换它的左右子树{BTreeNode* pnode=stacklist.top();stacklist.pop();BTreeNode *ptemp;ptemp=pnode->leftNode;pnode->leftNode=pnode->rightNode;pnode->rightNode=ptemp;if(pnode->leftNode)stacklist.push(pnode->leftNode); //若有左子树,把它的左子树压入栈中if(pnode->rightNode)stacklist.push(pnode->rightNode); //若有右子树,把它的右子树压入栈中}}void main(){BTreeNode *root=NULL;//二叉树根结点//创建二叉排序树insertToBTree(root,8);insertToBTree(root,6);insertToBTree(root,10);insertToBTree(root,5);insertToBTree(root,7);insertToBTree(root,9);insertToBTree(root,11);//遍历二叉树cout<<"原二叉树:"<<endl;goThroughBTree(root);//Revertsetree_Recursion(root);Revertsetree_Circle(root);cout<<"镜像二叉树:"<<endl;goThroughBTree(root);system("pause");}
运行图
关于辅助栈的用法在C语言强化(二)设计可以求最小元素的栈有介绍过
此次再次使用,相信同学们会对它有更深理解体会。
总结
递归的本质是一个存储了函数的栈
1 0
- C语言强化(十一)二叉树镜像变化 | 要求:不使用递归
- C语言强化(十)求 1+2+…+n | 要求:不使用关键字
- C语言函数的递归强化版
- C语言 二叉树 递归
- 求二叉树镜像(破坏二叉树和不破坏二叉树使用非递归实现求解二叉树镜像)
- C语言强化(四)求和为某个值的二叉树路径
- C语言强化(八)判断序列是不是二叉查找树的后序遍历结果
- 二叉树的遍历(c语言非递归算法)
- C语言递归实现二叉链表
- C语言 二叉树的遍历 递归和(多种)非递归算法
- 二叉树遍历的递归和非递归实现(C语言)
- C语言 二叉树的遍历(递归和非递归)
- C语言 二叉树的遍历递归和(多种)非递归算法
- C语言数据结构实现二叉树递归与非递归遍历(数据结构第四次实验)
- C语言二叉树的遍历,递归和非递归
- DS基础--先序遍历二叉树(递归、非递归、线索二叉树,C语言描述)
- 【c语言】 交换两个整形变量的值(要求不创建临时变量)
- C语言记忆强化1
- 互联网时代是一个“打劫”的时代
- jvm默认异常处理,和自定义异常处理
- win7 下配置 Qt5.1 for Android
- 外地户口在京生娃办材料系列之生育联络单
- iPhone和iPad屏幕的尺寸和分辨率
- C语言强化(十一)二叉树镜像变化 | 要求:不使用递归
- SVN 上传工程
- IOS网络开发框架
- 八大排序算法总结
- python 中迭代多个序列
- SQL 语言
- 强大的正则表达式编辑器Rubular
- CoreImage的一处简单使用
- COCOS2D-X 网络篇---强联网(采用技术 BSD SOCKET+多线程技术 +protobuf)客户端实战篇