//线索二叉树的存储结构描述如下:
typedef struct ThreadNode {
char data;//数据元素
struct ThreadNode* lchild, * rchild;//左右孩子指针;
int ltag, rtag;//左右线索标志 用0代表有孩子,
}ThreadNode,*ThreadTree;
1.中序线索二叉树的构造
ThreadNode* pre = NULL;//定义一个全局变量pre,用来表示访问结点的前一个结点
void visit(ThreadNode* q);
void InThread(ThreadTree T) {
if (T!= NULL) {
InThread(T->lchild);
visit(T);
InThread(T->rchild);
}
}
void visit(ThreadNode* q) {
if (q->lchild == NULL) {
q->lchild = pre;//建立前驱
q->ltag = 1;//用1代表是前驱,没有左孩子
}
if (pre!= NULL && pre->rchild ==NULL) {
pre->rchild = q;//建立后继
pre->rtag = 1;//用1代表是后继 没有有孩子。
}
pre = q;
}
//中序线索二叉树的构造;
void creatInThread(ThreadTree T) {
if (T != NULL) {
InThread(T);
if (pre->rchild == NULL) {
pre->rtag = 1;
}
}
}
2.前序线索二叉树的构造;
ThreadNode* pre = NULL;
void visit(ThreadNode* q);
//先序线索二叉树的构造;
void PreThread(ThreadTree T) {
if (T!= NULL) {
visit(T);
if (T->ltag == 0) {
PreThread(T->lchild);
}
PreThread(T->rchild);
}
}
void visit(ThreadNode* q) {
if (q->lchild == NULL) {
q->lchild = pre;//建立前驱
q->ltag = 1;//用1代表是前驱,没有左孩子
}
if (pre!= NULL && pre->rchild ==NULL) {
pre->rchild = q;//建立后继
pre->rtag = 1;//用1代表是后继 没有有孩子。
}
pre = q;
}
//前序线索二叉树的构造;
void creatPreThread(ThreadTree T) {
if (T != NULL) {
PreThread(T);
if (pre->rchild == NULL) {
pre->rtag = 1;
}
}
}
2.后序线索二叉树的构造;
//后续线索二叉树的构造;
void PostThread(ThreadTree T, ThreadTree &pre) {
if (T!= NULL) {
PostThread(T->lchild,pre);
PostThread(T->rchild,pre);
if (T->lchild == NULL) {
T->lchild = pre;//建立前驱
T->ltag = 1;//用1代表是前驱,没有左孩子
}
if (pre != NULL && pre->rchild == NULL) {
pre->rchild = T;//建立后继
pre->rtag = 1;//用1代表是后继 没有有孩子。
}
pre = T;
}
}
void creatPostThread(ThreadTree T) {
ThreadTree pre=NULL:
if (T != NULL) {
PostThread(T,pre);
if (pre->rchild == NULL) {
pre->rtag = 1;
}
}
}
- 中序线索二叉树找前驱或后继等问题
//找到以p为根的子树中,第一个被中序遍历的结点;
ThreadNode* Firstnode(ThreadNode* p) {
while (p->ltag == 0) {
p = p->lchild;
}
return p;
}
//在中序线索二叉树中找到结点p的后继结点
ThreadNode* Nextnode(ThreadNode* p) {
if (p->rtag == 1) {
return p->rchild;
}
else {
return Firstnode(p->rchild);
}
}
//在中序线索二叉树中进行中序遍历
void Inorder(ThreadNode* T) {
/*for (ThreadNode* p = T; p != NULL; p = Nextnode(p)) {
cout << p->data<<" ";
}*/
ThreadNode* p = T;
while (p) {
cout << p->data << " ";
p = Nextnode(p);//寻找p的后继结点;
}
}
//找到以p为根的子树中,最后一个被中序遍历的结点
ThreadNode* Lastnode(ThreadNode* p) {
while (p->rtag == 0) {
p = p->rchild;
}
return p;
}
//在中序线索二叉树中找到p节点的前驱节点
ThreadNode* Prenode(ThreadNode* p) {
if (p->ltag == 1) {
return p->lchild;
}
else {
return Lastnode(p->lchild);
}
}
//对中序线索二叉树进行逆向中序遍历
void RevInorder(ThreadNode* T) {
ThreadNode* p = T;
while (p) {
cout << p->data << " ";
p = Prenode(p);//找到p的前驱节点
}
}
5.先序线索二叉树问题
先序线索二叉树找先序后继;
在先序线索二叉树中找到指定节点*p
1:若p->rtag==1(表示p节点没有右孩子) 则next=p->rchild;
2.若p->rtag==0(表示p节点有有孩子)
则next=左孩子或者右孩子(有左孩子则是左孩子,没有孩子则是右孩子)
先序线索二叉树找先序前驱:
由于它们的孩子肯定是后继节点
1.若能找到p的父节点,且p是左孩子,则父节点就是它的前序节点
2.若你能找到p的父节点,且左兄弟非空,且p是右孩子,则前驱节点是它的左兄弟子树中的最右下角的那个节点。
3.若能找到p的父节点,且左兄弟为空,且p是右孩子,则父节点就是它的前序节点。
4.若找不到p的父节点,则没有前驱节点。
6.后续线索二叉树问题
后序线索二叉树找后续前驱
在后序线索二叉树中找到指定节点*p
1.若p->ltag==1(表示p节点没有左孩子),则pre=p->lchild;
2.若p->ltag==0(表示p节点有左孩子),则:
1.若右子树非空,则它的前驱节点就是它的右孩子;
2.若右子树为空,则它的前驱节点就是它的左孩子;
后续线索二叉树找后续后继
在后序线索二叉树中找到指定节点*p
1.若p->rtag==1(表示p节点没有右孩子),则next=p->rchild;
2.若p->rtag==0(表示p节点有右孩子),则:
因为它们的孩子肯定是前驱节点
1.若能找到p的父节点,且p是左孩子,若右孩子非空,则它的后继节点在它的右兄弟树中。
2.若能找到p的父节点,且p是左孩子,若右孩子为空,则它的后继节点就是父节点。
3.若能找到p的父节点,且p是右孩子,则它的后继节点就是父节点。