您的位置:首页 > 编程语言 > C语言/C++

C语言实现中序线索化二叉树并遍历

2017-11-08 14:26 295 查看
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#define OK 1
#define ERROR 0
using 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###
输出:
9a28
cbegdfa
*/

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

另外,如果还没看懂,那就看看这篇博客,图文并茂 http://blog.csdn.net/my_heart_/article/details/52086321
还有,本人水平有限,如果说的有错,请大佬赐教
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐