//严蔚敏《数据结构》
//二叉链表: 递归、非递归(非递归用栈)先序、中序、后序遍历(非递归后序遍历麻烦点,需要用到flag标志)
//以及层序遍历(层序用队列),以及建立在遍历上的一些操作
//思考:对二叉链表的操作几乎都是建立在遍历的基础上(所以说遍历很重要!!)
//若为简单的输出遍历,递归容易实现,但效率较低;
//若不是简单的输出,是建立在遍历基础上的一些操作,比如 寻找双亲,非递归容易实现
//5-7行是基于现在水平的我的理解,可能不太对,我会回来的
//自学中,加油!!!
#include<iostream>
using namespace std;
#define TElemType double
typedef struct BiTNode
{
TElemType data;
struct BiTNode* lchild,* rchild;
int flag;//标志变量 标志非递归的后序遍历
}BiTNode,* BiTree;
bool Creat_BiTree(BiTree& T)//递归先序创建并输入
{
TElemType num;
if(cin>>num){//此处应用if而不是while循环 这是在用递归,就不用while循环了
T=new BiTNode;
if(!T)
return false;
T->data=num;
Creat_BiTree(T->lchild);
Creat_BiTree(T->rchild);
}
if(!cin)
T=nullptr;
if(!cin){
cin.clear();
while(cin.get()!='\n')
continue;
}
return true;
}
void PreOrder_Bitree(BiTree T)//递归先序遍历
{
if(T){
cout<<T->data<<endl;
PreOrder_Bitree(T->lchild);
PreOrder_Bitree(T->rchild);
}
}
void InOrder_bitree(BiTree T)//递归中序遍历
{
if(T){
InOrder_bitree(T->lchild);
cout<<T->data<<endl;
InOrder_bitree(T->rchild);
}
}
void PostOrder_BiTree(BiTree T)//递归后序遍历
{
if(T){
PostOrder_BiTree(T->lchild);
PostOrder_BiTree(T->rchild);
cout<<T->data<<endl;
}
}
//构造的队列为层序遍历服务
#define QElemType BiTree
typedef struct QNode
{
QElemType data;
struct QNode* next;
}QNode,* QPtr;
typedef struct
{
QPtr head,tail;
int length;
}QueueList;
bool Init_Queue(QueueList& Q)
{
Q.head=new QNode;
if(!Q.head)
return false;
Q.head->next=nullptr;
Q.tail=Q.head;
Q.length=0;
return true;
}
bool IsEmpty_Queue(QueueList Q)
{
if(Q.length)
return false;
return true;
}
bool Push_Queue(QueueList& Q,QElemType e)
{
QPtr p=new QNode;
if(!p)
return false;
p->data=e;
p->next=Q.tail->next;
Q.tail->next=p;
Q.tail=p;
Q.length++;
return true;
}
bool Pop_Queue(QueueList& Q,QElemType& e)
{
if(IsEmpty_Queue(Q))
return false;
QPtr p=Q.head->next;
e=p->data;
Q.head->next=p->next;
if(p==Q.tail)//若头指针后面就是尾指针,需改动Q.tail的值
Q.tail=Q.head;
delete p;
Q.length--;//bug2:忘记该行代码
return true;
}
void LevelOrder_BiTree(BiTree T)//利用队列层序遍历
{
QueueList Q;
Init_Queue(Q);
Push_Queue(Q,T);
while(!IsEmpty_Queue(Q)){
BiTree bt;
Pop_Queue(Q,bt);
cout<<bt->data<<endl;
if(bt->lchild)
Push_Queue(Q,bt->lchild);
if(bt->rchild)
Push_Queue(Q,bt->rchild);
}
}
//构造的栈为非递归 先序、中序、后序遍历服务
#define SElemType BiTree
typedef struct SNode
{
SElemType data;
struct SNode* next,* prior;
}SNode,* SLink;
typedef struct
{
SLink head,tail;
int length;
}LinkStack;
bool Init_Stack(LinkStack& S)
{
S.head=new SNode;
if(!S.head)
return false;
S.head->next=S.head->prior=nullptr;
S.tail=S.head;
S.length=0;
return true;
}
bool IsEmpty_Stack(LinkStack S)
{
if(!S.length)
return true;
return false;
}
SElemType GetTop_Stack(LinkStack S)
{
return S.tail->data;
}
bool Push_Stack(LinkStack& S,SElemType e)
{
SLink p=new SNode;
if(!p)
return false;
p->data=e;
p->next=S.tail->next;
S.tail->next=p;
p->prior=S.tail;
S.tail=p;
S.length++;
return true;
}
bool Pop_Stack(LinkStack& S,SElemType& e)
{
SLink p=S.tail;
e=S.tail->data;
S.tail=S.tail->prior;
S.tail->next=p->next;
delete p;
S.length--;
return true;
}
void PreOrder_Bitree1(BiTree bt)//非递归先序遍历 使用栈
{
BiTree T=bt;
LinkStack S;
Init_Stack(S);
while(T||!IsEmpty_Stack(S)){
while(T){
cout<<T->data<<endl;
Push_Stack(S,T);
T=T->lchild;
}
if(!IsEmpty_Stack(S)){
Pop_Stack(S,T);
T=T->rchild;
}
}
}
void InOrder_bitree1(BiTree bt)//非递归中序遍历 使用栈
{
BiTree T=bt;
LinkStack S;
Init_Stack(S);
while(T||!IsEmpty_Stack(S)){
while(T){//T一直向左遍历,并将沿途结点压入栈
Push_Stack(S,T);
T=T->lchild;
}
if(!IsEmpty_Stack(S)){//从栈中得到双亲
Pop_Stack(S,T);
cout<<T->data<<endl;//打印结点数据
T=T->rchild;
}
}
}
void PostOrder_BiTree1(BiTree bt)//非递归后序遍历 使用栈
{
BiTree T=bt;
LinkStack S;
Init_Stack(S);
while(T||!IsEmpty_Stack(S)){
while(T){//T一直向左遍历,并将沿途结点压入栈
T->flag=0;//在入栈之前将T->flag置为0,不然在main调用两次PostOrder_BiTree1,第二个会发生错误
Push_Stack(S,T);
T=T->lchild;
}
while(!IsEmpty_Stack(S)&&GetTop_Stack(S)->flag==1){
Pop_Stack(S,T);
cout<<T->data<<endl;//打印结点数据
}
if(!IsEmpty_Stack(S)){//若flag不为1,则不输出,然后继续向右子树遍历
T=GetTop_Stack(S);
T->flag=1;
T=T->rchild;
}
else//左->右->根 当栈空时,遍历已经全部完成
break;
}
}
//以下的操作大多建立在遍历的基础之上 根据不同的要求进行不同的遍历
BiTree Clear_BiTree(BiTree& T)//清空二叉链表(选择递归后序遍历,好处:左右子树操作完后,才进行根的删除)
{
BiTree bt=T;
if(bt){
bt->lchild=Clear_BiTree(bt->lchild);
bt->rchild=Clear_BiTree(bt->rchild);
delete bt;
return nullptr;
}
}
bool IsEmpty_BiTree(BiTree T)//二叉链表为空,返回true;否则返回false
{
if(!T)
return true;
return false;
}
int Depth_BiTree(BiTree T)//返回二叉树的深度(采用递归后序遍历,先找Max(H左,H右),然后将其+1
{
if(T){
int Depth1=Depth_BiTree(T->lchild);
int Depth2=Depth_BiTree(T->rchild);
return (Depth1>Depth2?Depth1:Depth2)+1;
}
return 0;
}
BiTree Root(BiTree T)//返回指向根的指针
{
return T;
}
/*
bool Value_BiTree(BiTree T,BiTree p)//输出p指向树结点的数据(这个三个次序都可以,在此我选择先序了)
{
BiTree bt=T;
if(bt){
if(p==bt){
cout<<bt->data;
}
Value_BiTree(bt->lchild,p);
Value_BiTree(bt->rchild,p);
}
return true;
}
*/
//291-304行代码 输出选择递归,若函数类型为返回,递归不太好完成,在此选择非递归先序
TElemType Value_BiTree(BiTree T,BiTree p)
{
BiTree bt=T;
LinkStack S;
Init_Stack(S);
while(bt||!IsEmpty_Stack(S)){//bug1: 将||写为&&
while(bt){
if(bt==p)
return bt->data;
Push_Stack(S,bt);
bt=bt->lchild;
}
if(!IsEmpty_Stack(S)){
Pop_Stack(S,bt);//此处应为Pop_Stack(S,bt) 而不是Pop_Stack(S,e)
bt=bt->rchild;
}
}
}
bool Assign_BiTree(BiTree& T,BiTree p,TElemType e)//将数据e赋给p指向树节点的数据域(递归先序遍历)
{
//BiTree bt=T;//递归不要这一行,非递归需要
if(T){
if(T==p){
T->data=e;
}
Assign_BiTree(T->lchild,p,e);
Assign_BiTree(T->rchild,p,e);
}
return true;
}
bool Assign_BiTree1(BiTree& T,BiTree p,TElemType e)//非递归先序遍历
{
BiTree bt=T;
LinkStack S;
Init_Stack(S);
while(bt||!IsEmpty_Stack(S)){
while(bt){
if(p==bt){
bt->data=e;
}
Push_Stack(S,bt);
bt=bt->lchild;
}
if(!IsEmpty_Stack(S)){
Pop_Stack(S,bt);
bt=bt->rchild;
}
}
return true;
}
//输出 选择递归较容易,非输出 递归、非递归均可,看情况使用。若函数类型为返回,递归不太好完成,在此选择非递归先序
void Parent_BiTree(BiTree T,BiTree p)//输出树指针p的双亲(选择递归先序遍历) 递归输出
{
if(T){
if(T->lchild==p||T->rchild==p)
cout<<T->data<<endl;
Parent_BiTree(T->lchild,p);
Parent_BiTree(T->rchild,p);
}
}
BiTree Parent_BiTree1(BiTree T,BiTree p)//非递归返回 先序遍历
{
BiTree bt=T;
LinkStack S;
Init_Stack(S);
if(T==p)//p为总根,无双亲
return nullptr;
while(bt||!IsEmpty_Stack(S)){
while(bt){
if(bt->lchild==p||bt->rchild==p)
return bt;
Push_Stack(S,bt);
bt=bt->lchild;
}
if(!IsEmpty_Stack(S)){
Pop_Stack(S,bt);
bt=bt->rchild;
}
}
return nullptr;
}
//二叉链表找双亲、兄弟需要从头开始遍历 找孩子不需要遍历
BiTree LeftChild_BiTree(BiTree T,BiTree p)//返回树指针p的左孩子,若无,返回nullptr
{
return p->lchild;
}
BiTree RightChild_BiTree(BiTree T,BiTree p)//返回树指针p的右孩子,若无,返回nullptr
{
return p->rchild;
}
BiTree LeftSibling(BiTree T,BiTree p)//返回树指针p的左兄弟指针,若无,返回nullptr
{
return Parent_BiTree1(T,p)->lchild;
}
BiTree RightSibling(BiTree T,BiTree p)//返回树指针p的右兄弟指针,若无,返回nullptr
{
return Parent_BiTree1(T,p)->rchild;
}
bool InsertChild_BiTree(BiTree& T,BiTree p,int LR,BiTree e)//LR=0:插入数据e到p指针的左孩子结点
//LR=1:插入数据e到p指针的右孩子结点
{
if(LR==0){
if(!p->lchild){
p->lchild=e;
return true;
}
return false;
}
else{
if(!p->rchild){
p->rchild=e;
return true;
}
return false;
}
}
bool DeleteChild_BiTree(BiTree& T,BiTree p,int LR,BiTree e)//LR=0:删除p指针的子树(采用非递归后序遍历 ,最后删除根)
//LR=1:删除p指针的子树
{
BiTree bp=p;
if(LR==0){
bp=p->lchild;
p->lchild=nullptr;
}
else{
bp=p->rchild;
p->rchild=nullptr;
}
LinkStack S;
Init_Stack(S);
while(bp&&!IsEmpty_Stack(S)){
while(bp){
bp->flag=0;//入栈前设置bp->flag=0
Push_Stack(S,bp);
bp=bp->lchild;
}
while(!IsEmpty_Stack(S)&&GetTop_Stack(S)->flag==1){
Pop_Stack(S,bp);
delete bp;
}
if(!IsEmpty_Stack(S)){
bp=GetTop_Stack(S);
bp->flag=1;
bp=bp->rchild;
}
else
break;
}
return true;
}
//while循环可以替代递归
int main()
{
BiTree T;
Creat_BiTree(T);
cout<<"非递归后序遍历\n";
PostOrder_BiTree1(T);//非递归 记得将flag 重置为0
/*T=Clear_BiTree(T);
cout<<"非递归后序遍历\n";//Clear_BiTree的测试代码
PostOrder_BiTree1(T);*/
/*cout<<"深度:"<<Depth_BiTree(T)<<endl;
cout<<"非递归后序遍历\n";
PostOrder_BiTree1(T);
cout<<"值:"<<Value_BiTree(T,T->lchild->rchild->lchild)<<endl;
Assign_BiTree1(T,T->lchild->rchild,9.9);
cout<<"非递归后序遍历\n";
PostOrder_BiTree1(T);
Assign_BiTree(T,T->lchild->rchild,11.1);
cout<<"非递归后序遍历\n";
PostOrder_BiTree1(T);*///Clear_BiTree Depth_BiTree Assign_BiTree操作的测试代码
/*cout<<"====="<<endl;
Parent_BiTree(T,T->lchild->rchild);
cout<<"====="<<endl;
cout<<Parent_BiTree1(T,T->lchild->rchild->lchild)->data<<endl;
cout<<"====="<<endl;
cout<<LeftChild_BiTree(T,T->lchild->rchild)->data<<endl;
cout<<"====="<<endl;
cout<<RightChild_BiTree(T,T->lchild->rchild)<<endl;
cout<<"===="<<endl;
cout<<LeftSibling(T,T->lchild->rchild)->data<<endl;
cout<<"===="<<endl;
cout<<RightSibling(T,T->lchild)->data;*///Parent、LeftChild、RightChild、LeftSibling、RightSibling
//操作的测试代码
//下面为测试 InsertChild、deleteChild操作的代码
BiTree T2;
Creat_BiTree(T2);
cout<<"非递归后序遍历\n";
PostOrder_BiTree1(T2);
InsertChild_BiTree(T,T->lchild->lchild,0,T2);
cout<<"非递归后序遍历\n";
PostOrder_BiTree1(T);
DeleteChild_BiTree(T,T->lchild->lchild,0,T2);
cout<<"非递归后序遍历\n";
PostOrder_BiTree1(T);
return 0;
}
main函数的测试图如下所示
1.1
2.2
4.4
@
6.6
@
@
5.5
7.7
@
@
@
3.3
@
@
非递归后序遍历
6.6
4.4
7.7
5.5
2.2
3.3
1.1
8.8
9.9
@
11.1
@
@
12.2
@
13.3
@
@
非递归后序遍历
11.1
9.9
13.3
12.2
8.8
非递归后序遍历
11.1
9.9
13.3
12.2
8.8
6.6
4.4
7.7
5.5
2.2
3.3
1.1
非递归后序遍历
6.6
4.4
7.7
5.5
2.2
3.3
1.1
Process returned 0 (0x0) execution time : 16.433 s
Press any key to continue.