中序线索化(递归):
图形解析:
代码如下:
//中序线索化
void InorderThreading()
{
Node* prev = NULL;
_InoderThreading(_root, prev);
}
void _InoderThreading(Node* cur, Node* & prev)
{
if (cur)
{
_InoderThreading(cur->_left, prev);
if (NULL == cur->_left)//当前节点的左节点需要线索化
{
cur->_left = prev;
cur->_leftType = THREAD;
}
if (prev && NULL == prev->_right)//当前节点的前驱的右节点需要线索化
{
prev->_right = cur;
prev->_rightType = THREAD;
}
prev = cur;//更新prev
_InoderThreading(cur->_right, prev);
}
}
中序遍历中序线索化:
代码如下:
//中序遍历
void InOrder()
{
_InOrder(_root);
cout << endl;
}
//中序线索二叉树的中序遍历算法
void InorderThd()
{
Node* cur = _root;
while (cur)
{
//查找最左节点
while (cur->_leftType == LINK)
{
cur = cur->_left;
}
cout << cur->_data << " ";
//方法1
while (cur->_rightType == THREAD)
{
cur = cur->_right;
if (NULL == cur)
{
return;
}
cout << cur->_data << " ";
}
//执行到此处-->说明右节点为右子树
cur = cur->_right;
}
}
前序线索化二叉树:
void _PreOrderThreading(Node* cur,Node*& prev)
{
if (NULL == cur)
{
return;
}
if (NULL == cur->_left)
{
cur->_left = prev;
cur->_leftType = THREAD;
}
if (prev && NULL == prev->_right)
{
prev->_right = cur;
prev->_rightType = THREAD;
}
prev = cur;//更新prev的值
if (cur->_leftType == LINK)//因为是先线索化后进行递归,为了避免死循环,所以需要判断
{
_PreOrderThreading(cur->_left, prev);
}
if (cur->_rightType == LINK)
{
_PreOrderThreading(cur->_right, prev);
}
}
前序遍历前序线索化二叉树:
前序线索化二叉树的前序遍历算法(下面的代码很坑、有问题):
//前序遍历二叉树
void PreOrderThd()
{
Node* cur = _root;
while (cur)
{
//访问左子树
while (cur->_leftType == LINK)
{
cout << cur->_data << " ";
cur = cur->_left;
}
//此时的cur->_leftType == THREAD
cout << cur->_data << " ";
//1.子问题 2.cur->_rightType = THREAD
while (cur->_rightType == THREAD)
{
cur = cur->_right;
cout << cur->_data << " ";
}
cur = cur->_right;//子问题
}
}
测试代码1如下:
int array1[10] = { 1, 2, 3, '#', '#', 4, '#', '#', 5, 6 };
BinaryTreeThd<int> bt1(array1, sizeof(array1) / sizeof(int), '#');
bt1.PreOrder();
bt1.PreOrderThreading();
bt1.PreOrderThd();
结果如下:
测试代码2如下:
int array[15] = { 1, 2, '#', 3, '#', '#', 4, 5, '#', 6, '#', 7, '#', '#', 8 };
BinaryTreeThd<int> bt(array, sizeof(array) / sizeof(int), '#');
bt.PreOrder();
bt.PreOrderThreading();
bt.PreOrderThd();
很明显,结果不对,下面我们来仔细分析其中存在的问题:
将上面的程序改之:
//前序遍历二叉树
void PreOrderThd()
{
Node* cur = _root;
while (cur)
{
//访问左子树
while (cur->_leftType == LINK)
{
cout << cur->_data << " ";
cur = cur->_left;
}
//此时的cur->_leftType == THREAD
cout << cur->_data << " ";
cur = cur->_right;
}
}
测试代码如下:
void TestBinary()
{
int array1[10] = { 1, 2, 3, '#', '#', 4, '#', '#', 5, 6 };
BinaryTreeThd<int> bt1(array1, sizeof(array1) / sizeof(int), '#');
bt1.PreOrder();
bt1.PreOrderThreading();
bt1.PreOrderThd();
cout << endl;
int array[15] = { 1, 2, '#', 3, '#', '#', 4, 5, '#', 6, '#', 7, '#', '#', 8 };
BinaryTreeThd<int> bt(array, sizeof(array) / sizeof(int), '#');
bt.PreOrder();
bt.PreOrderThreading();
bt.PreOrderThd();
}
结果如下:
代码如下:
#pragma once
#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
#include <assert.h>
using namespace std;
enum PointerType
{
LINK,
THREAD,
};
template<class T>
struct BinaryTreeThdNode
{
BinaryTreeThdNode(const T& value)
:_data(value)
, _left(NULL)
, _right(NULL)
, _leftType(LINK)
, _rightType(LINK)
{}
T _data;
BinaryTreeThdNode<T>* _left;
BinaryTreeThdNode<T>* _right;
PointerType _leftType;//标记是否需要线索化
PointerType _rightType;
};
template<class T>
class BinaryTreeThd
{
typedef BinaryTreeThdNode<T> Node;
public:
BinaryTreeThd(const Node* node)
:_root(node)
{}
BinaryTreeThd(const T* arr, size_t size, const T& invalid)
{
size_t index = 0;
_root = _CreatTree(arr, size, invalid, index);
}
//先序遍历
void PreOrder()
{
_PreOrder(_root);
cout << endl;
}
//中序遍历
void InOrder()
{
_InOrder(_root);
cout << endl;
}
//后序遍历
void PostOrder()
{
_PostOrder(_root);
cout << endl;
}
//中序线索化
void InorderThreading()
{
Node* prev = NULL;
_InoderThreading(_root, prev);
}
//中序线索二叉树的中序遍历算法
void InorderThd()
{
Node* cur = _root;
while (cur)
{
//查找最左节点
while (cur->_leftType == LINK)
{
cur = cur->_left;
}
cout << cur->_data << " ";
//方法1
while (cur->_rightType == THREAD)
{
cur = cur->_right;
if (NULL == cur)
{
return;
}
cout << cur->_data << " ";
}
//执行到此处-->说明右节点为右子树
cur = cur->_right;
}
}
//前序线索二叉树的前序遍历算法
void PreOrderThreading()
{
Node* prev = NULL;
_PreOrderThreading(_root, prev);
if (NULL == prev)
{
prev->_rightType = THREAD;
}
}
void PreOrderThd()
{
if (NULL == _root)
{
return;
}
Node* cur = _root;
while (cur)
{
//访问根节点
cout << cur->_data << " ";
//访问左子树
while (cur->_leftType == LINK)
{
cur = cur->_left;
cout << cur->_data << " ";
}
//此时的cur->_leftType == THREAD
while (cur->_rightType == THREAD)
{
cur = cur->_right;
cout << cur->_data << " ";
}
cur = cur->_right;//子问题
}
}
//后序线索化二叉树
void PostOrderThreading()
{
Node* prev = NULL;
_PostOrderThreading(_root,prev);
}
//后序遍历
void PostOrderThd()
{
if (NULL == _root)
{
return;
}
Node* cur = NULL;
while (cur)
{
while (LINK == cur->_leftType || Link == cur->_rightType)
{
if (LINK == cur->_leftType)
{
cur = cur->_left;
}
if (LINK == cur->_rightType)
{
cur = cur->_right;
}
}
cout << cur->_data << " ";
Node* p = NULL;
}
}
protected:
//左、右、根
void _PostOrderThreading(Node* cur,Node*& prev)
{
if (NULL == cur)
{
return;
}
_PostOrderThreading(cur->_left, prev);
_PostOrderThreading(cur->_right, prev);
if (NULL == cur->_left)
{
cur->_left = prev;
cur->_leftType = THREAD;
}
if (prev && NULL == prev->_right)
{
prev->_right = cur;
prev->_rightType = THREAD;
}
prev = cur;//更新prev的值
}
void _PreOrderThreading(Node* cur,Node*& prev)
{
if (NULL == cur)
{
return;
}
if (NULL == cur->_left)
{
cur->_left = prev;
cur->_leftType = THREAD;
}
if (prev && NULL == prev->_right)
{
prev->_right = cur;
prev->_rightType = THREAD;
}
prev = cur;//更新prev的值
if (cur->_leftType == LINK)//因为是先线索化后进行递归,为了避免死循环,所以需要判断
{
_PreOrderThreading(cur->_left, prev);
}
if (cur->_rightType == LINK)
{
_PreOrderThreading(cur->_right, prev);
}
}
void _PreOrder(Node* root)
{
if (root)
{
cout << root->_data << " ";
_PreOrder(root->_left);
_PreOrder(root->_right);
}
}
void _InOrder(Node* root)
{
if (root)
{
_InOrder(root->_left);
cout << root->_data << " ";
_InOrder(root->_right);
}
}
void _PostOrder(Node* root)
{
if (root)
{
_PostOrder(root->_left);
_PostOrder(root->_right);
cout << root->_data << " ";
}
}
void _InoderThreading(Node* cur, Node* & prev)
{
if (cur)
{
_InoderThreading(cur->_left, prev);
if (NULL == cur->_left)//当前节点的左节点需要线索化
{
cur->_left = prev;
cur->_leftType = THREAD;
}
if (prev && NULL == prev->_right)//当前节点的前驱的右节点需要线索化
{
prev->_right = cur;
prev->_rightType = THREAD;
}
prev = cur;//更新prev
_InoderThreading(cur->_right, prev);
}
}
Node* _CreatTree(const T* arr, size_t size, const T& invalid, size_t& index)
{
Node* newRoot = _root;
if (index < size && arr[index] != invalid)
{
newRoot = new Node(arr[index]);
newRoot->_left = _CreatTree(arr, size, invalid, ++index);
newRoot->_right = _CreatTree(arr, size, invalid, ++index);
}
return newRoot;
}
private:
Node* _root;
};
前序线索化二叉树:
void _PreOrderThreading(Node* cur,Node*& prev)
{
if (NULL == cur)
{
return;
}
if (NULL == cur->_left)
{
cur->_left = prev;
cur->_leftType = THREAD;
}
if (prev && NULL == prev->_right)
{
prev->_right = cur;
prev->_rightType = THREAD;
}
prev = cur;//更新prev的值
if (cur->_leftType == LINK)//因为是先线索化后进行递归,为了避免死循环,所以需要判断
{
_PreOrderThreading(cur->_left, prev);
}
if (cur->_rightType == LINK)
{
_PreOrderThreading(cur->_right, prev);
}
}
中序线索化二叉树的迭代器:
template<class T>
struct BinaryTreeThdIterator
{
typedef BinaryTreeThdNode<T> Node;
typedef BinaryTreeThdIterator<T> self;
BinaryTreeThdIterator(Node* node)
:_node(node)
{}
T& operator*()
{
return _node->_data;
}
T* operator->()
{
return &(_node->_data);
}
self& operator++()
{
//后继
if (_node->_rightType == THREAD)
{
_node = _node->_right;
}
else//子问题
{
Node* cur = _node->_right;
while (cur->_leftType == LINK)
{
cur = cur->_left;
}
_node = cur;
}
return *this;
}
bool operator!=(const self& cur)const
{
return _node != cur._node;
}
bool operator==(const self& cur)const
{
return _node == cur._node;
}
Node* _node;
};
总结:
本文概要:1.中序线索化二叉树
2.中序遍历中序线索化二叉树
3.前序线索化二叉树
4.前序遍历前序线索化二叉树(易入坑)
5.中序线索化二叉树的迭代器