二叉线索树实现

二叉线索树实现

二叉线索树主要是方便查找树的前趋和后继的,充分的把二叉树的空指针域利用起来,要是有前趋就指向前趋,要是有后继就只想后继。
代码:

#include<iostream>
using namespace std;

/**通过枚举类型,child = 0, thread = 1,来表示树中的节点指向的是正常的孩子,还是用来指引线索*/
typedef enum{ child, thread } PointTag;

/**创建线索二叉树的结点*/
struct ThBiTreeNode{
	char m_nValue;
	ThBiTreeNode* m_pLeft;
	PointTag m_pLeftTag;
	ThBiTreeNode* m_pRight;
	PointTag m_pRightTag;
};

/**在创建时需要加进去的head*/
ThBiTreeNode* pre;


/**通过前序遍历来构造一个树*/
void CreateBiTree(ThBiTreeNode* &T){
	char c;
	scanf("%c", &c);

	if (c == ' '){
		T = NULL;
	}
	else{
		T = new(ThBiTreeNode);
		T->m_nValue = c;
		T->m_pLeftTag = child;
		T->m_pRightTag = child;
		CreateBiTree(T->m_pLeft);
		CreateBiTree(T->m_pRight);
	}
}


/**构建线索树(填装线索)*/
void InThred(ThBiTreeNode* &T){
	if (T){
		InThred(T->m_pLeft);

		/**左子树为空,改变tag,并指向它的前驱*/
		if (!(T->m_pLeft)){
			T->m_pLeftTag = thread;
			T->m_pLeft = pre;
		}

		/**此次遍历到了B,B在序列中前一个节点为A,如果A没有右节点,那么久把B作为A的后继*/
		if (!(pre->m_pRight)){
			pre->m_pRightTag = thread;
			pre->m_pRight = T;
		}

		/**本次的结点处理完之后,就成为了下一次处理节点的上一个节点*/
		pre = T;

		InThred(T->m_pRight);
	}
}

/**构建线索数(增加head节点),最后把序列最后一个数和head节点的右节点建立线索*/
void InOrderThreadBiTree(ThBiTreeNode* &head, ThBiTreeNode* &T){
	/**先把head节点放进来,判断T是否为空树的话,在添加线索的时候做,T为空树,我head照样可以连接*/
	head = new(ThBiTreeNode);
	head->m_nValue = NULL;
	head->m_pLeftTag = child;
	head->m_pRightTag = thread;

	/**如果传进来的树是一个空树,那么head节点的左子节点指向自己*/
	if (!T){
		head->m_pLeft = head;
	}
	else{
		head->m_pLeft = T;
		pre = head;
		InThred(T);
		/**是在所有都线索化完成之后,才把序列的最后一个的右线索,连接在head节点上*/
		/**在完成上面的线索建立后,pre是指向中序遍历的最后一个元素的,就是树中最右边的元素*/
		pre->m_pRightTag = thread;
		pre->m_pRight = head;
		/**把head的右线索连接在序列最后一个*/
		head->m_pRight = pre;
	}
}


void vist(ThBiTreeNode* T){
	std::cout << T->m_nValue << std::endl;
}

/**中序遍历打印二叉树*/
void InorderTraverse(ThBiTreeNode* T){

	ThBiTreeNode* temp;
	/**现在这个temp指向的就是加入了head节点之后树的根节点(不是head)*/
	temp = T->m_pLeft;

	/**如过指向左孩子的指针,和指向根节点的指针是同一个的时候*/
	/**表示这个树要么是空树,要么是遍历结束的时候*/
	while (temp != T){
		while (temp->m_pLeftTag == child){
			temp = temp->m_pLeft;
		}
		vist(temp);

		/**p-rchild != T,就表示这个点不是指向你加入的那个head节点,就表明,现在这个遍历的结点是有真正的后继的*/
		while (temp->m_pRightTag == thread && temp->m_pRight != T){
			/**这个时候,树已经线索化完成了,p的右孩子现在指向的是它序列中的后继*/
			temp = temp->m_pRight;
			vist(temp);
		}
		temp = temp->m_pRight;
	}
}

int main(){
	/**原始树*/
	ThBiTreeNode* T;

	/**加了头的树*/
	ThBiTreeNode* T_head;

	/**根据输入创建基本二叉树*/
	CreateBiTree(T);

	/**把head节点加进去,并且建立线索*/
	InOrderThreadBiTree(T_head, T);

	/**中序遍历带有head的树*/
	InorderTraverse(T_head);

	system("pause");
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值