二叉树的线索化

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

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

enum PointerTag {THREAD, LINK};

template <class T>
struct BinaryTreeNode_Thd
{
     T _data ;                         // 数据
     BinaryTreeNode_Thd<T >* _left;   // 左孩子
     BinaryTreeNode_Thd<T >* _right // 右孩子
     PointerTag   _leftTag ;          // 左孩子线索标志
     PointerTag   _rightTag ;         // 右孩子线索标志
};



代码实现:
#pragma once
#include<iostream>  
#include<assert.h>  
#include<stack>
using namespace std;


enum PointerTag

LINK,
THREAD 
};


template<class T>
struct BinaryTreeNode_Thd
{
BinaryTreeNode_Thd(const T& d)
:_data(d)
, _left(NULL)
, _right(NULL)
, _leftTag(LINK)
, _rightTag(LINK)
{}
T _data;
BinaryTreeNode_Thd<T>* _left;//左孩子  
BinaryTreeNode_Thd<T>* _right;//右孩子  
PointerTag _leftTag;//左孩子线索化标志  
PointerTag _rightTag;//右孩子线索化标志  
};
template<class T>
class BinaryTreeThd
{
typedef  BinaryTreeNode_Thd<T> Node;
public:
BinaryTreeThd()
:_root(NULL)
{}
BinaryTreeThd(const T* a, size_t size, const T& invalid)
{
size_t index = 0;
_root = _CreatTree(a, size, index, invalid);
}
void InOrderTheading()//中序线索化  
{
Node* prev = NULL;
_InOrderTheading(_root, prev);
}
void InOrderThd()//中序遍历  
{
Node* cur = _root;
while (cur)
{
while (cur != NULL&&cur->_leftTag == LINK)//找树的最左节点  
{
cur = cur->_left;
}
cout << cur->_data << " ";
while (cur->_rightTag == THREAD)
{
cur = cur->_right;
cout << cur->_data << " ";
}
cur = cur->_right;
}
cout << endl;
}
void PrevOrderTheading()//前序线索化  
{
Node* prev = NULL;
_PrevOrderTheading(_root, prev);
}
void PrevOrderThd()//前序遍历  
{
Node* cur = _root;
while (cur)
{
while (cur&&cur->_leftTag == LINK)
{
cout << cur->_data << " ";
cur = cur->_left;
}
cout << cur->_data << " ";
cur = cur->_right;
}
cout << endl;
}
void PostOrderTheading()//后序线索化  
{
Node* prev = NULL;
_PostOrderTheading(_root, prev);
}
void PostOrderThd()
{
stack<Node*> s;
Node* cur = _root;
while (cur)
{
while (cur && cur->_rightTag == LINK)
{
s.push(cur);
cur = cur->_right;
}
s.push(cur);
cur = cur->_left;
}
while (!s.empty())
{
cout << s.top()->_data << " ";
s.pop();
}
cout << endl;
}


protected:
Node* _CreatTree(const T *a, size_t size, size_t &index, const T& invalid)//建立二叉树  
{
assert(a);
Node* node = NULL;
if (a[index] != invalid && index < size)
{
node = new Node(a[index]);
node->_left = _CreatTree(a, size, ++index, invalid);
node->_right = _CreatTree(a, size, ++index, invalid);
}
return node;
}
void _InOrderTheading(Node *cur, Node* &prev)//递归方法中序线索化  
{
if (cur == NULL)
return;
_InOrderTheading(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;
_InOrderTheading(cur->_right, prev);
}
void _PrevOrderTheading(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)
_PrevOrderTheading(cur->_left, prev);
if (cur->_rightTag == LINK)
_PrevOrderTheading(cur->_right, prev);
}
void _PostOrderTheading(Node *cur, Node* &prev)//递归方法后序线索化  
{
if (cur == NULL)
return;
_PostOrderTheading(cur->_left, prev);
_PostOrderTheading(cur->_right, prev);
if (cur->_left == NULL)
{
cur->_leftTag = THREAD;
cur->_left = prev;
}
if (prev && prev->_right == NULL)
{
prev->_rightTag = THREAD;
prev->_right = cur;
}
prev = cur;
}
private:
Node* _root;
};


void Test()
{
int array1[10] = { 1, 2, 3, '#', '#', 4, '#', '#', 5, 6 };
BinaryTreeThd <int>t1(array1, 10, '#');
t1.InOrderTheading();//中序
t1.InOrderThd();
//t1.PrevOrderTheading();//前序
//t1.PrevOrderThd();
//t1.PostOrderTheading();//后序
//t1.PostOrderThd();
}

#define _CRT_SECURE_NO_WARNINGS 1
#include"BinaryTreeThreading.h"


int main()
{
Test();
system("pause");
return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值