二叉树的缺点:
在二叉树的数据结构里面,如果是利用递归的方式创建的,那么就存在栈溢出的缺陷,如果采用循环的方式创建的话,那么就存在着空间复杂度过高的缺点。
同时在二叉树里面如果含有N个结点的话,那么没有使用的结点指针就含有(N+1)个,那么就造成大量的结点指针浪费。
解决方法
如果在创建二叉树的时候将这些没有使用的结点指针用来存储这些结点的前驱和后继结点 ,那么在遍历的时候就会更加的方便。
前序线索化:
- 将二叉树线索化之后,那么遍历二叉树的元素就会大大减少对内存的浪费。
前序线索化代码:
void PreThrade(Node* root,Node*& prev) //Thrade from front
{
if(NULL == root)
return ;
if(NULL == root->leftTree)
{
root->leftTree = prev;
root->leftThrade = THRADE;
}
if(prev && NULL == prev->rightTree)
{
prev->rightTree = root;
prev->rightThrade = THRADE;
}
prev = root;
if(LINK == prev->leftThrade)
{
_PreThrade(root->leftTree,prev);
}
if(LINK == root->rightThrade)
{
_PreThrade(root->rightTree,prev);
}
}
- 中序线索化二叉树
中序线索化代码:
void _InThrade(Node* root,Node*& prev) //Thrade tree from mid
{
if(NULL == root)
return ;
if(LINK == root->leftThrade)
_InThrade(root->leftTree,prev);
if(NULL == root->leftTree)
{
root->leftTree = prev;
root->leftThrade = THRADE;
}
if(prev && NULL == prev->rightTree)
{
prev->rightTree = root;
prev->rightThrade = THRADE;
}
prev = root;
if(LINK == root->rightThrade)
_InThrade(root->rightTree,prev);
}
- 后序线索化二叉树
后序线索化代码:
void _BackThrade(Node* root,Node*& prev) //Theade tee from back
{
if(NULL == root)
return ;
if(LINK == root->leftThrade)
_BackThrade(root->leftTree,prev);
if(LINK == root->rightThrade)
_BackThrade(root->rightTree,prev);
if(NULL == root->leftTree)
{
root->leftTree = prev;
root->leftThrade = THRADE;
}
if(prev && NULL == prev->rightThrade)
{
prev->rightTree = root;
prev->rightThrade = THRADE;
}
prev = root;
}
- 线索化二叉树的前序遍历:
- 代码
void _PreOrder(Node* root)
{
if(NULL == root)
return ;
while(root)
{
while(LINK == root->leftThrade)
{
cout<<root->data<<" ";
if(root->leftTree)
root = root->leftTree;
}
if(NULL == root)
return ;
cout<<root->data<<" ";
root = root->rightTree;
if(NULL == root)
return ;
while(THRADE == root->rightThrade && NULL != root->rightTree)
{
cout<<root->data<<" ";
root = root->rightTree;
}
}
}
- 后序线索化遍历:
代码:
void _BackOrder(Node* root,Node* prev)
{
if(NULL == root)
return ;
Node* cur = root;
while(cur)
{
while(cur->leftTree != prev && cur->leftThrade == LINK) //走完树的左子树
cur = cur->leftTree;
while(cur && cur->rightThrade == THRADE) //走连在一起的后继结点
{
cout<<cur->data<<" ";
prev = cur;
cur = cur->rightTree;
}
if(root == cur) //判断cur是不是根结点
{
cout<<cur->data<<" ";
return ;
}
while(cur && cur->rightTree == prev)
{
cout<<cur->data<<" ";
prev = cur;
cur = cur->parent;
}
if(cur && cur->rightThrade == LINK)
cur = cur->rightTree;
}
}
- 注:这里的的后序遍历的时候要考虑左单支和右单支的情况!!