二叉树的线索化算法思想详解
2016-05-28 18:36
232 查看
二叉树的线索化,这几天以来我很难掌握,今天终于想通了,哈哈,首先我们来看看二叉树线索化之后会变成什么样子,这里我们以图中的二叉树为例,图如下:
![](http://s2.51cto.com/wyfs02/M02/7F/9E/wKioL1clqWXAc9hmAAAeyeZzebo767.png)
画的太糙,各位看官讲究着看吧- -。所谓二叉树的线索化,就是当一个节点的左右指针为空时,就让它的左右指针指向该节点的前驱或者后继(一般来说左指针指向前驱,右指针指向后继)。这里不论指向前驱或者后继,我们都应该线索化时,至少要明确两个节点指针的值,当前节点和当前节点的前驱/后继。这也是线索化的两种思路:
保存前驱:访问当前节点时若当前节点的左指针为空,则令左指针指向前驱,若前驱的右指针为空,则令前驱的右指针指向当前节点,代码描述如下:
void visit(NODE* cur,NODE* &prev)//当前指针的前驱在当前指针访问时会改变,故传引用用来改变//prev
{
if(prev->right==NULL;
prev->right=cur;
if(cur->left==NULL)
cur->left=prev;
prev=cur;
} 这里我们要注意的是应该先进行访问,最后再改变prev的值。
保存后继:这种方法很难做到,并且个人觉得没有什么意义,因为在遍历整个数的过程中我们始终都会访问到一个节点的后继,若将要访问后继那我们如何保存到未来的东西,即使通过类似栈的数据结构通过压栈来强行访问,效率也是不高的,在此不推荐。
接下来献上c++完整的线索二叉树结构以及中序线索化过程,通过递归与非递归两种方式实现,其他的都大同小异。
节点类定义如下:
typedef char Datatype;
enum NodeType
{
LINK,
THERAD
};
struct TheardBinaryTreeNode
{
TheardBinaryTreeNode* _left;
TheardBinaryTreeNode* _right;
NodeType _leftTag;
NodeType _rightTag;
Datatype _data;
TheardBinaryTreeNode(const Datatype & data)
:_left(NULL)
, _right(NULL)
, _leftTag(LINK)
, _rightTag(LINK)
,_data(data)
{}
TheardBinaryTreeNode()
: _left(NULL)
, _right(NULL)
, _leftTag(LINK)
, _rightTag(LINK)
,_data((Datatype)0)
{}
}; 中序线索化如下:
void InTherad()
{
NODE* prev = NULL;
_InTherad(_root, prev);
//stack<NODE*>s;//借助栈来实现非递归的中序线索化
//NODE* cur = _root;
//NODE* prev = NULL;
//while (!s.empty()||cur)
//{
// while (cur)
// {
// s.push(cur);
// cur = cur->_left;
// }
// NODE* top = s.top();
// s.pop();
// if (top->_left == NULL&&top->_leftTag == LINK)
// {
// top->_left = prev;
// top->_leftTag = THERAD;
// }
// prev = top;
// if (top->_right == NULL&&top->_rightTag==LINK)
// {
// top->_rightTag = THERAD;
// if (!s.empty())
// top->_right = s.top();
// }
// else
// cur = top->_right;
//}
}
void _InTherad(NODE*root, NODE* &prev)//递归的中序线索化
{
if (root == NULL)
return;
_InTherad(root->_left, prev);
if (prev&&prev->_rightTag == LINK&&prev->_right == NULL)
{
prev->_right = root;
prev->_rightTag = THERAD;
}
if (root->_leftTag == LINK&&root->_left == NULL)
{
root->_leftTag = THERAD;
root->_left = prev;
prev = root;
}
_InTherad(root->_right,prev);
} 如有不足或者疑问希望留言提出。3Q -3-。
本文出自 “pawnsir的IT之路” 博客,请务必保留此出处http://10743407.blog.51cto.com/10733407/1769333
![](http://s2.51cto.com/wyfs02/M02/7F/9E/wKioL1clqWXAc9hmAAAeyeZzebo767.png)
画的太糙,各位看官讲究着看吧- -。所谓二叉树的线索化,就是当一个节点的左右指针为空时,就让它的左右指针指向该节点的前驱或者后继(一般来说左指针指向前驱,右指针指向后继)。这里不论指向前驱或者后继,我们都应该线索化时,至少要明确两个节点指针的值,当前节点和当前节点的前驱/后继。这也是线索化的两种思路:
保存前驱:访问当前节点时若当前节点的左指针为空,则令左指针指向前驱,若前驱的右指针为空,则令前驱的右指针指向当前节点,代码描述如下:
void visit(NODE* cur,NODE* &prev)//当前指针的前驱在当前指针访问时会改变,故传引用用来改变//prev
{
if(prev->right==NULL;
prev->right=cur;
if(cur->left==NULL)
cur->left=prev;
prev=cur;
} 这里我们要注意的是应该先进行访问,最后再改变prev的值。
保存后继:这种方法很难做到,并且个人觉得没有什么意义,因为在遍历整个数的过程中我们始终都会访问到一个节点的后继,若将要访问后继那我们如何保存到未来的东西,即使通过类似栈的数据结构通过压栈来强行访问,效率也是不高的,在此不推荐。
接下来献上c++完整的线索二叉树结构以及中序线索化过程,通过递归与非递归两种方式实现,其他的都大同小异。
节点类定义如下:
typedef char Datatype;
enum NodeType
{
LINK,
THERAD
};
struct TheardBinaryTreeNode
{
TheardBinaryTreeNode* _left;
TheardBinaryTreeNode* _right;
NodeType _leftTag;
NodeType _rightTag;
Datatype _data;
TheardBinaryTreeNode(const Datatype & data)
:_left(NULL)
, _right(NULL)
, _leftTag(LINK)
, _rightTag(LINK)
,_data(data)
{}
TheardBinaryTreeNode()
: _left(NULL)
, _right(NULL)
, _leftTag(LINK)
, _rightTag(LINK)
,_data((Datatype)0)
{}
}; 中序线索化如下:
void InTherad()
{
NODE* prev = NULL;
_InTherad(_root, prev);
//stack<NODE*>s;//借助栈来实现非递归的中序线索化
//NODE* cur = _root;
//NODE* prev = NULL;
//while (!s.empty()||cur)
//{
// while (cur)
// {
// s.push(cur);
// cur = cur->_left;
// }
// NODE* top = s.top();
// s.pop();
// if (top->_left == NULL&&top->_leftTag == LINK)
// {
// top->_left = prev;
// top->_leftTag = THERAD;
// }
// prev = top;
// if (top->_right == NULL&&top->_rightTag==LINK)
// {
// top->_rightTag = THERAD;
// if (!s.empty())
// top->_right = s.top();
// }
// else
// cur = top->_right;
//}
}
void _InTherad(NODE*root, NODE* &prev)//递归的中序线索化
{
if (root == NULL)
return;
_InTherad(root->_left, prev);
if (prev&&prev->_rightTag == LINK&&prev->_right == NULL)
{
prev->_right = root;
prev->_rightTag = THERAD;
}
if (root->_leftTag == LINK&&root->_left == NULL)
{
root->_leftTag = THERAD;
root->_left = prev;
prev = root;
}
_InTherad(root->_right,prev);
} 如有不足或者疑问希望留言提出。3Q -3-。
本文出自 “pawnsir的IT之路” 博客,请务必保留此出处http://10743407.blog.51cto.com/10733407/1769333
相关文章推荐
- 【代码】C++实现二叉树基本操作及测试用例
- 【代码】C++实现广义表及其测试用例
- 【智能指针的延伸】两种定制删除器的实现方法
- 【干货】share智能指针的模拟实现
- 【代码】模板动态线性表&类型萃取
- 【技巧】通过适配器模式完成栈的数据结构
- 【代码】模板实现动态线性表(无类型萃取)
- 解决 NSObjCRuntime的问题
- 【干货】C++通过模板特化实现类型萃取实例--实现区分基本类型与自定义类型的memcpy
- 【代码】模板实现双向链表的去重、拼接、合并、排序
- 关于mybatis的collection映射问题
- 【探索】VS下实现虚继承的方法-2
- 【总结】C++静态成员函数及测试用例
- 15种最佳系统日志优化实践
- 【总结】C++静态成员变量的特性总结及测试用例
- 【总结】C++静态成员变量的特性总结及测试用例
- 求N个数的最小公倍数
- WPF模板
- 【总结】C++基类与派生类的赋值兼容规则
- 【总结】逆置双向链表的三种方法