中序线索二叉树的实现

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述在这里插入图片描述

#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;
}
发布了122 篇原创文章 · 获赞 14 · 访问量 6179

猜你喜欢

转载自blog.csdn.net/weixin_44001521/article/details/103748419