中序线索化二叉树并遍历

来源:互联网 发布:淘宝的昵称有什么用 编辑:程序博客网 时间:2024/06/03 14:30
#include <iostream>#include <cstdio>#include <cstring>#include <cstdlib>#define OK 1#define ERROR 0using namespace std;enum PointerTag {Link, Thread};  //声明枚举,Link == 0:指针,Thread == 1:线索typedef char TElemType;typedef int Status;typedef struct BiThrNode {    TElemType   data;    struct BiThrNode    *lchild, *rchild;  //左右孩子指针    PointerTag  LTag, RTag;   //左右标志}BiThrNode, *BiThrTree;BiThrTree   pre;  //全局变量Status CreateBiTree(BiThrTree &T) {  //以先序次序创建二叉树    char ch;    cin >> ch;    if (ch == '#')  T = NULL;    else {        T = (BiThrNode *)malloc(sizeof(BiThrNode));  //申请空间        T->data = ch;                //结点        T->LTag = Link;              //初始化结点,其lchild域全部有左孩子        CreateBiTree(T->lchild);     //左孩子        CreateBiTree(T->rchild);     //右孩子    }    return OK;}/*所有线索化的实质:将二叉树链表中的空指针改为前驱或后继的线索。-------------------------------------------------------------前驱或后继的信息只有在遍历时才能得到,因此线索化的过程即为在遍历的过程中修改空指针的过程。--------------------------------------------------------------为了记下遍历过程中访问结点的先后关系,设一个指针pre始终指向刚刚访问过的结点,而指针p指向当前访问的结点,则pre指向p的前驱--------------------------------------------------------------中序遍历的操作:若二叉树为空,则空操作;否则(1)左子树(2)根节点(3)右子树*/void InThreading(BiThrTree p) {  //联想中序遍历    if (p) {        InThreading(p->lchild);    //左子树线索化        if (!p->lchild) {          //寻找前驱线索            p->LTag = Thread;            p->lchild = pre;        }        if (!pre->rchild) {       //寻找后继线索            pre->RTag = Thread;            pre->rchild = p;        }        pre = p;                 //保持pre指向p的前驱        InThreading(p->rchild);   //左子树完,进行右子树线索化    }}Status InOrderThreading(BiThrTree &Thrt, BiThrTree T) {      //线索化算法    //中序遍历二叉树T,并将其中序线索化,Thrt指向头结点   //仿照线性表的存储结构,在二叉树的线索链表上也添加一个头结点   Thrt = (BiThrTree)malloc(sizeof(BiThrNode));    Thrt->LTag = Link;                          //建立头结点    Thrt->RTag = Thread;                        //后继线索   Thrt->rchild = Thrt;                        //右指针回指    if (!T)        Thrt->lchild = Thrt;                    //若二叉树为空,则左指针回指    else {        Thrt->lchild = T;                       //头结点的左子树指向二叉树T        pre = Thrt;                             //pre指向刚刚访问过的结点        InThreading(T);                         //中序遍历进行 中序 线索化        pre->rchild = Thrt;                     //将最后一个线索化        pre->RTag = Thread;        Thrt->rchild = pre;    }    return OK;}Status PrintElement(TElemType e) {               //输出函数    cout << e;    return OK;}Status InOrderTraverse_Thr(BiThrTree T, Status(*Visit)(TElemType e)) {      //第二个参数运用了函数指针,调用上一步写的输出函数    //T指向头结点,头结点的左链lchild指向根节点,参见前面的线索化算法    //中序遍历二叉树线索化T的非递归算法,对每个数据元素调用输出函数   BiThrNode *p;    p = T->lchild;                                      //p指向根节点    while (p != T) {                                    //空树或遍历结束后,p == T        while (p->LTag == Link)            p = p->lchild;        if (!Visit(p->data))                           //访问左子树为空的结点            return ERROR;        while (p->RTag == Thread && p->rchild != T) {            p = p->rchild;                             //访问后继结点            Visit(p->data);        }        p = p->rchild;    }    return OK;}int main(){    BiThrNode   *T, *Thre;    cout<< "先序创建二叉树" << endl;    CreateBiTree(T);                        //在线索化之前,你的有一颗二叉树,不然怎么线索化    InOrderThreading(Thre, T);              //中序遍历二叉树T,并将其中序线索化    InOrderTraverse_Thr(Thre, PrintElement);//以双向线索链表为存储结构式对二叉树进行遍历    return 0;}/*输入:abc##de#g##f###输出:cbegdfa*/ 

资料参考于清华大学出版的数据结构(C语言版)

另外,如果还没看懂,那就看看这篇博客,图文并茂 http://blog.csdn.net/my_heart_/article/details/52086321

还有,本人水平有限,如果说的有错,请大佬赐教

阅读全文
0 0
原创粉丝点击