当前位置 博文首页 > kbtx的博客:(先序/中序/后续)线索化二叉树的c++实现(在codebl
所谓线索化二叉树,就是将二叉树的空指针利用起来,分别指向自己的前驱和后继,为了这样做,有必要再额外设置两个逻辑值用于判断当前的指针指向的究竟是左(右)子树还是前驱(后继)结点。
我个人之所以用逻辑值而不是整数,是因为指针和整数的占的字节数是一样的,既然都用上整数了,干脆直接把线索存入“整数”里就完了,代码会更简单,遍历效率也会更高,别忘了在结构体中增加的一个数据项会让由这个结构体创建出的所有对象都持有一份独立的数据。
接下来我们定义二叉树的结点与相关操作:
#include<cstdio>
#include<cstdlib>
#include<queue>
#define max_size 10
#define useless_data -1
#define node_child 1
#define node_link 0
const char child[] = "child";
const char pointer[] = "pointer";
typedef struct TreeNode{
int data;
TreeNode* left_child;
bool left_child_property;
TreeNode* right_child;
bool right_child_property;
TreeNode(){
data = useless_data;
left_child = 0;
right_child = 0;
left_child_property = node_child;
right_child_property= node_child;
}
bool clean(){
if(this->left_child) {
if(this->left_child->clean()){
this->left_child = 0;
}
}
if(this->right_child){
if(this->right_child->clean()){
this->right_child = 0;
}
}
if(this->data==useless_data){
delete this;
return true;
}
return false;
}
void destory_all(){
if(this->left_child&&this->left_child_property==node_child) this->left_child->destory_all();
if(this->right_child&&this->right_child_property==node_child) this->right_child->destory_all();
delete this;
}
void destory(){
if(this->left_child&&this->left_child_property==node_child) this->left_child->destory_all();
if(this->right_child&&this->right_child_property==node_child) this->right_child->destory_all();
}
void output_inOrder(){
if(this->left_child_property==node_child&&this->left_child) this->left_child->output_inOrder();
printf("%d ",this->data);
if(this->right_child_property==node_child&&this->right_child) this->right_child->output_inOrder();
}
/**
*将当前结点的left_child(指向prev)和前驱结点的right_child(指向this)线索化,要求传入当前结点的前驱
*线索化后变为left_link和right_link
**/
void visit_and_build_thread(TreeNode*& prev){
if(this->left_child==0&&this->left_child_property==node_child){
this->left_child = prev;
this->left_child_property = node_link;
}
if(prev&&prev->right_child==0&&prev->right_child_property==node_child){
prev->right_child = this;
prev->right_child_property = node_link;
}
//线索化完毕,将前驱移至当前结点的位置
prev = this;
}
/**
* 用前序遍历将二叉树线索化,需要传入前驱结点
**/
void build_thread_preorder(){
//如果直接传入 (TreeNode*)0, 引用会找不到地址,因此先声明变量
TreeNode* prev = 0;
build_thread_preorder(prev);
//函数执行完毕后,prev会指向遍历的最后一个结点(此时prev->right_child如果为0,需要修改结点类型)
if(prev->right_child == 0){
prev->right_child_property = node_link;
}
}
void build_thread_preorder(TreeNode*& prev){
visit_and_build_thread(prev);
//如果把前驱结点当成左子树访问会导致死循环
if(this->left_child&&this->left_child_property==node_child){
this->left_child->build_thread_preorder(prev);
}
if(this->right_child){
this->right_child->build_thread_preorder(prev);
}
}
/**
* 用中序遍历将二叉树线索化,需要传入前驱结点
**/
void build_thread_inorder(){
//如果直接传入 (TreeNode*)0, 引用会找不到地址,因此先声明变量
TreeNode* prev = 0;
build_thread_inorder(prev);
//函数执行完毕后,prev会指向遍历的最后一个结点(此时prev->right_child必定为0,需要修改结点类型)
if(prev->right_child == 0){
prev->right_child_property = node_link;
}
}
void build_thread_inorder(TreeNode*& prev){
if(this->left_child){
this->left_child->build_thread_inorder(prev);
}
visit_and_build_thread(prev);
if(this->right_child){
this->right_child->build_thread_inorder(prev);
}
}
/**
* 用后序遍历将二叉树线索化,需要传入前驱结点
**/
void build_thread_postorder(){
//如果直接传入 (TreeNode*)0, 引用会找不到地址,因此先声明变量
TreeNode* prev = 0;
build_thread_postorder(prev);
//函数执行完毕后,prev会指向遍历的最后一个结点(此时prev->right_child如果为0,需要修改结点类型)
if(prev->right_child == 0){
prev->right_child_property = node_link;
}
}
void build_thread_postorder(TreeNode*& prev){
if(this->left_child){
this->left_child->build_thread_postorder(prev);
}
if(this->right_child){
this->right_child->build_thread_postorder(prev);
}
visit_and_build_thread(prev);
}
void output_node(int level){
printf( "address:(0x%x) with data:%d ,at level:%d; left_%s = 0x%x , right_%s = 0x%x;\n",
(int)this,this->data,level,
(this->left_child_property==node_child?child:pointer),(int)this->left_child,
(this->right_child_property==node_child?child:pointer),(int)this->right_child );
}
void output_inOrder_detailed(int level = 1){
if(this