二叉树的建立(非递归建立与定义建立)与基本操作(广度和深度遍历,求叶子树高)实现

来源:互联网 发布:怎么在手机淘宝交电费 编辑:程序博客网 时间:2024/04/30 11:17

      二叉树的建立可以用二叉树性质第六条建立,也可以按照完全二叉树的定义来建立。

      遍历主要分为广度优先遍历和深度优先遍历,深度优先遍历又分为递归前序遍历、递归后序遍历、递归中序遍历,和非递归前序遍历、非递归后序遍历、非递归中序遍历。

      广度优先遍历主要用队列的思想实现,而深度优先遍历如上述所说用递归和非递归思想实现。


现在说说建立和遍历的实现思想。

       二叉树建立的基本思想是:依次输入节点信息,若输入的节点不是虚节点,则建立一个新节点。若新节点是第一个节点,则令其为根节点;否则将新节点作为孩子节点链接到它的双亲节点上。如此反复进行,直到输入结束标志#为止。为使新节点能够与双亲节点正确相连,以及考虑到这种方法中先建立的节点,其孩子节点也一定要先建立的特点,可以设置一个指针型的数组构成的队列来保存已输入的节点的地址,并使队尾(rear)指向当前输入的节点;对头(front)指向这个节点的双亲节点。由于根节点的地址放在队列的第一个单元里,因此当rear为偶数是,rear所指向的节点应作为左孩子与其双亲节点链接;否则rear所指向的节点应作为右孩子预期双亲节点链接。若双亲节点或孩子节点为虚节点,则无需链接。当双亲节点与两个孩子节点链接完毕,才进行出队操作,使对头指针指向下一个待链接的双亲节点。

       递归遍历的思想:符合人的思维逻辑,无需多说,只不过要搞清楚算法执行的内部步骤也是不容易的,有兴趣的诸君可以自行尝试。

       非递归遍历的思想:(中序遍历为例)使用一个堆栈stack[N]来保存每次调用的参数,这个堆栈的栈顶指针为top,另设一个活动指针p来指向当前访问的节点。当p所指向的节点非空,将该节点的地址进栈,然后将p指向该节点的左孩子节点;当p所指向的节点为空时,从栈顶退出栈顶元素,并访问该节点,然后将p指向该节点的右孩子节点;如此反复,直到p为空并且栈顶指针头top=-1为止。

      下面给出实现的代码和运行结果,还是秉持一贯的作风建议一句:将运行结果和代码对照起来学习,效果更明显。其中递归遍历全部实现了,而非递归遍历只实现了中序遍历,其他两种遍历留给诸君进行练习,学了之后总要检验下学会了没有吧?哈哈

/*********************\Author:HarrykateDate:2014/9/14Time:17:08Name:binarytree\*********************/#include "iostream"#include "malloc.h"using namespace std;#define Maxsize 1024typedef char datatype;typedef struct node{datatype data;struct node*lchild,*rchild;}bitree;bitree*CreatTree()//非递归的方式建立完全二叉树{cout<<"连续输入字符建立完全二叉树,并以‘#’结束"<<endl;char ch;bitree*Q[Maxsize];int front,rear;bitree*root,*s;root=NULL;front=1,rear=0;while ((ch=getchar())!='#'){s=NULL;s=(bitree*)malloc(sizeof(bitree));s->data=ch;s->lchild=NULL;s->rchild=NULL;rear++;Q[rear]=s;if (rear==1)root=s;else{if(s&&Q[front]){if(rear%2==0)Q[front]->lchild=s;elseQ[front]->rchild=s;}if(rear%2==1)front++;}}return root;}bitree *CreatTree2(int i,int n)//定义的方式建立完全二叉树                           //不够通用,仅提供一种参考{bitree *root;root=(bitree*)malloc(sizeof(bitree));root->data=i;if(2*i<=n)              //若2*i<=n,那么tree的左孩子为tree[2*i];root->lchild=CreatTree2(2*i,n);elseroot->lchild=NULL;if(2*i+1<=n)//若2*i+1<=n,那么tree的右孩子为tree[2*i+1];root ->rchild=CreatTree2(2*i+1,n);elseroot->rchild=NULL;return root;}void PreOrder(bitree*p)//前序递归遍历{if (p!=NULL){cout<<"->"<<p->data;PreOrder(p->lchild);PreOrder(p->rchild);}}void InOrder(bitree*p)//中序递归遍历{if (p!=NULL){InOrder(p->lchild);cout<<"->"<<p->data;InOrder(p->rchild);}}void NinOrder(bitree*p)//非递归的中序遍历,其他两种非递归遍历诸君自己实现{bitree*stack[Maxsize];bitree*s=p;int top=-1;while (top!=-1||s!=NULL){while (s!=NULL){if (top==Maxsize-1){cout<<"OVERFLOW";return;}else{top++;stack[top]=s;s=s->lchild;}}s=stack[top];top--;cout<<s->data;s=s->rchild;}}void PostOrder(bitree*p)//后序递归遍历{if (p!=NULL){PostOrder(p->lchild);PostOrder(p->rchild);cout<<"->"<<p->data;}}void Layer(bitree*p)//用队列实现广度优先遍历{bitree*Q[Maxsize];bitree*s;int rear=1,front=0;Q[rear]=p;while (front<rear){front++;s=Q[front];cout<<"->"<<s->data;if (s->lchild!=NULL){rear++;Q[rear]=s->lchild;}if (s->rchild!=NULL){rear++;Q[rear]=s->rchild;}}}int CountLeaf(bitree*p)//计算叶子节点数目{if(!p)return 0;else if(!p->lchild&&!p->rchild)return 1;elsereturn CountLeaf(p->lchild)+CountLeaf(p->rchild);}int Height(bitree*p)//计算数的高度{int lc,rc;if(p==NULL)return 0;lc=Height(p->lchild)+1;rc=Height(p->rchild)+1;return lc>rc?lc:rc;}int main(){bitree*p;int leaf,height;p=CreatTree();cout<<"深度优先遍历如下所示"<<endl<<endl;;cout<<"    前序遍历为";PreOrder(p);cout<<endl<<endl;cout<<"    中序遍历为";InOrder(p);cout<<endl<<endl;cout<<"    后序遍历为";PostOrder(p);cout<<endl<<endl;cout<<"广度优先遍历为";Layer(p);cout<<endl<<endl;leaf=CountLeaf(p);cout<<"叶子数目为:"<<leaf<<endl<<endl;height=Height(p);cout<<"数的高度为:"<<height<<endl<<endl;return 0;}
运行结果如下:



终于写完了,代码有点多,工作量比较大。不过诸君能通过这篇博文学会二叉树的基本操作,那也是甚感欣慰的。

鼓掌!!




0 0
原创粉丝点击