#include"pch.h"
#include<iostream>
using namespace std;
typedef char elem;
typedef struct BiThrNode {
struct BiThrNode * lchild, *rchild;
int LTag, RTag;
elem data;
}BiThrNode, *BiThrTree;
//RTag=1:结点的后继,RTag=0:结点的右孩子
//LTag=1:结点的前驱,LTag=0:结点的左孩子
BiThrTree pre;
typedef struct StackNode {
BiThrTree StackData;
struct StackNode *next;
}StackNode, *LinkStack;
bool Push(LinkStack &L, BiThrTree e) {
StackNode *p = new StackNode;
p->StackData = e;
p->next = L;
L = p;
return true;
}
bool Pop(LinkStack &S, BiThrTree &t) {
if (!S) return false;
LinkStack temp = S;
t = temp->StackData;
S = S->next;
delete temp;
return true;
}
BiThrTree getTop(LinkStack L) {
if (!L) return NULL;
else
return L->StackData;
}
bool isEmpty(LinkStack S) {
return S == NULL;
}
void createTree(BiThrTree & B, char *str) {
LinkStack l = NULL; B = NULL;
char ch = str[0];
BiThrTree p = NULL, t;
int mark = -1, j = 0;//mark=1时表示后面时左孩子树,mark=2为右孩子树
while (ch != '\0') {
switch (ch) {
case '(': { //入
mark = 1;
Push(l, p);
p = NULL;
break;
}
case ')': {
Pop(l, t);
break;
}
case ',': {
mark = 2;
break;
}
default: { //输入字母
p = new BiThrNode;
p->data = ch;
p->lchild = p->rchild = NULL;
if (isEmpty(l)) {
B = p;
}
else {
switch (mark) {
case 1: {//左孩子
(l->StackData)->lchild = p;
break;
}
case 2: {//右孩子
(l->StackData)->rchild = p;
break;
}
}
}
}
}
j++;
ch = str[j];
}
}
//中序递归
void InOrder(BiThrTree B) {
if (B != NULL) {
InOrder(B->lchild);
printf("%c ", B->data);
InOrder(B->rchild);
}
}
//实质就是把二叉树的空指针指向前继,后继
//任务:中序线索化上述二叉树并找出根结点的前驱和后继。
//利用pre始终指向刚访问过的结点
//1.以结点p为根结点的子树中中序排序
void InThreading(BiThrTree p) {
//pre是全局变量,初始化时其右孩子指针为空,便于在树最左点开始建立线索
if (p) {
//1.1对左孩子进行递归线索化
InThreading(p->lchild);//左子树递归线索化
if (!p->lchild) { //p的左孩子为空
p->LTag = 1;//加上左线索
p->lchild = pre;//p左孩子指针指向pre(后继)
}
else p->LTag = 0;//有左孩子
if (!pre->rchild) {
pre->RTag = 1;
pre->rchild = p;//pre右孩子指针指向p(后继)
}
else
pre->RTag = 0; //有右孩子
pre = p; //保持pre是指向P的前驱
InThreading(p->rchild);//右子树递归线索化
}
}
//2.带头结点的二叉树中序线序化
void InOrderThreading(BiThrTree & thrt, BiThrTree T) {
//中序遍历二叉树T,并将其中线索化,thrt指向头结点
thrt = new BiThrNode;//建立头结点
thrt->LTag = 0; //头结点右左孩子,如果树非空,则称左孩子为树根
thrt->RTag = 1; //头结点的右孩子指针为右线索
thrt->rchild = thrt; //初始化右指针指向自己
if (!T) thrt->lchild = thrt; //树空,左指针指向自己
else {
thrt->lchild = T;
pre = thrt;//头结点的左孩子指向根,pre指向头结点
InThreading(T);//对以T为根的二叉树进行中序线索化
pre->rchild = thrt;//上一句调用函数结束之后,pre为最右结点,pre的右线索指向头结点
pre->RTag = 1;
thrt->rchild = pre;
}
}
//3.遍历线索二叉树
//中序线索树中遍历
void InOrderTraverse_Thr(BiThrTree T) {
//T指向头结点,头结点都lchild指向根节点,
//中序遍历二叉线索树非递归
BiThrTree p;
p = T->lchild;//根结点
while (p != T) { //空树或遍历结束时,p==T
while (p->LTag == 0) p = p->lchild;//沿着左子树向下
cout << p->data<<" ";
while(p->RTag == 1 && p->rchild != T) {//沿右线索访问后继结点
p = p->rchild;
cout << p->data<<" ";
}
p = p->rchild;//转向p的右子树
}
}
BiThrTree Locate(BiThrTree T,elem e) {
//T指向头结点,头结点都lchild指向根节点,
//中序遍历二叉线索树非递归
BiThrTree p;
if (T == NULL) return NULL;
p = T->lchild;//根结点
while (p != T) { //空树或遍历结束时,p==T
while (p->LTag == 0) p = p->lchild;//沿着左子树向下
if (p->data == e) return p;
while (p->RTag == 1 && p->rchild != T) {//沿右线索访问后继结点
p = p->rchild;
if (p->data == e) return p;
}
p = p->rchild;//转向p的右子树
}
return false;
}
//结点的前驱和后继。
BiThrTree inPre(BiThrTree B) {
BiThrTree q, PRE = NULL;
if (B->LTag == 1) { //直接返回前驱
PRE = B->lchild;
}
else {//要返回左子树最左点
q = B->lchild;
while (q->RTag == 0) {
q = q->rchild;
}
PRE = q;
}
return PRE;
}
BiThrTree inAft(BiThrTree B) {
BiThrTree next = NULL,q;
if (B->RTag == 1) { //直接返回后继
next = B->rchild;
}
else {//要返回右子树最左点
q = B->rchild;
while (q->LTag == 0) {
q = q->lchild;
}
next = q;
}
return next;
}
BiThrTree findFirst(BiThrTree B) {//循环找到最左下角结点
while (B->LTag == 0) {
B = B->lchild;
}
return B;
}
BiThrTree findLast(BiThrTree B) {
while (B->RTag == 0) {
B = B->rchild;
}
return B;
}
elem value(BiThrTree B) {
if (B) {
return B->data;
}
else return NULL;
}
int main() {
BiThrTree B, T = NULL, temp = NULL;
char str[] = "A(B(D,E(H(J,K(L,M(,N))))),C(F,G(,I)))";
createTree(B, str);
cout << "目标字符串 " << str << endl;
InOrder(B); cout << endl;
InOrderThreading(T,B);
InOrderTraverse_Thr(T);
cout << endl;
//根结点的前驱的值为
cout<<"根结点的前驱的值为"<<value(inPre(T->lchild))<<endl;
//根结点的后继的值为
cout <<"根结点的后继的值为" <<value(inAft(T->lchild))<<endl;
cout << "中序线索二叉树的第一个值为" <<value(findFirst(T->lchild)) << endl;
cout << "中序线索二叉树的倒数第一个值为" << value(findLast(T->lchild)) << endl;
char e; cout << "定位元素的位置" << endl;
while (cin >> e) {
if (Locate(T, e) != NULL)
{
cout << "指针所指向的地址为 " << Locate(T, e) << '\t' << "的值为" << value(Locate(T, e)) << endl;
cout << "前驱是" << value(inPre(Locate(T, e))) << "\t后继是" << value(inAft(Locate(T, e))) << endl;
}
else
cout << "不存在" << endl;
}
return 0;
}