深入理解数据结构——二叉树线索树基本操作

#include <iostream>
#include <string>

using namespace std;

typedef char EType;

struct BinaryTreeNode {
	EType data;
	BinaryTreeNode* LChird;//左孩地址
	bool Lflag;
	BinaryTreeNode* RChird;//右孩地址
	bool Rflag;
};

typedef BinaryTreeNode* BinaryTree;

//前序遍历:首先访问根节点,然后遍历左子树,最后遍历右子树
void PreOrderThreadTraversal(BinaryTreeNode* BT) {

	BinaryTreeNode* p=BT;

	while (p)
	{
		cout << p->data << endl;
		if (!p->Lflag)//左标志位为0
			p=p->LChird;
		else
			p = p->RChird;
	}
}

//中序遍历:首先遍历左子树,然后访问根节点,最后遍历右子树
void InOrderThreadTraversal(BinaryTreeNode* BT) {
	
	BinaryTreeNode* p = BT;
	bool flag;

	while (p)
	{
		while(!p->Lflag)//查找一个子树最左子孙
			p = p->LChird;
		flag = true;
		while (flag && p) {
			cout << p->data << endl;//访问节点
			if (!p->Rflag)//右标志位为0,p节点存在右子树,为强制退出作准备
				flag = p->Rflag;  //flag=NULL;

			p = p->RChird;    //查找p右子树的跟或后继节点
		}
	
	}
}
 
//后序遍历:首先遍历左子树,然后遍历右子树,最后访问根节点
void PostOrderRecursive(BinaryTreeNode* BT) {
	//二叉树遍历递归算法
	if (BT) {

		PostOrderRecursive(BT->LChird);
		PostOrderRecursive(BT->RChird);
		cout << BT->data << endl;
	}
}



//前序遍历的非递归算法
struct SType {
	BinaryTreeNode* ptr;
	bool status;
};

struct Stack {
	SType* element;
	int top;
	int maxsize;

};

//创建空堆栈
void CreateStack(Stack& S, int MaxStackSize) {
	S.maxsize = MaxStackSize;
	S.element = new SType[S.maxsize];//创建数组元素
	S.top = -1;//top指向的是数据空间的第一个元素,本身的值代表数据元素的下表,空表设top为-1
}
//判断堆栈是否为空
bool IsEmpty(Stack& S) {
	if (S.top == -1) return true;
	else return false;
}

//出栈操作,将栈顶元素取出,并且将top指向下一个元素的位置
bool Pop(Stack& S, SType& result) {
	if (IsEmpty(S)) return false;
	result = S.element[S.top];
	S.top--;//栈顶指向下一个元素地址
	return true;
}

//进栈操作,将top+1,输入元素存入新的栈顶
bool Push(Stack& S, SType& x) {//传入的是x的地址
	if (IsEmpty(S)) return false;
	S.top++;
	S.element[S.top] = x;
	return true;
}

//前序遍历:首先访问根节点,然后遍历左子树,最后遍历右子树
void PreOrderThreading(BinaryTreeNode* BT) {
	//二叉树转化为前序线索树算法
	Stack S;
	SType temp;
	BinaryTreeNode* p = BT,*q=NULL;//p最开始指向根节点,q始终指向p系欸但那前驱

	int MaxStackSize = 50;
	CreateStack(S, MaxStackSize);//产生一个空栈

	while (p || IsEmpty(S)) {
		while (p) {
			temp.ptr = p;
			Push(S, temp);//根节点进栈,以后回溯时再退栈
			if (p->RChird)
				p->Rflag = false;
			else
				p->Rflag = true;

			if (p->LChird){//如果p仍然有左子树,继续向前
				if (!p->RChird)
					p->RChird = p->LChird;
				p->Lflag = false;
				q = p;
				p = p->LChird;

			}
			else {
				//如果没有左子树
				p->Lflag = true;
				p->LChird = q;
				q = p; break;
			}
		}

		if (!IsEmpty(S)) {
			Pop(S, temp);
			p = temp.ptr;
			if (!p->RChird) {
				q->RChird = p->RChird;
				p = p->RChird;//指针指向回溯节点的右子树
			}
			else
				p = NULL;
		}
	}
	q->Rflag = true;//将二叉树的最右子孙的右链接域标志设为1
	q->RChird = NULL;
}

//中遍历:首先遍历左子树,然后访问根节点,最后遍历右子树
void InOrderThreading(BinaryTreeNode* BT) {
	//二叉树转化为中序线索树算法
	Stack S;
	SType temp;
	BinaryTreeNode* p = BT,*q=NULL;//p指向根节点data
	int MaxStackSize = 50;
	CreateStack(S, MaxStackSize);//产生一个空栈

	while (p || IsEmpty(S)) {

		while (p) {//找到最左子树
			temp.ptr = p;//temp指向根节点
			Push(S, temp);     //根节点进栈,以后回溯时再退栈
			if (p->LChird) {//如果p仍然又左子树,则继续推进
				p->Lflag = false;
				p = p->LChird;    //指针指向左子树
			}//没有左子树了 
			else {
				p->LChird = q;//没有左子树,那么链接域指向前驱
				p->Lflag = true;//记录标志位
				q = p;//q现在指向最后面一个左孩
				p = NULL;//p设为null,强制退栈,退出循环
			}
		}
		if (!IsEmpty(S)) {//左子树为空,利用堆栈回溯
			Pop(S, temp);//从堆栈中弹出回溯节点指针
			p = temp.ptr;
			p->Rflag = false;//假设p右孩子,0
			if (!q->RChird && q != p) {//如果没有右孩
				q->RChird = p;//那么链接域指向前驱
				q->Rflag = true;//记录标志位
				q = p;
			}
			p = p->RChird;//指针指向回溯节点的右子树
		}
		q->Rflag = true;//将二叉树的最右子孙的右链接域标志设为1
	}
}


void InOrderThreadInsertLeft(BinaryTreeNode* S, BinaryTreeNode* T) {
	//在中序线索树中插入T指向的新节点作为S指向节点的左孩子算法

	BinaryTreeNode* q;
	T->Rflag = true;//没有右孩
	T->RChird = S;//右孩指向S

	T->Lflag = S->Lflag;//将T插入到S和S的左孩之间
	T->LChird = S->LChird;
	
	S->Lflag = false;//S有左孩
	S->LChird = T;//S的左孩为T

	if (!T->Lflag) {//找到左子树中的最右子孙
		q = T->LChird;
		while (!q->RChird)
			q=q->RChird;
		q->RChird = T;//使得最右子孙指向T
	}

}


void InOrderThreadInsertRight(BinaryTreeNode* S, BinaryTreeNode* T) {
	//在中序线索树中插入T指向的新节点作为S指向节点的右孩子算法

	BinaryTreeNode* q;
	T->Lflag = true;//没有左孩
	T->LChird = S;//左孩指向S

	T->Rflag = S->Rflag;//将T插入到S和S的右孩之间
	T->RChird = S->RChird;

	S->Rflag = false;//S有右孩
	S->RChird = T;//S的右孩为T

	if (!T->Rflag) {//找到左子树中的最ZUO子孙
		q = T->RChird;
		while (!q->LChird)
			q = q->LChird;
		q->LChird = T;//使得最ZUO子孙指向T
	}

}


//一般树的 操作
struct TreeNode {
	EType data;
	TreeNode* son;//最大子孩
	TreeNode* next;//节点右边的第一个兄弟
};

//一般树中求T指针所指向节点的°的算法

int TreeNodeDegree(TreeNode *T) {
	int degree = 0;
	if (!T->son) return 0;//根节点下没有节点
	degree++;
	T = T->son;
	while (T->next) {
		T = T->next;
		degree++;
	}
	return degree;
}

struct QType {
	TreeNode* ptr;
};

//二叉树存储下按层次遍历一般树的算法
void LevelOrderTreeLtoR(TreeNode* T) {
	Queue Q;
	QType temp;
	int MaxQueueSize = 100;

	CreatQueue(Q, MaxQueueSize);

	temp.ptr = T;
	EnQueue(Q, temp);//进队

	while (!IsEmpty(Q)) {
		OutQueue(Q, temp);//出队
		T = temp.ptr;
		while (T) {
			cout << T->data << endl;//访问节点
			temp.ptr = T->son;//下一个节点
			if (T->son)
				EnQueue(Q, temp);  //检查是否有左子树,有的话进队
			T = T->next;//没有的话,访问兄弟节点

		}
	}
}

//定义队列顺序存储结构
struct Queue
{
	QType* element;          // 存放结点的数据元素。
	int front;				//对头节点
	int real;				//队尾节点
	int maxsize;			//队列最大容量
};

//构造空队列算法
void CreatQueue(Queue& Q, int MaxQueueSize) {
	Q.maxsize = MaxQueueSize;
	Q.element = new QType[Q.maxsize];
	Q.front = 0;
	Q.real = 0;
}

//判断队列是否为空
bool IsEmpty(Queue& Q) {
	if (Q.front == Q.real) return true;
	return false;
}

//判断队列是否满了front=real+1;
bool IsFull(Queue& Q) {
	if (Q.front == (Q.real + 1) % (Q.maxsize + 1)) return true;
	return false;
}

//返回队头元素的值
bool GetFront(Queue& Q, QType& result) {
	//将font后面一个位置的队列元素的值取出
	if (IsEmpty(Q)) return false;
	result = Q.element[(Q.front + 1) % (Q.maxsize + 1)];
	return true;
}

//进队运算
//将一个新的的元素x存储到当前real所指空间的下一个位置,首先要判断队列是否为满了
bool EnQueue(Queue& Q, QType& x) {
	if (IsFull(Q)) return false;
	Q.real = (Q.real + 1) % (Q.maxsize + 1); //real指向空间的下一个位置
	Q.element[Q.real] = x;//存入x
	return true;
}

//出队运算
//将front所指空间的下一个位置的元素取出,首先要判断队列是否为空
bool OutQueue(Queue& Q, QType& result) {
	if (IsEmpty(Q)) return false;
	Q.front = (Q.front + 1) % (Q.maxsize + 1); //front指向空间的下一个位置
	result = Q.element[Q.front];
	return true;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

南叔先生

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值