一颗线索二叉树:
根据下图进行节点的创建:
代码如下:
#include <iostream>
using namespace std;
typedef char ElemType;typedef struct BiThrNode
{ElemType data;int ltag,rtag;struct BiThrNode *lchild,*rchild;
}BiThrNode,*BiThrTree;
因为普通二叉树有空指针域,所以我们可以利用这些空指针来线索化
1、二叉树的线索化,实质上就是遍历一棵二叉树,在遍历过程中,访问节点的操作是检查当前结点的左右指针域是否为空,如果为空,即将他们改为前驱节点或后继节点的线索。为记录前驱节点,定义pre为全局变量,始终指向当前结点的前驱节点。
定义一个全局变量指向线索二叉树的前驱节点:
BiThrNode *pre;
中序遍历进行线索化:
void InThreading(BiThrTree p)
{if (p){InThreading(p->lchild);if (!p->lchild){p->ltag = 1;p->lchild = pre;}if (!pre->rchild){pre->rtag = 1;pre->rchild = p;}pre = p;InThreading(p->rchild);}
}
根据下图建立头结点,线索化:
代码如下:
bool InOrderThr(BiThrNode *head,BiThrTree T)
{head = new BiThrNode;if (head==NULL)return false;head->ltag = 0;head->rtag = 1;head->rchild = head;if (!T){head->lchild = head;}else{head->lchild = T;pre = head;InThreading(T);pre->rchild = head;pre->rtag = 1;head->rchild = pre;}return true;
}
对于中序线索二叉树上的任意节点,寻找其中序的前驱节点,有以下两种情况:
1、如果该节点的左标志域为1,那么其左指针所指向的节点便是它的前驱节点。
2、如果该节点的左标志为0,表明该节点有左孩子,根据中序遍历的定义,它的前驱节点是以该节点的左孩子为根节点的子树的最右节点,即沿着其左子树的右指针链向下查找,当某节点的右标志域为1时,它就是所要找的前驱节点。
在中序线索二叉树上查找任意节点的中序前驱节点:
BiThrNode *InPreNode(BiThrNode *p)
{BiThrNode *pre;pre = p->lchild;if (p->ltag!=1){while(pre->rtag == 0){pre = pre->rchild;}}return pre;
}
对于中序线索二叉树上的任意节点,寻找其中序的后继节点,有以下两种情况:
1、如果该节点的右标志域为1,那么其右指针所指向的节点便是它的后继节点。
2、如果该节点的右标志为0,表明该节点有右孩子,根据中序遍历的定义,它的后继节点是以该节点的右孩子为根节点的子树的最左节点,即沿着其右子树的左指针链向下查找,当某节点的左标志域为1时,它就是所要找的后继节点。
在中序线索二叉树上查找任意节点的中序后继节点:
BiThrNode *InpostNode(BiThrNode *p)
{BiThrNode *post;post = p->rchild;if (p->rtag!=1){while(post->ltag==0){post = post->lchild;}}return post;
}
从最后一个节点根据前驱节点进行线索二叉树的遍历:
void InOrderPre(BiThrNode *head)
{BiThrNode *p;p = head->rchild;//指向最后一个节点while(p != NULL && p!=head){cout<<p->data;p = InPreNode(p);}
}
从第一个节点根据后继节点进行线索二叉树的遍历:
void InOrderPost(BiThrNode *head) {BiThrNode *p;p = head->lchild;while (p->ltag != 1) {p = p->lchild;}while (p != NULL && p != head) {cout << p->data;p = InPostNode(p);}
}
完整代码如下:
#include <iostream>
using namespace std;
typedef char ElemType;typedef struct BiThrNode {//节点的创建ElemType data;int ltag, rtag;struct BiThrNode *lchild, *rchild;
} BiThrNode, *BiThrTree;BiThrNode *pre;//定义一个全局变量指向线索二叉树的前驱节点void InThreading(BiThrTree &p) {if (p) {InThreading(p->lchild);if (!p->lchild) {p->ltag = 1;p->lchild = pre;}if (!pre->rchild) {pre->rtag = 1;pre->rchild = p;}pre = p;InThreading(p->rchild);}
}bool InOrderThr(BiThrTree &head, BiThrTree T) {head = new BiThrNode;if (head == NULL)return false;head->ltag = 0;head->rtag = 1;head->rchild = head;if (!T) {head->lchild = head;} else {head->lchild = T;pre = head;InThreading(T);pre->rchild = head;pre->rtag = 1;head->rchild = pre;}return true;
}BiThrNode *InPreNode(BiThrNode *p) {BiThrNode *pre;pre = p->lchild;if (p->ltag != 1) {while (pre->rtag == 0) {pre = pre->rchild;}}return pre;
}BiThrNode *InPostNode(BiThrNode *p) {BiThrNode *post;post = p->rchild;if (p->rtag != 1) {while (post->ltag == 0) {post = post->lchild;}}return post;
}void InOrderPre(BiThrNode *head) {BiThrNode *p;p = head->rchild;//指向最后一个节点while (p != NULL && p != head) {cout << p->data;p = InPreNode(p);}
}void InOrderPost(BiThrNode *head) {BiThrNode *p;p = head->lchild;while (p->ltag != 1) {p = p->lchild;}while (p != NULL && p != head) {cout << p->data;p = InPostNode(p);}
}void CreateBiTree(BiThrTree &T) {//以先序遍历的方式创建二叉树char ch;cin >> ch;if (ch == '#')T = NULL;else {T = new BiThrNode;T->data = ch;T->ltag = 0;T->rtag = 0;CreateBiTree(T->lchild);CreateBiTree(T->rchild);}
}int main() {BiThrTree T;BiThrNode *head;CreateBiTree(T);//以先序遍历输入if (InOrderThr(head, T))cout << "线索化完成" << endl;elsecout << "线索化失败" << endl;cout<<"逆序输出中序遍历: ";InOrderPre(head);//逆序输出中序遍历cout << endl;cout<<"正序输出中序遍历: ";InOrderPost(head);//正序输出中序遍历return 0;
}
测试效果图:
测试结果:
本文参考文章地址:
https://blog.csdn.net/g15827636417/article/details/52967949