- 好久不见,朋友们!虽然我知道没人看我的博客,但我还是想叨逼叨一下。啊,好久没编程了(其实也就一周没编),但你们知道,程序员一天不编程那能叫程序员么???虽然我不是程序员哈哈哈哈哈,但还是要有基本素养嘛。
- 继续写二叉树,给自己立一个flag,就是这几天要写完之前没做完的几道题,和二叉树红黑树各种树之类的~~虽然有这个flag,但我还是很实诚地遵从自己的内心,买了一张明天的电影票,等我回来告诉你们好不好看!好看的话,我就!!写影评!!但!!不给看!!
- 好的,我是屯了很多电影和书没看啦,但我屯的代码好像更多。之前又比较犯懒,就只码代码,没写博客,但我发现哦,写博客真的很有助于增进对代码的分析能力,所以我又开始以我神经兮兮的风格开始写博客啦!
- 今天我要写的博客是关于二叉树的线索化,当然,也可以理解为是线索二叉树。
线索二叉树
什么是线索二叉树
- 对于n个结点的二叉树,在二叉链表的数据存储结构中,总是有(2n - (n-1) = n+1)个空链域。
- 我们利用这些空链域存放某种遍历次序下该结点前驱结点和后续结点的指针,并将这些指针称为线索,称该二叉树为线索二叉树,称给二叉树加上线索的过程为二叉树的线索化。
为什么要进行二叉树的线索化
- 我们都知道,二叉树是一种非线性的数据结构,遍历二叉树时,我们常使用递归或者用栈辅助从而实现非递归的遍历。
- 显然,当我们使用二叉树作为存储结构时, 取到一个结点,我们只能获取到结点的左右孩子,而无法获取到结点的前驱和后继。
- 那么,为了进一步增强遍历的实用性,我们利用二叉树结构中的空指针来存放各结点的前驱和后继信息。
线索二叉树的基本设计
- 如果_left为空,则存放指向中序遍历序列中该结点的前驱结点。
- 如果_right为空,则存放指向中序遍历序列中该结点的后继结点。
- 如果_leftTag为Link,则代表着结点存放的是其左孩子;存放的是Thread则代表着其存放的是其前驱结点。
- 如果_rightTag为Link,则代表着结点存放的是其右孩子;存放的是Thread则代表着其存放的是其后继结点。
线索二叉树的实现
中序遍历模型
代码实现
#include<iostream>
using namespace std;
//线索化标志Tag
enum PointerTag {THREAD, LINK};
//结点结构
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>
struct __BinaryTreeIterator
{
typedef BinaryTreeNodeThd<T> Node;
typedef __BinaryTreeIterator<T> Self;
Node* _node;
__BinaryTreeIterator(Node* node)
:_node(node)
{}
T& operator*()
{
return _node->_data;
}
T* operator->()
{
return &(_node->_data);
}
bool operator ==(const Self& s)
{
return (_node == s._node);
}
bool operator != (const Self& s)
{
return (_node != s._node);
}
virtual Self& operator++() = 0;//纯虚函数
};
//中序遍历迭代器
template<class T>
struct __BinaryTreeInInterator :public __BinaryTreeIterator<T>
{
typedef BinaryTreeNodeThd<T> Node;
typedef __BinaryTreeInInterator<T> Self;
__BinaryTreeInInterator(Node* node)
:__BinaryTreeIterator(node)
{}
Self& operator++()
{
if (_node->_rightTag == THREAD)
{
_node = _node->_right;
}
else
{
Node* sub = _node->_right;
if (sub && sub->_leftTag == LINK)
{
sub = sub->_left;
}
_node = sub;
}
return *this;
}
};
//前序遍历迭代器
template<class T>
struct __BinaryTreePrevInterator :public __BinaryTreeIterator<T>
{
typedef BinaryTreeNodeThd<T> Node;
typedef __BinaryTreePrevInterator<T> Self;
__BinaryTreePrevInterator(Node* node)
:__BinaryTreeInterator(node)
{}
Self& operator++()
{
if (_node->_leftTag == LINK)
{
_node = _node->_left;
}
else
{
_node = _node->_right;
}
return *this;
}
};
//二叉树的线索化
template <class T>
struct BinaryTreeThd
{
typedef BinaryTreeNodeThd<T> Node;
typedef __BinaryTreeInInterator<T> InInterator;
typedef __BinaryTreePrevInterator<T> PrevInterator;
public:
BinaryTreeThd(T* a, size_t n, const T& invalid)
{
size_t index = 0;
_root = _CreateTree(a, n, index, invalid);
}
PrevInterator PrevBegin()
{
return root;
}
PrevInterator PrevEnd()
{
return NULL;
}
InInterator InBegin()
{
Node* sub = _root;
while (sub && sub->_leftTag == LINK)
{
sub = sub->_left;
}
return sub;
}
InInterator InEnd()
{
return NULL;
}
void InOrder()
{
_InOrder(_root);
cout << endl;
}
void InOrderThreading()
{
Node* prev = NULL;
_InOrderThreading(_root, prev);
}
protected:
Node* _CreateTree(T* a, size_t n, size_t& index, const T& invalid)
{
Node* root = NULL;
if (index < n && a[index] != invalid)
{
root = new Node(a[index]);
root->_left = _CreateTree(a, n, ++index, invalid);
root->_right = _CreateTree(a, n, ++index, invalid);
}
return root;
}
void _InOrder(Node* root)
{
if (root == NULL)
{
return;
}
_InOrder(root->_left);
cout << root->_data << ' ';
_InOrder(root->_right);
}
void _InOrderThreading(Node* root, Node*& prev)
{
if (root == NULL)
return;
_InOrderThreading(root->_left, prev);
if (root->_left == NULL)
{
root->_left = prev;
root->_leftTag = THREAD;
}
if (prev && prev->_right == NULL)
{
prev->_right = root;
prev->_rightTag = THREAD;
}
prev = root;
_InOrderThreading(root->_right, prev);
}
private:
Node* _root;
};
测试用例
void TestBinaryTreeThd()
{
int a1[] = {1, 2, 3, '#', '#', 4, '#' , '#', 5, 6};
BinaryTreeThd<int> t1(a1, sizeof(a1)/sizeof(a1[0]), '#');
t1.InOrder();
t1.InOrderThreading();
实现结果
References
http://blog.csdn.net/u014492609/article/details/40477795
http://blog.csdn.net/my_heart_/article/details/52086321