用c++实现二叉树的线索化

       二叉树是一种非线性结构,遍历二叉树几乎都是通过递归或者用栈辅助实现非递归的遍历。用二叉树作为存储结构时,取到一个节点,只能获取节点的左孩子和右孩子,不能直接得到节点的任一遍历序列的前驱或者后继。

       为了保存这种在遍历中需要的信息,我们利用二叉树中指向左右子树的空指针来存放节点的前驱和后继信息。







实现源代码:

#include<iostream>
using namespace std;


enum PointerTag//枚举类型
{
THREAD,//0
    LINK,//1
};


//线索化二叉树的结点结构
template < class T>
struct BinaryTreeNodeThd
{
T _data;//数据域
BinaryTreeNodeThd<T>* _left;//左子树
BinaryTreeNodeThd<T>* _right;//右子树
PointerTag _leftTag;//左标记
PointerTag _rightTag;//右标记


//构造函数,线索化:利用二叉树中指向左、右子树的空指针来存放结点的前驱和后继信息
BinaryTreeNodeThd(const T& x)
:_data(x)//数据域
,_left(NULL)//左孩子指针
,_right(NULL)//右孩子指针
,_leftTag(LINK)//指示结点遍历前驱
,_rightTag(LINK)//指示结点遍历后继
{}


};


//线索化二叉树类
template < class T>
class BinaryTreeThd
{
typedef BinaryTreeNodeThd<T> Node;//Node  线索化结点结构
public:
BinaryTreeThd()
:_root(NULL)
{}


    //构造函数,arr为结点数组,size为结点个数, index指向结点位置,invalid 非法值,如"#"
BinaryTreeThd(const T* arr,size_t size,size_t index,const T& invalid)
{
_root = _CreateBinaryTreeThd(arr, size, index, invalid);
}


//先序线索化
void PrevorderThread()
{
Node* prev = NULL;
_PrevorderThread(_root, prev);
}


//先序线索化遍历二叉树,访问根结点->左子树->右子树
void _PrevorderThreading()
{
Node* cur = _root;


if (cur == NULL)
{
return;
}


while (cur)
{
while (cur->_leftTag == LINK)
{
cout << cur->_data << " ";//依次访问根结点->左子树
cur = cur->_left;
}
cout << cur->_data<<" ";


//转移到右边的结点
cur = cur->_right;
}


}


//中序线索化
void InorderThread()
{
Node* prev = NULL;
_InorderThread(_root, prev);
}


//中序线索化遍历二叉树,访问左子树->根结点->右子树
void _InvorderThreading()
{
Node* cur = _root;


if (cur == NULL)
{
return;
}


while (cur)
{
while (cur->_leftTag == LINK)
{
cur = cur->_left;
}
cout << cur->_data << " ";//依次访问左子树->根结点


while (cur->_rightTag == THREAD)
{
cur = cur->_right;
cout << cur->_data << " ";//访问右子树
}
cur = cur->_right;
}


}
protected:
Node* _CreateBinaryTreeThd(const T* arr, size_t size, size_t& index, const T& invalid)
{
Node* root = NULL;


if (index < size&&arr[index] != invalid)
{
root = new Node(arr[index]);
root->_left = _CreateBinaryTreeThd(arr, size, ++index, invalid);
root->_right = _CreateBinaryTreeThd(arr, size, ++index, invalid);
}


return root;
}


//先序线索化子树
void _PrevorderThread(Node* cur, Node*& prev)
{
if (cur == NULL)
{
return;
}


//置前线索化
if (cur->_left == NULL)
{
cur->_leftTag = THREAD;
cur->_left = prev;
}


//置后线索化
if (prev&&prev->_right == NULL)
{
prev->_rightTag = THREAD;
prev->_right = cur;
}


prev = cur;


if (cur->_leftTag == LINK)
{
_PrevorderThread(cur->_left, prev);
}


if (cur->_rightTag == LINK)
{
_PrevorderThread(cur->_right, prev);
}


}


//中序线索化子树
void _InorderThread(Node* cur, Node*& prev)
{
if (cur == NULL)
{
return;
}


//递归遍历左子树
_InorderThread(cur->_left, prev);


if (cur->_left == NULL)
{
cur->_leftTag = THREAD;
cur->_left = prev;
}


if (prev&&prev->_right == NULL)
{
prev->_rightTag = THREAD;
prev->_right = cur;
}


prev = cur;


//递归遍历右子树
_InorderThread(cur->_right, prev);


}
private:
Node* _root;


};


void test()
{
int arr1[10] = { 1,2,3,'#','#',4,'#','#', 5,6 };
int arr2[15] = { 1,2,'#',3,'#','#',4,5,'#',6,'#',7,'#','#',8 };


BinaryTreeThd<int>tree1(arr1, 10, 0, '#');//二叉树tree1
BinaryTreeThd<int>tree2(arr2, 15, 0, '#');//二叉树tree2


cout << "打印二叉树tree1:" << endl;
cout << "      " << arr1[0] << endl;
cout << "   " << arr1[1] << "      " << arr1[8] << endl;
cout << arr1[2] << "   " << arr1[5] << "   " << arr1[9] << endl;

cout << "打印二叉树tree2:" << endl;
cout << "        " << arr2[0] << endl;
cout << "  " << arr2[1] << "            " << arr2[6] << endl;
cout << "     " << arr2[3] << "     " << arr2[7] << "      " << arr2[14]<<endl;
cout << "                " << arr2[9] << endl;
cout << "                     " << arr2[11] << endl;

// 注意一棵二叉树一次只能线索化一次,如:先序线索之后,已经发生了线索标记,不能紧接着就进行中序线索化


cout << "先序线索化遍历二叉树tree1:   ";
tree1.PrevorderThread();
tree1._PrevorderThreading();
cout << endl;
cout << "先序线索化遍历二叉树tree2:   ";
tree2.PrevorderThread();
tree2._PrevorderThreading();
cout << endl;

/*cout << "中序线索化遍历二叉树tree1:   ";
   tree1.InorderThread();
tree1._InvorderThreading();
cout << endl;
cout << "中序线索化遍历二叉树tree2:   ";
tree2.InorderThread();
tree2._InvorderThreading();
cout << endl;*/

}


int main()
{
test();
system("pause");
return 0;

}

扫描二维码关注公众号,回复: 949475 查看本文章

运行结果1:

打印二叉树tree1:

      1

   2      5

3   4   6

打印二叉树tree2:

        1

  2            4

     3     5      8

                6

                     7

先序线索化遍历二叉树tree1:   1 2 3 4 5 6

先序线索化遍历二叉树tree2:   1 2 3 4 5 6 7 8

请按任意键继续. . .

运行结果2:

打印二叉树tree1:

      1

   2      5

3   4   6

打印二叉树tree2:

        1

  2            4

     3     5      8

                6

                     7

中序线索化遍历二叉树tree1:   3 2 4 1 6 5

中序线索化遍历二叉树tree2:   2 3 1 5 6 7 4 8

请按任意键继续. . .


猜你喜欢

转载自blog.csdn.net/yanxiaolx/article/details/51539263