#include <iostream>
using namespace std;
///
//树节点
typedef struct TreeNode //定义树节点
{
char data; //树节点数据域
struct TreeNode *lp, *rp;
}treenode;
///
//队列
typedef struct Line_Up //定义队中节点
{
treenode *point; //队列节点数据域
struct Line_Up * lpp, *rpp;
}lineup;
lineup *Create_line(); //创建控制节点,返回指向控制节点指针
lineup *In_line(lineup *p,treenode *ppoint); //入队
lineup *Out_line(lineup *p); //出队
lineup *Clean_line(lineup *p); //清空队
treenode *GetFL(lineup *p); //取队首元素
bool Isempty_line(lineup *p); //队空判断
treenode *CreateTree(treenode *head1,lineup *linec); //创建二叉树,返回根节点指针
lineup *FrootView(treenode *headTreeView, lineup *lpv); //先根遍历
lineup *MrootView(treenode *headTreeView, lineup *lpv); //中根遍历
lineup *LrootView(treenode *headTreeView, lineup *lpv); //后根遍历
void printViewResult(lineup *lpv); //打印遍历二叉树结果
lineup *LineToStackPop(lineup *lpv); //队列改成栈使用
int main()
{
treenode *head=NULL; //全局性指向树根操作节点的指针
lineup *lineC = Create_line(); //全局性的指向队操作手节点的指针
head = CreateTree(head,lineC); //开始创建二叉树
lineC=FrootView(head,lineC); //前序遍历二叉树
cout << "前序遍历结果是:";
printViewResult(lineC);
lineC=MrootView(head,lineC); //中序遍历二叉树
cout << "中序遍历结果是:";
printViewResult(lineC);
lineC=LrootView(head,lineC); //后序遍历二叉树
cout << "后序遍历结果是:";
printViewResult(lineC);
lineC=Clean_line(lineC); //清空队,回收空间
free(lineC);
return 0;
}
//先根遍历
lineup *FrootView(treenode *headTreeView, lineup *lpv)
{
if (headTreeView == NULL){ return NULL; } //指根节点为空,二叉树为空
bool lor = false; //访问左子树还是右子树控制变量
treenode *p = headTreeView; //指根节点指针不能变
lineup *lpvv = Create_line();
lpv = In_line(lpv, p); //首先遍历了根节点
lpvv = In_line(lpvv, p); //辅助遍历队列
while ((lpvv->rpp)!=NULL) //"栈"不为空
{
if (p == NULL)
{
lpvv = LineToStackPop(lpvv);
if ((lpvv->rpp)!= NULL)
{
p = (lpvv->rpp)->point; //将辅助队列改成栈使用
}
}
if (p == NULL){ break; } //p从栈取不到节点,遍历结束
while ((p->lp) != NULL&&lor == false)
{
lpv = In_line(lpv, p->lp); //访问到左子节点
lpvv = In_line(lpvv, p->lp); //左子节点进栈
p = p->lp; //p移向其左子节点
} //持续访问左子节点
lor = true;
if (p->rp != NULL&&lor==true) //如果右子节点存在
{
lpvv = LineToStackPop(lpvv);
lpv = In_line(lpv, p->rp); //访问到右子节点
lpvv = In_line(lpvv, p->rp); //右子节点进栈
p = p->rp; //p移向其右子节点
lor = false; //下一步回到持续访问左子节点
}
else
{
p = NULL;
}
}
free(lpvv);//释放掉辅助栈操作节点的空间
return lpv;
}
//中根遍历
lineup *MrootView(treenode *headTreeView, lineup *lpv)
{
if (headTreeView == NULL){ return NULL; } //指根节点为空,二叉树为空
bool lor = false; //访问左子树还是右子树控制变量
treenode *p = headTreeView; //遍历游走指针
lineup *lpvv = Create_line();
lpvv = In_line(lpvv, p); //辅助遍历"栈"
while ((lpvv->rpp) != NULL) //"栈"不为空
{
if (p == NULL)
{
lpvv = LineToStackPop(lpvv);
if ((lpvv->rpp) != NULL)
{
p = (lpvv->rpp)->point; //将辅助队列改成栈使用
}
}
if (p == NULL){ break; } //p从栈取不到节点,遍历结束
while ((p->lp) != NULL&&lor == false)
{
lpvv = In_line(lpvv, p->lp); //左子节点进栈
p = p->lp; //p移向其左子节点
} //持续访问左子节点
lor = true;
if (p->rp != NULL&&lor == true) //如果右子节点存在
{
lpv = In_line(lpv, p); //
p = p->rp; //p移向其右子节点
lpvv = LineToStackPop(lpvv); //pop掉根
lpvv = In_line(lpvv, p); //右子节点进栈
lor = false; //下一步回到持续访问左子节点
}
else
{
lpv = In_line(lpv, p); //访问到这个根(包括左右子树已经访问或者左右子树为空)
p = NULL;
}
}
free(lpvv);//释放掉辅助栈操作节点的空间
return lpv;
}
//后根遍历
lineup *LrootView(treenode *headTreeView, lineup *lpv)
{
if (headTreeView == NULL){ return NULL; } //指根节点为空,二叉树为空
bool lor = false; //访问左子树还是右子树控制变量
bool CanR = true;
treenode *p = headTreeView; //遍历游走指针
lineup *lpvv = Create_line();
lpvv = In_line(lpvv, p); //辅助遍历"栈"
while ((lpvv->rpp) != NULL) //"栈"不为空
{
if (p == NULL)
{
if ((lpvv->rpp) != NULL)
{
p = (lpvv->rpp)->point; //将辅助队列改成栈使用
}
}
if (p == NULL){ break; } //p从栈取不到节点,遍历结束
while ((p->lp) != NULL&&lor == false)
{
lpvv = In_line(lpvv, p->lp); //左子节点进栈
p = p->lp; //p移向其左子节点
} //持续访问左子节点
lor = true;
if (p->rp != NULL&&lor == true&&CanR==true) //如果右子节点存在
{
lpvv = In_line(lpvv, p->rp); //右子节点进栈
p = p->rp; //p移向其右子节点
lor = false; //下一步回到持续访问左子节点
}
else
{
//lpvv满足两个节点以上//情况:是左子根结束,pop一次,允许寻右
if ((((lpvv->rpp)->lpp)->point)->lp == p)
{
lpv = In_line(lpv, p);
lpvv = LineToStackPop(lpvv);
CanR = true;
p = NULL;
} //lpvv满足三个节点//情况:是左子根的右结束
else if ((lpvv->rpp)->lpp->lpp!=NULL&&(((lpvv->rpp)->lpp)->point)->rp == p && ((((lpvv->rpp)->lpp)->lpp)->point)->lp == ((lpvv->rpp)->lpp)->point) //是左子根的右子结束,pop两次,允许寻右
{
lpv = In_line(lpv, p);
lpvv = LineToStackPop(lpvv);
lpv = In_line(lpv, (lpvv->rpp)->point);
lpvv = LineToStackPop(lpvv);
CanR = true;
p = NULL;
}
else //否则,为满足右子根的右子
{
if ((lpvv->rpp)->lpp->lpp == NULL && (((lpvv->rpp)->lpp)->point)->rp == p)
{
lpv = In_line(lpv, p);
lpvv = LineToStackPop(lpvv);
lpv = In_line(lpv, (lpvv->rpp)->point);
lpvv = LineToStackPop(lpvv);
break;
}
while ((((lpvv->rpp)->lpp)->point)->rp == p &&(lpvv->rpp)!=NULL)
{
if ((lpvv->rpp)->lpp == lpvv->lpp)//如果lpvv只剩两个元素
{
lpv = In_line(lpv, p);
lpvv = LineToStackPop(lpvv);
lpv = In_line(lpv, (lpvv->rpp)->point);
lpvv = LineToStackPop(lpvv);
break;
}
if (((((lpvv->rpp)->lpp)->lpp)->point)->rp == ((lpvv->rpp)->lpp)->point)//是右的右的右
{
lpv = In_line(lpv, p);
lpvv = LineToStackPop(lpvv);
lpv = In_line(lpv, (lpvv->rpp)->point);
lpvv = LineToStackPop(lpvv);
p = (lpvv->rpp)->point;
if (lpvv->rpp->lpp!=NULL&&((lpvv->rpp)->lpp)->point->lp == p)//回到左子根结束了吗
{
lpv = In_line(lpv, p);
lpvv = LineToStackPop(lpvv);
CanR = true;
p = NULL;
break;
}
else if (lpvv->lpp == lpvv->rpp)//只剩一个元素了吗
{
lpv = In_line(lpv, p);
lpvv = LineToStackPop(lpvv);
break;
}
}
}
}
}
}
free(lpvv);//释放掉辅助栈操作节点的空间
return lpv;
}
//打印遍历结果
void printViewResult(lineup *lpv)
{
if (lpv == NULL)
{
cout << "当前二叉树为空!无遍历结果。" << endl;
return;
}
while (lpv->lpp != NULL)
{
cout << ((lpv->lpp)->point)->data << " ";
lpv = Out_line(lpv);
}
cout << endl;
}
//队列改成栈使用
lineup *LineToStackPop(lineup *lpv)
{
if (lpv->lpp == lpv->rpp)//只有一个元素在队
{
lineup *pfree = lpv->rpp;
lpv->lpp = lpv->rpp = NULL;
free(pfree);
return lpv;
}
lineup *pfree = lpv->rpp;
lpv->rpp = (lpv->rpp)->lpp;
(lpv->rpp)->rpp = NULL;
pfree->lpp = NULL;
free(pfree);
return lpv;
}
//创建二叉树kernel函数(输入要合法:比如e..#合法,e..fjfj#不合法层次构造二叉树)
treenode *CreateTree(treenode *head1,lineup *linec)
{
char ch;
int flag=1;
bool hnode = true;
treenode *ptemp = NULL;
cout << "请输入符合实际层次构造二叉树的逻辑数据,如不能“e..dh#”这样输入!" << endl;
while (cin >> ch&&ch != '#')
{
if (hnode == true)//如果输入的是根节点,则把head1附上值
{
head1 = (treenode *)malloc(sizeof(treenode));//创建根节点空间
head1->data = ch;
head1->lp = NULL;
head1->rp = NULL;
linec = In_line(linec, head1);//将指向根节点的指针加到队列中
hnode = false;
continue;
}
if (flag == 1)//为1时弹出一节点的指针并为创建左子树准备
{
ptemp = GetFL(linec);//复制队首元素的treenode*指针值
}
if (flag == 1)//创建的是左子树
{
if (ch != '.')//当输入左子树不为空时
{
ptemp->lp = (treenode *)malloc(sizeof(treenode));
(ptemp->lp)->data = ch;
(ptemp->lp)->lp = NULL;
(ptemp->lp)->rp = NULL;
linec = In_line(linec,ptemp->lp);
}
else
{
ptemp->lp = NULL;
}
flag = 2;
}
else
{
if (ch != '.')//当输入右子树不为空时
{
ptemp->rp = (treenode *)malloc(sizeof(treenode));
(ptemp->rp)->data = ch;
(ptemp->rp)->lp = NULL;
(ptemp->rp)->rp = NULL;
linec = In_line(linec, ptemp->rp);
linec = Out_line(linec);//创建一个节点的左右子树结束
}
else
{
ptemp->rp = NULL;
linec = Out_line(linec);//创建一个节点的左右子树结束
}
flag = 1;
}
}
linec = Clean_line(linec);//清空辅助队列
return head1;
}
///以下全为队操作
//创建队操作节点
lineup *Create_line()
{
lineup *s = NULL;
s = (lineup *)malloc(sizeof(lineup)); //创建队操作节点
s->lpp = NULL;
s->point = NULL;
s->rpp = NULL;
return s;
}
//入队(rp队尾进队)
lineup *In_line(lineup *p, treenode *ppoint)
{
lineup *s = NULL;
if (p->rpp == NULL)
{
s = (lineup *)malloc(sizeof(lineup)); //节点空间
s->lpp = NULL;
s->point = ppoint;
s->rpp = NULL;
p->lpp = p->rpp = s;
}
else
{
s = (lineup *)malloc(sizeof(lineup));
s->lpp = p->rpp;
s->point = ppoint;
(p->rpp)->rpp = s;
s->rpp = NULL;
p->rpp = s;
}
return p;
}
//取队首元素数据值
treenode *GetFL(lineup *p)
{
treenode *pt = NULL;
if (Isempty_line(p)) //判空
{
return NULL;
}
pt = (p->lpp)->point;
return pt;
}
//出队(lp队首出队)
lineup *Out_line(lineup *p)
{
lineup *pfree = NULL;
if (Isempty_line(p)) //判空
{
return p;
}
if (p->lpp == p->rpp) //一个元素
{
pfree = p->rpp;
p->lpp = p->rpp = NULL;
free(pfree);
return p;
}
pfree = p->lpp; //多于一个元素
p->lpp = (p->lpp)->rpp;
(p->lpp)->lpp = NULL;
pfree->rpp = NULL;
free(pfree);
return p;
}
//清空队
lineup *Clean_line(lineup *p)
{
while (p->lpp != NULL)
{
Out_line(p);
}
return p;
}
//判队空
bool Isempty_line(lineup *p)
{
if (p->lpp == NULL)
{
return true;
}
return false;
}