您的位置:首页 > 编程语言 > C语言/C++

c++ 二叉树的线索化(前中后序遍历)

2016-03-16 15:40 351 查看
#pragma once//.hpp函数头文件

#include<iostream>

using namespace std;

enum BinTreeNodeChildType
{
Thread,
Link
};

template <class T>
struct BinaryTreeThrNode
{
public:
T _data;  //数据域
BinaryTreeThrNode<T>* _leftChild;//做孩子
BinaryTreeThrNode<T>* _rightChild;//右孩子
BinTreeNodeChildType _leftType;//左节点类型
BinTreeNodeChildType _rightType;//右节点类型
BinaryTreeThrNode<T>* _parent;//父节点  (后续线索化 遍历 用到)

public:
BinaryTreeThrNode(const T& data)
:_data(data)
, _leftChild(NULL)
, _rightChild(NULL)
, _leftType(Link)
, _rightType(Link)
, _parent(NULL)
{}

~BinaryTreeThrNode()
{}
};

template <class T>
class BinaryTreeThread
{
public:
BinaryTreeThrNode<T>* _root;
public:
BinaryTreeThread()
:_root(NULL)
{}

BinaryTreeThread(T*a, size_t size)
{
size_t index = 0;
_root = _CreateBiTree(a, index, size);
}

void InOrderThread()
{
BinaryTreeThrNode<T>* prev = NULL;
BinaryTreeThrNode<T>* cur = _root;
_InOrderThread(cur,prev );
}

void PreOrderThread()
{
BinaryTreeThrNode<T>* prev = NULL;
_PreOrderThread(_root,prev);
}

void InOrderThe1()  //cur每次循环跳一次
{
BinaryTreeThrNode<T>* cur = _root;
BinaryTreeThrNode<T>*prev = _root;
while (cur)
{
if (cur->_leftChild&&prev->_rightChild != cur&&cur->_leftType == Link)
cur = cur->_leftChild;
else
{
cout << cur->_data << ' ';
if (cur->_rightType == Thread)
prev = cur;
cur = cur->_rightChild;
}
}
}
void InOrderThe()  //cur每次循环中有循环
{
BinaryTreeThrNode<T>* cur = _root;
while (cur)
{
while (cur&&cur->_leftType == Link)
{
cur = cur->_leftChild;
}
cout << cur->_data << ' ';
while (cur&&cur->_leftType== Thread)
{
cur = cur->_rightChild;
cout << cur->_data<<' ';
}
cur = cur->_rightChild;
}
}

//前序线索遍历
void PreOrderThe()
{
BinaryTreeThrNode<T>* cur = _root;
while (cur&&cur->_rightChild)
{
while (cur->_leftType != Thread)
{
cout << cur->_data << ' ';
cur = cur->_leftChild;
}
while (cur->_rightType == Thread)
{
cout << cur->_data << ' ';
cur = cur->_rightChild;
if (cur->_rightChild == NULL)
cout << cur->_data << ' ';

}
}

}
//后续线索遍历
void PostOrderThe1()//老师的方法
{
if (_root == NULL)
return;

BinaryTreeThrNode<T>* cur = _root->_left;
BinaryTreeThrNode<T>* prev = NULL;

while (cur != _root)
{
// 1.找最左节点
while (cur && cur->_leftTag == LINK)
cur = cur->_left;

while (cur && cur->_rightTag == THREAD)
{
cout << cur->_data << " ";
prev = cur;
cur = cur->_right;
}

// 当跳到root则遍历完成
if (cur == _root)
{
cout << _root->_data << " ";
break;
}

// 一个节点的右树已经访问完成,则跳转到根节点
if (cur && cur->_rightTag == LINK
&& cur->_right == prev)
{
cout << cur->_data << " ";
prev = cur;

cur = cur->_parent;
}

// 往右树跳转
if (cur && cur->_rightTag == LINK)
{
cur = cur->_right;
}
}

cout << endl;
}

void PosOrderThe()//后续线索遍历(借助 父节点)
{
BinaryTreeThrNode<T>* cur = _root;
BinaryTreeThrNode<T>* prev = NULL;//防止死循环的记录指针
while (cur)
{

while (prev!=cur->_leftChild&&cur!=prev&&cur->_leftType != Thread)//左支不为Thread且 prev不为cur坐支且prev!=cur 循环压左
cur = cur->_leftChild;
if (prev==cur&&cur->_rightType == Link)//右支不为Thread类型 压右
cur = cur->_rightChild;
else
{
while (cur->_rightType == Thread)  //右支为Thread类型 循环压右  输出
{

cout << cur->_data << ' ';
cur = cur->_rightChild;
prev= cur;
}
cout << cur->_data << ' ';
cur = cur->_parent;
if (cur&&cur->_rightType == Link&&cur->_leftChild==prev)
{
prev = cur;//prev始终为右支返回的父节点
}
}
if (cur == _root&&prev != cur)//prev是从右支返回的并且 cur为根节点结束循环
{
cout << cur->_data << ' ';
break;
}
}
}
//后续线索化
void PosOrderThread()
{
BinaryTreeThrNode<T>* prev = NULL;
_PosOrderThread(_root,prev);
}

BinaryTreeThrNode<T>* _CreateBiTree(const T* tmp,  size_t& index, size_t size)
{
BinaryTreeThrNode<T>* root = NULL;
BinaryTreeThrNode<T>* parent = NULL;
if (index < size&&tmp[index] != '#')
{

root = new BinaryTreeThrNode<T>(tmp[index]);
parent=_CreateBiTree(tmp, ++index, size);
if (parent)
{
root->_leftChild = parent;
parent->_parent = root;
}
parent = _CreateBiTree(tmp, ++index, size);

}
if (parent)
{
root->_rightChild = parent;
parent->_parent = root;
}
return root;
}

//中序线索化

void _InOrderThread(BinaryTreeThrNode<T>*cur,BinaryTreeThrNode<T>* & prev)
{
if (cur ==NULL)
return;
_InOrderThread(cur->_leftChild,prev);//向左树遍历
if (cur->_leftChild==NULL)            //左为空  改变左类型 左指向prev
{
cur->_leftType = Thread;
cur->_leftChild = prev;

}
if (prev&&prev->_rightChild == NULL) //prev!=NULL 且prev右不空 改变右类型 让右指向当前
{
prev->_rightType = Thread;
prev->_rightChild = cur;
}
prev = cur;                          //prev指向递归返回前的节点
_InOrderThread(cur->_rightChild, prev);  //指向右数节点

}

//前序线索化 自己的笨办法
void _PreOrderThread1(BinaryTreeThrNode<T>* cur, BinaryTreeThrNode<T>* &prev)
{
if (cur == NULL)
return;
if (prev&&prev->_rightType == Thread&&prev->_rightChild==NULL)//给右为空的左节点
prev->_rightChild = cur;
if (cur->_leftChild)//左不空  压左
{
prev = cur;   //prev=上个节点
_PreOrderThread(cur->_leftChild, prev);
}
else
{
cur->_leftType = Thread;//左空  左节点类型为线索类型
cur->_leftChild = prev;//线索指向prev
}
if (cur->_rightChild)//右不为空
{
_PreOrderThread(cur->_rightChild, prev);//压右
}
else
{

if (prev&&prev->_rightType==Thread&&cur->_leftType==Link&&cur->_rightChild==NULL)
cur->_rightChild =prev;//判断是否该节点为只有左分支 是的话使右线索指向左分支
cur->_rightType = Thread;//右分支为线索类型
if (cur->_rightChild==NULL)//不连续压左情况  右分支为空  使prev=cur
prev = cur;
}
}

void _PreOrderThread(BinaryTreeThrNode<T>* cur, BinaryTreeThrNode<T>* &prev)//老师方法
{
if (cur == NULL)//空返回
return;
if (cur->_leftChild == NULL)//左植线索化  当前递归中
{
cur->_leftType = Thread;
cur->_leftChild = prev;
}
if (prev&&prev->_rightChild == NULL)//右植线索化 返回上次递归中
{
prev->_rightType = Thread;
prev->_rightChild = cur;
}

prev = cur; //prev为上次递归cur

if (cur->_leftType==Link)//cur左值类型为节点类型 继续递归
_PreOrderThread(cur->_leftChild, prev);
if (cur->_rightType==Link)//cur右植类型为节点类型 继续递归
_PreOrderThread(cur->_rightChild, prev);
}

//后续线索化
void _PosOrderThread(BinaryTreeThrNode<T>* cur,BinaryTreeThrNode<T>*& prev)
{
if (cur == NULL)
return;

if (cur->_leftChild == NULL)//作为空左支线索化=prev
{
cur->_leftType = Thread;
cur->_leftChild = prev;
}

if (cur->_leftType==Link)//cur左支类型为节点类型  递归左
_PosOrderThread(cur->_leftChild,prev);

if (cur->_rightType==Link)//cur右植为节点类型  递归右
_PosOrderThread(cur->_rightChild,prev);
if (prev&&prev->_rightChild == NULL)  //prev右植为空  prev指向当前
{
prev->_rightType = Thread;
prev->_rightChild = cur;
}
prev = cur;  //子树递归结束 prev=cur

}
};

//测试用例
#include"bintreethread.hpp"
#include"BinaryTreeThreading.h"

using namespace std;

void test()
{
int a[10] = { 1, 2, 3, '#', '#',4, '#', '#', 5, 6 };
int s[18] = { 1, 2, 3, 4, '#', '#', 5, '#', '#', 6, '#', '#', 7, 8, '#', '#', 9, 10 };
int k[14] = { 1, 2, 3, 4, '#','#','#',5,'#','#', 6, 7,'#','#' };
BinaryTreeThread<int> s1;
BinaryTreeThread<int> s2(s,18);
//BinaryTreeThread<int> s2(k, 14);
//BinaryTreeThread<int> s2(a, 10);

/*s2.InOrderThread();
s2.InOrderThe();*/
//s2.PreOrderThread();

s2.PosOrderThread();
s2.PosOrderThe();
}

int main()
{
test();
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: