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

原创 2016年05月30日 16:59:40

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

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







实现源代码:

#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;

}

运行结果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

请按任意键继续. . .


版权声明:本文为博主原创文章,未经博主允许不得转载。

C++实现中序线索二叉树

//线索二叉树的实现 #include "stdafx.h" #include using namespace std; enum flag{ Child, Thread }; ...

线索化二叉树C++

线索化二叉树 1.创建二叉树 2.先序递归遍历输出二叉树 3.线索化二叉树 4.输出线索化二叉树...
  • J_Anson
  • J_Anson
  • 2015年11月19日 10:15
  • 690

线索二叉树的原理以及创建和遍历(c++)

这是一篇非常好的关于线索二叉树的文章,内容详细到位,叙述清晰。作者是以为很认真、信息的人,估计花了不少时间和精力,向作者致敬! 引用地址:http://waret.iteye.com/blog/70...
  • wbcg111
  • wbcg111
  • 2016年03月26日 10:31
  • 1173

C++实现二叉树及其线索化和遍历

/* * BiTree.h * * Created on: Oct 17, 2015 * Author: chris */ #ifndef BITREE_H_ #define ...

二叉树的线索化(C++实现)

关于四种遍历方式的递归和非递归实现可点击 我的github 里面的BInaryTree.h查看。 我们希望很快找到某的结点的前序或者后继,又不想遍历一遍,这就需要我们记录下每个结点的前驱和后继,因此为...

二叉树的线索化实现

  • 2011年11月21日 14:36
  • 6KB
  • 下载

【C++】后序线索化二叉树及其遍历

#include using namespace std; enum PointTag { LINK, THREAD, }; struct BinTreeThingNode { char _d...
  • ZDF0414
  • ZDF0414
  • 2015年11月28日 13:57
  • 683

C++实现线索二叉树 -- 创建遍历查找等操作

本文代码为C++实现线索二叉树,文中所有代码均经过测试。 #ifndef _THREAD_BIN_TREE_H #define _THREAD_BIN_TREE_H #include #inclu...

c++线索二叉树源代码

  • 2011年05月22日 03:28
  • 248KB
  • 下载

中序线索化二叉树及中序遍历

  • 2008年04月01日 21:43
  • 2KB
  • 下载
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:用c++实现二叉树的线索化
举报原因:
原因补充:

(最多只允许输入30个字)