二叉树之三
#include<iostream>
#include<stack>
#include <queue>
using namespace std;
struct BiNode
{
char data;
BiNode *LChild;
BiNode *RChild;
int ltag;int rtag;
};
void Creat(BiNode *root) //先序建立
{
char ch;
cin>>ch;
if(ch=='#'){root->data=ch;root->ltag=root->rtag=0;} //#代表NULL
else
{
root->data=ch;root->ltag=root->rtag=0;
root->LChild=new BiNode;
Creat(root->LChild); //LChild为指针类型,所以需要用*
root->RChild=new BiNode;
Creat(root->RChild);
}
}
void Destroy(BiNode& root)
{
if(root.data!='#')
{Destroy(*root.LChild);
Destroy(*root.RChild);
delete &root;}
}
bool Empty(BiNode& root)
{
if(&root==NULL)
return true;
else return false;
}
void PreOrder(BiNode& root) //先根遍历
{
if (root.data!='#')
{
cout<<root.data;
PreOrder(*root.LChild);
PreOrder(*root.RChild);
}
}
void NorecPreOrder(BiNode& root) //非递归先根遍历
{
if(root.data!='#')
{
stack<BiNode*> s;
s.push(&root);
while(!s.empty())
{
BiNode *q=s.top();s.pop();
cout<<q->data<<' ';
if(q->RChild->data!='#')
s.push(q->RChild);
if(q->LChild->data!='#')
s.push(q->LChild);
}
}
}
void InOrder(BiNode& root) //中根遍历
{
if(root.data!='#')
{ InOrder(*root.LChild);
cout<<root.data;
InOrder(*root.RChild);
}
}
void NorecInOrder(BiNode& root) //非递归中根遍历
{
if(root.data!='#')
{
stack<BiNode*> s;
BiNode *q=&root;int em=1;
do{
while(q->data!='#')
{s.push(q);q=q->LChild;}
if(s.empty())em=0;
else {
q=s.top();s.pop();
cout<<q->data<<' ';
q=q->RChild;
}
}while(em);
}
}
void PostOrder(BiNode& root) //后根遍历
{
if(root.data!='#')
{
PostOrder(*root.LChild);
PostOrder(*root.RChild);
cout<<root.data;
}
}
void NorecPostOrder(BiNode& root) //非递归后根遍历
{
if(root.data!='#')
{
stack<BiNode*>s;stack<int>s2;
int em=1;
BiNode temp=root; BiNode *p=&temp;
//为什么要声明另一个BiNode temp呢,目的是使得p所指向的地址跟root的地址不同,最终使得root的属性不改变
//temp跟root的地址不同
do
{
while(p->data!='#'){s.push(p);s2.push(1);p=p->LChild;}
//??????????????root.LChild居然改变了
//cout<<"root.LChild->data"<<root.LChild->data<<endl;
if(s.empty())em=0;
else
{
if(s2.top()==1)
{p=s.top();s2.pop();s2.push(2);p=p->RChild;}
else //==2的情况
{p=s.top();s.pop();s2.pop();cout<<p->data<<' ';p->data='#';}
}
} while (em);
}
}
//后根遍历,最后一次p=s.top();
//结果是p=root;
//如果不另外开个空间,找个变量来储存root
//则这二者指向相同的空间。p->data='#'即相当于root->data='#'
//可以测试:添加语句 if(root.data=='#'&&p==&root)cout<<"NorecPostOrder :"<<"my god,root.data=='#'&&p==&root"<<endl;
//为什么NorecInOrder(BiNode& root)函数不会发生这样的问题呢,代码如下:
/*void NorecInOrder(BiNode& root) //非递归中根遍历
{
if(root.data!='#')
{
stack<BiNode*> s;
BiNode *q=&root;int em=1;
do{
while(q->data!='#')
{s.push(q);q=q->LChild;}
if(s.empty())em=0;
else {
q=s.top();s.pop();
cout<<q->data<<' ';
q=q->RChild;
}
}while(em);
if(q==&root)cout<<"NoreInOrder: q==&root"<<root.data<<endl;
}
}
*/
//虽然也有声明BiNode *q=&root;但随后q=q->LChild;。。。q的地址已经改变了,和root已经没关系,
//关键是最终并不像非递归后根遍历那样,要再次使得p=root;所以p的改变不会影响到root
void WidthFirst(BiNode& root) //宽度优先,按层遍历
{
if(root.data!='#')
{
BiNode *p=&root;
queue<BiNode*> q;
q.push(p);
while(!q.empty())
{
p=q.front();q.pop();
cout<<p->data<<' ';
if(p->LChild->data!='#')q.push(p->LChild);
if(p->RChild->data!='#')q.push(p->RChild);
}
}
}
void CountNode(BiNode& root,int& num) //num要用引用类型
{
if(root.data!='#')
{
CountNode(*root.LChild,num);
num++;
CountNode(*root.RChild,num);
}
}
void CountLeaf(BiNode& root,int& num2)
{
if(root.data!='#')
{
if(root.LChild->data=='#'&&root.RChild->data=='#')
num2++;
if(root.LChild->data!='#')
CountLeaf(*root.LChild,num2);
if(root.RChild->data!='#')
CountLeaf(*root.RChild,num2);
}
}
int CountDepth(BiNode& root)
{
if(root.data!='#')
{
if(root.LChild->data=='#'&&root.RChild->data=='#')return 1;
return CountDepth(*root.LChild)>CountDepth(*root.RChild)?
CountDepth(*root.LChild)+1:CountDepth(*root.RChild)+1;
}
else return 0;
}
BiNode* CopyTree(BiNode& root)
{
if(root.data=='#'){return &root;}
else
{
BiNode *q;
q=new BiNode;
q->data=root.data;
q->LChild=CopyTree(*root.LChild);
q->RChild=CopyTree(*root.RChild);
return q;
}
}
void ThreadPreOrder(BiNode *root ,BiNode* &pre) //先根线索化二叉树
{
if(root->data!='#')
{
//cout<<"root.data "<<root->data<<endl;
//cout<<"pre.data "<<pre->data<<endl;
if(root->LChild->data=='#')
{
root->LChild=pre;/*cout<<"root.LChild=⪯ root.LChild->data: "<<root->LChild->data<<endl;*/
root->ltag=1;
}
if(pre->data!='#'&&pre->RChild->data=='#')
{
pre->RChild=root;/*cout<<"pre.RChild=&proot; pre.RChild->data: "<<pre->RChild->data<<endl;*/
pre->rtag=1;
}
pre=root;
if(root->ltag==0)ThreadPreOrder(root->LChild,pre);
ThreadPreOrder(root->RChild,pre);
}
}
void ThreadInOrder(BiNode &root,BiNode* &pre) //中根线索化二叉树
{
if(root.data!='#')
{
ThreadPreOrder(*root.LChild,pre);
cout<<root.data<<' ';
if(root.LChild->data=='#')
{
root.LChild=pre;cout<<"void ThreadInOrder(BiNode& root,BiNode& pre) "<<root.LChild->data<<endl;
root.ltag=1;
}
if(pre->data!='#'&&pre->RChild->data=='#')
{
pre->RChild=&root;
pre->rtag=1;cout<<"void ThreadInOrder(BiNode& root,BiNode& pre) "<<root.RChild->data<<endl;
}
pre=&root;
ThreadPreOrder(*root.RChild,pre);
}
}
BiNode* inpre(BiNode *q)
{
BiNode *p, *r;
if(q->ltag==1) p=q->LChild;
else {
r=q->LChild;
while(r->rtag!=1)r=r->RChild;
p=r;
}
return p;
}
void main()
{
BiNode *rt;rt=new BiNode;
Creat(rt);
WidthFirst(*rt);cout<<endl;
int n=0;CountNode(*rt,n);cout<<n<<endl; //统计结点,叶子,和深度
n=0;CountLeaf(*rt,n);cout<<n<<endl;
cout<<CountDepth(*rt)<<endl;
PreOrder(*rt);cout<<endl;
NorecPreOrder(*rt);cout<<endl;
InOrder(*rt);cout<<endl;
NorecInOrder(*rt);cout<<endl;
PostOrder(*rt);cout<<endl;
NorecPostOrder(*rt);cout<<endl;
//BiNode *cpy;cpy=new BiNode;
//cpy=CopyTree(*rt); //之后cpy相当于rt
BiNode *pre;pre=new BiNode;
pre->data='#';
//ThreadPreOrder(rt,pre);
//cout<<rt->LChild->data<<endl;
cout<<rt->LChild->LChild->data<<endl;
ThreadInOrder(*rt,pre);cout<<endl;
cout<<rt->RChild->ltag<<endl;
cout<<rt->RChild->LChild->data<<endl;
}
//sample input: ab#d##c## 先序建立二叉树