二叉树各种操作的非递归实现

来源:互联网 发布:淘宝实拍保护平台 编辑:程序博客网 时间: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

原创粉丝点击