线索化和线索树的遍历

#include <iostream>

typedef struct TreeNode{
	ElemType e;
	int ltag, rtag;
	TreeNode *lchild, *rchild;
}TreeNode, * BiTree;

void PreThread(BiTree *Tr) {
	if (!Tr)
		return;
	if (pre && !pre->rchild) {
		pre->rtag = 1;
		pre->rchild = Tr;
	}
	if (!Tr->lchild) {
		Tr->ltag = 1;
		Tr->lchild = pre;
	}
	pre = Tr;
	/*
		在线索化中,当前节点的指针域有且只有lchild会发生变化.
		pre节点先于current node被visit过了,不会造成任何影响.
		而且只有前序遍历会导致指针域先于节点的遍历这种情况的发生.
	*/
	if (!Tr->ltag)
		PreThread(Tr->lchild);
	PreThread(Tr->rchild);
}

void MidstThread(BiTree *Tr, TreeNode * &pre) {
	if (!Tr)
		return;
	MidstThread(Tr->lchild);
	if (pre && !pre->rchild) {
		pre->rtag = 1;
		pre->rchild = Tr;
	}
	if (!Tr->lchild) {
		Tr->ltag = 1;
		Tr->lchild = pre;
	}
	pre = Tr;
	MidstThread(Tr->rchild);
}

void PostThread(BiTree *Tr) {
	if (!Tr)
		return;
	PostThread(Tr->lchild);
	PostThread(Tr->rchild);
	if (pre && !pre->rchild) {
		pre->rtag = 1;
		pre->rchild = Tr;
	}
	if (!Tr->lchild) {
		Tr->ltag = 1;
		Tr->lchild = pre;
	}
	Pre = Tr;
}

int Thread(BiTree Tr) {
	BiTree pre = NULL;
	MidstThread(Tr, pre);
	pre->rtag = 0;
	pre->rchild = NULL;
}

//中序线索树的一些操作.
int GetLeftMost(BiTree *Tr) {
	while (!Tr->ltag && Tr->lchild) {
		Tr = Tr->lchild;
	}
	return Tr;
}

int GetNext(BiTree *Tr) {
	if (Tr->rtag)
		return Tr->rchild;
	return GetLeftMost(Tr->rchild);
}

int GetPrior(BiTree *Tr) {
	if (Tr->ltag)
		return Tr->lchild;
	return GetLeftMost(Tr->lchild);
}

int MidstTraverse(BiTree *Tr) {
	for (Tr = GetLeftMost(Tr); Tr; Tr = GetNext(Tr))
		visit(Tr);
}

//前序线索树的一些操作. 以下假定其存储结构为三岔链表,声明如下.
typedef struct TreeNode{
	ElemType e;
	int ltag, rtag;
	TreeNode *lchild, *rchild, *parent;
}TreeNode, * BiTree;
//dfs建🌲的时候改一下parent域就好了.

int GetRightMost(BiTree Tr) {
	while (1) {
		if (!Tr->rtag && Tr->rchild)
			Tr = Tr->rchild;
		else if(!Tr->ltag && Tr->lchild)
			Tr = Tr->lchild;
	}
	return Tr;
}

int GetNext(BiTree Tr) {
	//Case 1: 能直接找到后继
	if (Tr->rtag)
		return Tr->rchild;
	//Case 2: 有左儿子,左儿子就是后继
	if (!Tr->ltag && Tr->lchild)
		return Tr.lchild;
	//Case 3: 只有右儿子,右儿子是后继
	if (!Tr->rtag && Tr->rchild)
		return Tr->rchild;
	//没有右儿子的时候一定能找到前驱;
	//有右儿子的两种情况也能找得到.
}

int GetPrior(BiTree Tr) {
	//Case 1: ltag
	if (Tr->ltag)
		return Tr->lchild;
	//Case 2: 需要找父节点帮忙
	//SubCase 1: 没有父亲,根
	if (!Tr->parent)
		return false;
	//SubCase 2: 我是父节点的左儿子,我的前驱就是父亲.
	if (Tr->parent->lchild == Tr) {
		return Tr->parent;
	}
	//SubCase 3: 我是父节点的单独右儿子
	if (Tr->parent->lchild == NULL) {
		return Tr->parent;
	}
	//SubCase 4: 有左儿子也有右儿子,我是右儿子.
	return GetRightMost(Tr->parent->lchild);
}

//后序的情况也类似,不再赘述. 前序线索树找不到前序、后序线索树找不到后序.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值