//测试数据:EBH GAC F D
#include<iostream>
#include<cstdio>
#include<stack>
#include<queue>
using namespace std;
typedef char Elemtype;
//定义这棵树的结点
typedef struct node{
Elemtype data;
struct node *lchild;
struct node *rchild;
}BitTree;
//递归先序遍历
void PreOrder(BitTree *bt)
{
if(bt!=NULL)
{
cout<<bt->data;
PreOrder(bt->lchild);
PreOrder(bt->rchild);
}
}
//非递归先序遍历
void Preorder(BitTree *bt)
{
BitTree *p;
stack<BitTree *> s;
s.push(bt);
while(!s.empty())
{
p=s.top();
s.pop();
while(p)
{
cout<<p->data;
if(p->rchild) s.push(p->rchild);
p=p->lchild;
}
}
}
//递归中序遍历
void InOrder(BitTree *bt)
{
if(bt!=NULL)
{
InOrder(bt->lchild);
cout<<bt->data;
InOrder(bt->rchild);
}
}
//非递归中序遍历
void Inorder(BitTree *bt)
{
stack<BitTree *> s;
s.push(bt);
BitTree *p;
p=bt->lchild;
while(p||!s.empty())
{
while(p)
{
s.push(p);
p=p->lchild;
}
p=s.top();
s.pop();
cout<<p->data;
p=p->rchild;
}
}
//递归后序遍历
void PostOrder(BitTree *bt)
{
if(bt!=NULL)
{
PostOrder(bt->lchild);
PostOrder(bt->rchild);
cout<<bt->data;
}
}
//非递归后序遍历
void Postorder(BitTree *bt)
{
stack<BitTree *> s;
BitTree *p,*q;
p=bt;
q=NULL;
while(p||!s.empty())//使用p的原因是方便第一次进入,优化代码
{
if(p!=q)
{
while(p)
{
s.push(p);
if(p->lchild) p=p->lchild;
else p=p->rchild;
}
}
if(s.empty()) break;//写这句话的原因是访问根结点结束后,p为非空,所以还是能够进入循环,但堆栈已空,所以要用这句话推出
q=s.top();
if(q->rchild==p)
{
s.pop();
cout<<q->data;
p=q;
}
else p=q->rchild;
}
}
//二叉树的非递归层次遍历
void levelBitTree(BitTree *bt)
{
queue<BitTree *> q;
BitTree *p;
p=NULL;
p=bt;
if(p) q.push(p);
while(!q.empty())
{
p=q.front();
q.pop();
cout<<p->data;
if(p->lchild) q.push(p->lchild);
if(p->rchild) q.push(p->rchild);
}
}
//建立二叉链表算法
BitTree *creBitTree()
{
BitTree *bt; Elemtype x;
scanf("%c",&x);
if(x==' ') bt=NULL;
else{
bt=(BitTree *)malloc(sizeof(BitTree));
bt->data=x;
bt->lchild=creBitTree();
bt->rchild=creBitTree();
}
return bt;
}
//统计二叉树中叶子节点的个数
int cleaf=0;
void countleaf(BitTree *bt)
{
if(bt!=NULL)
{
if(bt->lchild==NULL&&bt->rchild==NULL) cleaf++;
countleaf(bt->lchild);
countleaf(bt->rchild);
}
}
//交换二叉树中所有结点的左右子树
void exchange(BitTree *bt)
{
BitTree *t;
if(bt!=NULL)
{
if(bt->lchild!=NULL||bt->rchild!=NULL)
{t=bt->lchild;bt->lchild=bt->rchild;bt->rchild=t;}
exchange(bt->lchild);
exchange(bt->rchild);
}
}
//求二叉树的高度
int hightree(BitTree *bt)
{
int h,h1,h2;
if(bt==NULL) h=0;
else{
h1=hightree(bt->lchild);
h2=hightree(bt->rchild);
h=(h1>h2?h1:h2)+1;
}
return h;
}
//查找值为x的结点
int ok=0;
void searchtree(BitTree *bt,Elemtype x,BitTree **p1)
{
if(bt!=NULL&&!ok)
{
if(bt->data==x)
{ok=1;*p1=bt;}
else{
*p1=NULL;
searchtree(bt->lchild,x,p1);
searchtree(bt->rchild,x,p1);
}
}
}
//删除值为x的结点,使得其左右子树的安排仍然满足原来的中序遍历序列
/*分析:为了保持中序遍历序列不变,对于找到的结点p可以分为4种情况考虑
(1)若结点p为叶子结点,则只需将该结点p的双亲结点f的左指针或右指针置为空即可
(2)若结点p的左子树为空,则只需将该结点p的双亲结点f的左指针或右指针指向该结点p的右孩子即可
(3)若结点p的左子树非空,则只需找到结点p的左子树中最右下的结点s(s的右指针必为空),将该结点s的左子树接到该结点s的双亲结点q上,再用该结点s中的数据替换p中的数据,最后删除该结点(s)即可
(4)若结点p为根结点bt且该结点左子树为空,则只需将根结点的指针bt移到结点p的右子树上即可
详细图解分析在 秦玉平 马靖善所编的数据结构(第三版) p129-129的例5.14*/
//为了此功能专门设计的查找函数,f记录双亲结点,p记录查找到的结点
int Find=0;
void search(BitTree *bt,Elemtype x,BitTree **p,BitTree **f)
{
if(bt!=NULL&&!Find)
{
if(bt->data==x)
{Find=1;*p=bt;}
else{
if(!Find){
*f=bt;
search(bt->lchild,x,p,f);
}
if(!Find){
*f=bt;
search(bt->rchild,x,p,f);
}
}
}
}
//删除x的函数
void deltree(BitTree **bt,Elemtype x)
{
BitTree *p,*f;
BitTree *q,*s;
p=f=NULL;
search(*bt,x,&p,&f);
if(p!=NULL)
{
if(p->lchild!=NULL)
{
q=p->lchild;
s=q;
while(s->rchild!=NULL){q=s;s=s->rchild;}
if(q!=s) q->rchild=s->lchild;
else p->lchild=q->lchild;
p->data=s->data;
free(s);
}
else{
if(f!=NULL){
if(p==f->lchild) f->lchild=p->rchild;
else f->rchild=p->rchild;
}
else
*bt=(*bt)->rchild;
free(p);
}
}
else
cout<<"Not find this node"<<endl;
}
int main()
{
BitTree *bt;
// BitTree **p1;
// Elemtype x;
// Elemtype y;
// int h;
bt=creBitTree();//建树
// PreOrder(bt);//递归先序
// cout<<endl;
// InOrder(bt);//递归中序
// cout<<endl;
// PostOrder(bt);//递归后序
// cout<<endl;
// countleaf(bt);//统计叶子结点个数
// cout<<cleaf<<endl;
// exchange(bt);
// PreOrder(bt);//递归先序
// cout<<endl;
// InOrder(bt);//递归中序
// cout<<endl;
// PostOrder(bt);//递归后序
// cout<<endl;
// h=hightree(bt);//求树的高度
// cout<<h<<endl;
// cin>>x;
// p1=(BitTree **)malloc(sizeof(BitTree));//给**p开辟空间
// searchtree(bt,x,p1);//找到x,并把x的地址存放在p里面,注意,p放的是x的地址,而不是这个地址里的内容
// cout<<(*p1)->data<<endl;//输出p指的内容,也就是找到的x
// cin>>y;
// deltree(&bt,y);
// InOrder(bt);//递归中序
// cout<<endl;
// Preorder(bt);//非递归先序遍历
// cout<<endl;
// Inorder(bt);//非递归中序遍历
// cout<<endl;
// Postorder(bt);//非递归后序遍历
// cout<<endl;
levelBitTree(bt);
cout<<endl;
return 0;
}
链式二叉树的递归与遍历
最新推荐文章于 2021-09-15 00:41:38 发布