数据结构与算法-实验4-实现二叉树的前、中、后序遍历

#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;

}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值