早上突然发现,我前天写的这个建立线索树并遍历的代码忘了发,今天补上,正好复盘一下
建立中序线索树
附设指针pre,p
p遍历完之后,pre=p,也就是pre是遍历结点p的前驱,p是pre的后继如果p的左孩子为空,那么p-lchild=pre
如果pre的右孩子为空,&&pre!=NULL,pre->rchild=p
中序的前驱,
如果ltag=1,左孩子就是前驱
如果ltag=0,左孩子的最右下结点中序的后继,
如果rtag=1,右孩子就是后继
如果rtag=0,右孩子的最左下结点还要注意,前序遍历的前驱和后序遍历的后继借助二叉树是无法找到的
只能借用三叉链表,找到他的父节点,才有可能实现
中序借助线索遍历
建立循环,p不空,那么p就一直等于p的后继就可以实现
因为在上面,我们已经总结了后继的不同情况,可以写一个函数来实现
就在循环中调用函数就行了我们还可以利用前驱,来实现中序的倒序遍历
#include<iostream>
using namespace std;
typedef struct Treenode {
int data;
struct Treenode* lchild, * rchild;
int ltag, rtag;
}Treenode, * Tree;
Treenode* pre = NULL;
//变遍历,边建立线索二叉树
void visit(Tree T) {
if (T->lchild == NULL) {
T->ltag = 1;
T->lchild = pre;//第一个左孩子为空,前驱为null
}
if (pre != NULL && pre->rchild == NULL) {
pre->rchild = T;//后继,就让pre的→指向p
pre->rtag = 1;
}
pre = T;//保持在T的后面
//只需考虑每次的visit,结点关系
//最后一个结点需要有孩子指向NULL
}
//中序线索化
void mid_order_(Tree& T) {
if (T != NULL) {
mid_order_(T->lchild);
visit(T);
mid_order_(T->rchild);
}
}
//中序线索化
void mid_order_build(Tree& T) {
if (T != NULL) {
mid_order_(T);
pre->rchild = NULL;//处理最后一个结点
pre->rtag = 1;
/*if (pre->lchild == NULL)
pre->rtag = 1;*/
//我觉得和这个是一个效果
}
}
//树的初始化
void InitTree(Tree &T) {
T = NULL;
}
//树的建立,递归建立,输入需要注意
//1 2 4 0 0 0 3 0 5 0 0
void buildTree(Tree& T) {
T = new Treenode;
int x;
cin >> x;
if (x == 0)
T = NULL;
else {
T->data = x;
T->ltag = T->rtag = 0;
buildTree(T->lchild);
buildTree(T->rchild);
}
}
//中序递归遍历
void midorder_circual(Tree T) {
if (T != NULL) {
midorder_circual(T->lchild);
cout << T->data << " ";
midorder_circual(T->rchild);
}
}
//返回一个树的最左下结点
Treenode* left_low(Tree T) {
Treenode* s = T;
while (s->ltag ==0) {
//这里lchild不能作为判断标志,因为线索二叉树的任何一个结点lchild都不为NULL
//必须用ltag来判断
s = s->lchild;
}
return s;
}
//返回树的最右下结点
Treenode* right_low(Tree T) {
Treenode* s = T;
while (s->rtag == 0)
s = s->rchild;
return s;
}
//中序的后继
Treenode * node_behind(Tree T) {
Treenode* p = T;
if (p->rtag == 1)
return p->rchild;//后继为右孩子结点
else {//为右子树的最左下结点
return left_low(p->rchild);
}
}
//中序的前驱
Treenode* node_pre(Tree T) {
Treenode* p = T;
if (p->ltag == 1)
return p->lchild;
else {//
return right_low(p->lchild);
}
}
//中序线索树的遍历
void visit_midorder_(Tree T) {
Treenode* p;
for (p=left_low(T);p != NULL; p = node_behind(p))
cout << p->data << " ";
}
//中序线索树的倒序遍历
void visit_midorder_dao(Tree T) {
Treenode* p = T;
for (p = right_low(T); p != NULL; p = node_pre(p))
cout << p->data << " ";
}
int main() {
Tree T;
InitTree(T);
buildTree(T);
midorder_circual(T);//中序递归遍历
cout << endl;
mid_order_build(T);//中序线索化
visit_midorder_(T);//中序线索树的遍历,利用后继遍历
cout << endl;
visit_midorder_dao(T);//中序线索树的倒序遍历
return 0;
}