二叉树各种操作的非递归实现
来源:互联网 发布:淘宝实拍保护平台 编辑:程序博客网 时间:2024/05/19 02:28
#include "stdafx.h"#include <iostream>#include <stack>#include <queue>//定义二叉树(二叉链表表示法)的节点typedef struct BiTNode{char data;//数据域struct BiTNode * lchild;//指向左子树struct BiTNode * rchild;//指向右子树} BiTNode, * BiTree;/////////下面为辅助函数//////////////////BiTree createBiTNode(char data){ BiTree p=(BiTree) malloc(sizeof(BiTNode)); if(p!=NULL) { p->data=data; p->lchild=NULL; p->rchild=NULL; return p; } return NULL;}void createLChild(BiTree & parent,BiTree & lchild){ parent->lchild=lchild;}void createRChild(BiTree & parent,BiTree & rchild){ parent->rchild=rchild;}//////////////////////////////////////////////由于主要讨论遍历所以随意创建一颗二叉树//创建一颗如图所示的二叉树// A// /// B// / \// C D// / \// E F// \// GBiTree createBiTree(){ BiTree Pa=createBiTNode('A'); BiTree Pb=createBiTNode('B'); BiTree Pc=createBiTNode('C'); BiTree Pd=createBiTNode('D'); BiTree Pe=createBiTNode('E'); BiTree Pf=createBiTNode('F'); BiTree Pg=createBiTNode('G'); createLChild(Pa,Pb); createLChild(Pb,Pc); createRChild(Pb,Pd); createLChild(Pd,Pe); createRChild(Pd,Pf); createRChild(Pe,Pg); return Pa;}//摧毁二叉树//这里定义的是递归摧毁,也可以定义非递归摧毁void DestoryBiTree(BiTree t){ if(t!=NULL) { BiTree plchild=t->lchild; BiTree prchild=t->rchild; free(t); DestoryBiTree(plchild); DestoryBiTree(prchild); }}//定义一个全局访问函数//////////////////void vist(char data){std::cout<<data<<" ";}////////////////下面是递归遍历算法/////////先序递归遍历算法///////////////////////void PreOrderTraverse(BiTree t){if(t!=NULL){vist(t->data);//遍历根节点 PreOrderTraverse(t->lchild);//先序遍历左子树PreOrderTraverse(t->rchild);//先序遍历右子树}}//中序递归遍历算法/////////////////////void InOrderTraverse(BiTree t){if(t!=NULL){ InOrderTraverse(t->lchild);//中序遍历左子树vist(t->data);//遍历根节点InOrderTraverse(t->rchild);//中序遍历右子树}}//后序递归遍历算法/////////////////////void PostOrderTraverse(BiTree t){ if(t!=NULL){ PostOrderTraverse(t->lchild);//后序遍历左子树PostOrderTraverse(t->rchild);//后序遍历右子树vist(t->data);//遍历根节点}}///////////////////////////////////////////////////////////////////////下面是非递归遍历算法////////////////先序非递归遍历算法//////////////////思路//对于任一结点P:// 1)访问结点P,并将结点P入栈;// 2)判断结点P的左孩子是否为空,若为空,则取栈顶结点并进行出栈操作,并将栈顶结点的右孩子置为当前的结点P,循环至1);若不为空,则将P的左孩子置为当前的结点P;// 3)直到P为NULL并且栈为空,则遍历结束。void Nonrecursive_PreOrderTraverse(BiTree t){std::stack<BiTree> stack;//定义一个栈 BiTree p=t;BiTree q;while(p!=NULL || !stack.empty()){if(p!=NULL){//////访问数据///////// vist(p->data);/////////////////////////stack.push(p);p=p->lchild;}else{ q=stack.top(); stack.pop(); p=q->rchild;}}}//中序非递归遍历算法//////////////////思路:// 对于任一结点P,// 1)若其左孩子不为空,则将P入栈并将P的左孩子置为当前的P,然后对当前结点P再进行相同的处理;// 2)若其左孩子为空,则取栈顶元素并进行出栈操作,访问该栈顶结点,然后将当前的P置为栈顶结点的右孩子;// 3)直到P为NULL并且栈为空则遍历结束void Nonrecursive_InOrderTraverse(BiTree t){std::stack<BiTree> stack;//定义一个栈 BiTree p=t;BiTree q;while(p!=NULL || !stack.empty()){if(p!=NULL){stack.push(p);p=p->lchild;}else{ q=stack.top(); stack.pop(); //////访问数据///////// //跟先序其他都一样只是访问数据操作的时机不同 vist(q->data); /////////////////////// p=q->rchild;}}}//非递归后序遍历的算法较复杂 //-------重点---------//后序非递归遍历算法//////////////////思路一//对于任一结点P,将其入栈,然后沿其左子树一直往下搜索,//直到搜索到没有左孩子的结点,此时该结点出现在栈顶,//但是此时不能将其出栈并访问,因此其右孩子还为被访问。//所以接下来按照相同的规则对其右子树进行相同的处理,//当访问完其右孩子时,该结点又出现在栈顶,此时可以将其出栈并访问。//这样就保证了正确的访问顺序。可以看出,在这个过程中,每个结点都两次出现在栈顶,//只有在第二次出现在栈顶时,才能访问它。因此需要多设置一个变量标识该结点是否是第一次出现在栈顶。typedef struct PostTraNode{BiTree p;//指向二叉树节点的指针bool isPop;//下次出现在栈顶是是否应该出栈}PostTraNode;void Nonrecursive_PostOrderTraverse1(BiTree t){ BiTree p=t; std::stack <PostTraNode *> stack; while(p!=NULL || !stack.empty()) { if(p!=NULL) { PostTraNode * pPost=(PostTraNode *)malloc(sizeof(PostTraNode)); if(pPost) { pPost->isPop=false; pPost->p=p; } stack.push(pPost); p=p->lchild; } else { PostTraNode * pPost=stack.top(); if(pPost->isPop)//可以出栈,即可以访问该节点 { stack.pop(); vist(pPost->p->data); } else { pPost->isPop=true; p=pPost->p->rchild; } } }}//思路二//要保证根结点在左孩子和右孩子访问之后才能访问,因此对于任一结点P,//先将其入栈。如果P不存在左孩子和右孩子,则可以直接访问它;//或者P存在左孩子或者右孩子,但是其左孩子和右孩子都已被访问过了,//则同样可以直接访问该结点。若非上述两种情况,则将P的右孩子和左孩子依次入栈,//这样就保证了每次取栈顶元素的时候,左孩子在右孩子前面被访问,//左孩子和右孩子都在根结点前面被访问。void Nonrecursive_PostOrderTraverse2(BiTree t){if(t==NULL)return; BiTree cur;BiTree pre=NULL;//上一次访问的节点std::stack<BiTree> stack;stack.push(t);while(!stack.empty()){ cur=stack.top();if((cur->lchild==NULL && cur->rchild==NULL) || (pre!=NULL && (cur->lchild==pre || cur->rchild==pre))){ stack.pop();vist(cur->data);pre=cur;}else{if((cur->rchild)!=NULL)stack.push(cur->rchild);if((cur->lchild)!=NULL)stack.push(cur->lchild);}}}//按层从上到下,从左到右遍历void Nonrecursive_LayerOrderTraverse(BiTree t){if(t==NULL)return;std::queue<BiTree> queue;//定义一个队列BiTree p=t;queue.push(p);while(!queue.empty()){ p=queue.front();queue.pop();vist(p->data);if(p->lchild != NULL)queue.push(p->lchild);if(p->rchild != NULL)queue.push(p->rchild);}}//////////////////////////////////////////////////////////////////////////////求二叉树的深度/////////////////////////int max(int x,int y){return x>y ? x : y;}////递归算法int BiTreeDepth(BiTree t){ if(t==NULL)return 0;else return 1+max(BiTreeDepth(t->lchild),BiTreeDepth(t->rchild));}////非递归实现int Nonrecursive_BiTreeDepth(BiTree t){if(t==NULL)return 0;int depth=1;std::queue<BiTree> queue;BiTree p=t;queue.push(p);queue.push(NULL);//NULL标志一层结束while(queue.size()>1){p=queue.front();queue.pop();if(p!=NULL){if(p->lchild!=NULL)queue.push(p->lchild);if(p->rchild!=NULL)queue.push(p->rchild);}else{++depth;queue.push(NULL);}}return depth;}int _tmain(int argc, _TCHAR* argv[]){BiTree t=createBiTree(); PreOrderTraverse(t);std::cout<<std::endl; InOrderTraverse(t);std::cout<<std::endl;PostOrderTraverse(t);std::cout<<std::endl;std::cout<<BiTreeDepth(t)<<std::endl; std::cout<<"非递归遍历结果余下"<<std::endl;Nonrecursive_PreOrderTraverse(t);std::cout<<std::endl;Nonrecursive_InOrderTraverse(t); std::cout<<std::endl; Nonrecursive_PostOrderTraverse1(t); std::cout<<std::endl;Nonrecursive_PostOrderTraverse2(t); std::cout<<std::endl;Nonrecursive_LayerOrderTraverse(t); std::cout<<std::endl;std::cout<<Nonrecursive_BiTreeDepth(t)<<std::endl;std::cout<<std::endl;DestoryBiTree(t);system("PAUSE");return 0;}
参考资料: 数据结构(C语言版)严蔚敏 P126——P131
- 二叉树各种操作的非递归实现
- 二叉树的各种遍历的递归非递归实现。
- 遍历二叉树的各种操作(非递归遍历)
- 遍历二叉树的各种操作(非递归遍历)
- 遍历二叉树的各种操作(非递归遍历)
- 遍历二叉树的各种操作(非递归遍历)
- 遍历二叉树的各种操作(非递归遍历)
- 遍历二叉树的各种操作(非递归遍历)
- 遍历二叉树的各种操作(非递归遍历)
- 遍历二叉树的各种操作(非递归遍历)
- 遍历二叉树的各种操作(非递归遍历)
- 遍历二叉树的各种操作(非递归遍历)
- 遍历二叉树的各种操作(非递归遍历)
- 遍历二叉树的各种操作(非递归遍历)
- 遍历二叉树的各种操作(非递归遍历)
- 遍历二叉树的各种操作(非递归遍历)
- 遍历二叉树的各种操作(非递归遍历)
- 遍历二叉树的各种操作(非递归遍历)
- VC++的Unicode编程
- 如何将jQuery的"$"转换为别的名字
- 几种常见的排序算法实现
- 在客户机自动挂载家目录
- android WebView实现java与javascript的交互
- 二叉树各种操作的非递归实现
- opiodr aborting process unknown ospid (24117442) as a result of ORA-609
- dhcp服务器
- 计算excel列的名字
- samba文件服务器跨windwos 局域网
- php里存储json格式的数据报错之单双引号
- 远程连接
- bash:vi:command not find
- 关于GDAL计算图像坐标的几个问题