二叉树的部分操作

来源:互联网 发布:路由器域名重定向设置 编辑:程序博客网 时间:2024/04/30 04:29

以下代码包括二叉树的创建、前中后序遍历(递归)、非递归中序遍历(栈实现)、层序遍历(队列实现)和中序线索化遍历。

  1. main
#include<stdio.h>#include<stdlib.h>#include<iostream>#include"Tree.h"#include"Queue.h"#include"Stack.h"#include"Tree.h"#include"Marco.h"using namespace std;BiThrTree pre;//全局变量,表示刚刚访问过的结点int main(){    BiThrTree  T = NULL;    printf("二叉树测试程序开始:\n");    printf("1.创建非空二叉树:\n");    CreateBiThrTree(T);    printf("\n2.前序遍历二叉树:\n");    PreOrderTraverse(T);    printf("\n3.中序遍历二叉树:\n");    InOrderTraverse(T);    printf("\n4.后序遍历二叉树:\n");    PostOrderTraverse(T);    printf("\n5.非递归中序遍历二叉树(用栈实现):\n");    NoRecursionInTraverse(T);    printf("\n6.层序遍历二叉树(用队列实现):\n");    LevelOrderTraverse(T);    printf("\n7.中序线索化遍历二叉树:\n");    BiThrTree Thrt;    InOrderThreading( Thrt,T );    InOrderAfterThreading(Thrt);    cout << "\n二叉树测试程序结束!" << endl;    return OK;}

2.Tree.c

#include<stdio.h>#include<stdlib.h>#include<iostream>#include"Tree.h"#include"Stack.h"#include"Queue.h"#include"Marco.h"using namespace std;extern BiThrTree pre;/********************对二叉树的操作********************///1.创建二叉树int CreateBiThrTree(BiThrTree &T){    char data;    scanf("%c", &data);    if (' ' == data)    {        T = NULL;                                       //如果字符为空,则根节点为空    }    else    {        if (!(T = (BiThrTree)malloc(sizeof(BiThrNode))))//否则建立根节点        {            printf("出错:创建结点时分配空间错误!");            exit(OVERFLOW);        }        T->data = data; //根节点数据域        T->LTag = Link;        T->RTag = Link;        CreateBiThrTree(T->lchild);                 //构造左子树        CreateBiThrTree(T->rchild);                 //构造右子树    }    return OK;}//2.前序遍历void PreOrderTraverse(BiThrTree T){    if (T)    {        printf("%c", T->data);        PreOrderTraverse(T->lchild);        PreOrderTraverse(T->rchild);    }}//3.中序遍历void InOrderTraverse(BiThrTree T){    if (T)    {        InOrderTraverse(T->lchild);        printf("%c", T->data);        InOrderTraverse(T->rchild);    }}//4.后序遍历void PostOrderTraverse(BiThrTree T){    if (T)    {        PostOrderTraverse(T->lchild);        PostOrderTraverse(T->rchild);        printf("%c", T->data);    }}//5.非递归中序遍历void NoRecursionInTraverse(BiThrTree T){    BiThrTree p;    Stack s;    if (!(s.base = (BiThrTree*)malloc(sizeof(BiThrNode))))  //初始化栈    {        printf("出错:栈初始化失败时分配存储空间失败!\n");        exit(1);    }    s.top = s.base;    s.stackSize = STACK_INIT_SIZE;    p = T;    while(p || (s.top - s.base))    {        while (p)                           //遍历左子树,直到最左下角的节点        {            Push(s, p);            p = p->lchild;        }        if((s.top-s.base))                              //左子树为空,根结点退栈,再遍历右子树        {            Pop(s, p);            printf("%c", p->data);            p = p->rchild;        }    }}//6.层序遍历void LevelOrderTraverse(BiThrTree T){    Queue Q;    BiThrTree p=T;                                     //p在过程中不断被赋予新的结点地址    Q.front = Q.rear = (QPtr)malloc(sizeof(QNode));    //初始化链队列    if (!Q.front)    {        cout << "\n初始化分配存储空间失败!\n" << endl;        exit(1);    }    Q.front->next = NULL;    if (p)        EnQueue(Q, p);    while (Q.front != Q.rear)    {        DelQueue(Q, p);                                 //将被删除的结点赋予p,从而实现结点的更新        cout << p->data;        if (p->lchild != NULL)        {            EnQueue(Q, p->lchild);        }        if (p->rchild != NULL)        {            EnQueue(Q, p->rchild);        }    }//while}//7.中序线索化遍历int InOrderThreading(BiThrTree &Thrt,BiThrTree T){    if (!(Thrt = (BiThrTree)malloc(sizeof(BiThrNode))))    {        printf("出错:分配空间错误!");        exit(-2);    }    Thrt->LTag = Link;                          //建立头节点    Thrt->RTag = Thread;    Thrt->rchild = Thrt;                            //右指针回指指向头节点    if (!T)                                     //二叉树空,头节点的lchild指向根节点    {        Thrt->lchild = Thrt;    }    else    {        Thrt->lchild = T;                       //T不为空,头节点的lchild连接根结点        pre = Thrt;                             //全局变量pre初始化,始终指向刚刚访问过的结点        InThreading(T);                         //中序遍历进行中序线索化,传入的是根结点        pre->rchild = Thrt;        pre->RTag = Thread;        Thrt->rchild = pre;                     //最后一个结点进行线索化       }    return OK;}void InThreading(BiThrTree p){    if (p)    {        InThreading(p->lchild);                 //递归,左子树线索化,直至最左下角的结点,其左子树为空,不在继续递归        //中间部分为对 当前结点 的线索化        if (!p->lchild)                         //当前结点 没有左子树,前驱线索        {            p->LTag = Thread;            p->lchild = pre;                        //p->lchild指向直接前驱        }        if (!pre->rchild)                       //刚访问过的结点 没有右子树,后继线索        {            pre->RTag = Thread;            pre->rchild = p;                        //        }        pre = p;                                //保持pre指向刚刚访问过的结点        InThreading(p->rchild);                 //递归,右子树线索化    }}//利用已经线索化的二叉树进行中序遍历输出, 非递归void InOrderAfterThreading(BiThrTree Thrt)          //传入的是pre,传入前进行的最后操作为:                                              {                                               //pre->rchild = Thrt;pre->RTag = Thread;Thrt->rchild = pre;    BiThrTree p;    p = Thrt->lchild;    while (p != Thrt)    {        while (p->LTag == Link)        {            p = p->lchild;        }        cout << p->data;        while (p->RTag == Thread && p->rchild != Thrt)        {            p = p->rchild;            cout << p->data;        }        p = p->rchild;    }}

3.Stack.c

#include<stdio.h>#include<stdlib.h>#include"Stack.h"#include"Tree.h"/***********************对栈的操作***********************///1.Pushvoid Push(Stack &s, BiThrTree e){    // 栈满,追加空间    if (s.top - s.base >= s.stackSize)    {        s.base = (BiThrTree *)realloc(s.base, (s.stackSize + STACKINCREMENT) * sizeof(BiThrNode));        if (!s.base)            exit(0);        s.top = s.base + s.stackSize;        s.stackSize = s.stackSize + STACKINCREMENT;    }    *(s.top) = e;      // 存放数据    s.top++;}//2.Popvoid Pop(Stack &s, BiThrTree &e){    if (s.top == s.base)    {        printf("\n出错:出栈时栈为空!\n");        exit(-2);    }    e = *(--s.top);   // 将栈顶元素弹出并修改栈指针}

4.Queue.c

#include<stdio.h>#include<stdlib.h>#include<iostream>#include"Queue.h"#include"Marco.h"#include"Tree.h"using namespace std;/*******************对队列的操作***************************///1.EnQueuevoid EnQueue(Queue &Q, BiThrTree e){    QPtr q;    if (!(q = (QPtr)malloc(sizeof(QNode))))    {        printf("出错:队列分配存储空间失败!\n");        exit(OVERFLOW);    }    q->data = e;    q->next = NULL;    Q.rear->next = q;    Q.rear = q;}//2.DelQueuevoid DelQueue(Queue &Q, BiThrTree &e){    if (Q.front == Q.rear)    {        cout << "出错:执行删除操作的队列为空!" << endl;        exit(1);    }    QPtr p = Q.front->next;    e = p->data;    Q.front->next = p->next;    if (Q.rear == p)    {        Q.rear = Q.front;    }    free(p);}

5.Tree.h

#ifndef TREE_H_#define TREE_H_#include<stdio.h>#define STACK_INIT_SIZE 100#define STACKINCREMENT  10typedef enum PointerTag { Link, Thread };           //Link==0,表示指针,Thread==1,表示线索typedef struct BiThrNode{    char data;    struct BiThrNode *lchild;    struct BiThrNode *rchild;    PointerTag LTag;    PointerTag RTag;}BiThrNode, *BiThrTree;/********************对二叉树的操作********************///1.创建int CreateBiThrTree(BiThrTree &T);//2.前序遍历void PreOrderTraverse(BiThrTree T);//3.中序遍历void InOrderTraverse(BiThrTree T);//4.后序遍历void PostOrderTraverse(BiThrTree T);//5.非递归中序遍历void NoRecursionInTraverse(BiThrTree T);//6.层序遍历void LevelOrderTraverse(BiThrTree T);//7.中序遍历并线索int InOrderThreading(BiThrTree &Thrt,BiThrTree T);void InThreading(BiThrTree p);//利用已经线索化的二叉树进行中序遍历输出void InOrderAfterThreading(BiThrTree Thrt);#endif

6.Stack.h

#ifndef STACK_H_#define STACK_H_#include"Tree.h"typedef struct{    BiThrTree *top;    BiThrTree *base;    int stackSize;}Stack;                             //用于非递归遍历二叉树/*******************需要的对栈的操作***********************///1.Pushvoid Push(Stack &s, BiThrTree e);//2.Popvoid Pop(Stack &s, BiThrTree &e);#endif

7.Queue.h

#ifndef QUEUE_H_#define QUEUE_H_#include"Tree.h"typedef struct QNode                //用于层序遍历二叉树{    BiThrTree data;             //存储地址    struct QNode *next;}QNode, *QPtr;typedef struct{    QPtr front;    QPtr rear;}Queue;/******************对队列的操作****************************///1.EnQueuevoid EnQueue(Queue &Q, BiThrTree e);//2.DelQueuevoid DelQueue(Queue &Q, BiThrTree &e);#endif

8.Marco.h(此部分的代码作用暂时不大)

#ifndef MARCO_H_#define MARCO_H_#define OK 0#define ERROR 1//#define OVERFLOW -2#endif

图片中结果的格式和上面的代码运行结果的格式不完全相同,但对结果并无影响
在编写二叉树的线索化的代码时,一直不清楚线索化的具体过程,尽管看上去很容易理解。希望在调试的过程中理解过程,但很难进行下去,因为并没有能够运行的代码,每当想到这里就果断放弃调试,感觉是对时间的浪费。终于,今天静下心来,搜到了一个二叉树动态线索化的网页,观看后勉强理解了,代码写出后,进行调试,进一步理解过程。当然,写代码时不断抄袭书中内容的习惯一直是硬伤,鉴于二叉树的重要性,打算完全靠自己重新写一次。望天道酬勤!

ps:在写这个程序期间,学习了部分C++的知识,但在上述代码中所夹杂的C++代码都是基本的输出,没有输入。(如有错误,望各位指出)。

1 0
原创粉丝点击