二叉樹線索化
阿新 • • 發佈:2019-02-05
1 原理分析
線索化意義:
二叉樹是非線性結構,遍歷二叉樹都是通過遞迴或者用棧輔助非遞迴來遍歷的。
1)不借用棧或者佇列來實現遍歷的非遞迴,還有一種方法是線索化。
2)為了實現迭代器,面向物件。
如果我們知道一個節點的前驅和後繼,那麼我們就可直接遍歷二叉樹。
設定二叉樹節點的前驅和後繼,就是線索化二叉樹,我們利用指向左右子樹的空指標存放節點的前驅和後繼。
線索化設計思路:
遍歷二叉樹,當遍歷到一個節點的左節點或右節點為空時,設定它的前驅和後繼,那麼訪問時直接可根據節點的前驅和後繼來進行訪問
1.1 中序線索化和遍歷
1.2 前序線索化和遍歷
1.3 後續線索化和遍歷
2 程式碼實現:
//BinaryTreeNodeThd.h
#pragma once
#include<iostream>
#include<string.h>
#include<assert.h>
enum PointerTag { THREAD, LINK };
template<class T>
struct BinaryTreeNodeThd
{
T _data; // 資料
BinaryTreeNodeThd* _left; // 左孩子
BinaryTreeNodeThd* _right; // 右孩子
PointerTag _leftTag; // 左孩子線索標誌
PointerTag _rightTag; // 右孩子線索標誌
BinaryTreeNodeThd* _parent;//用於後序遍歷
BinaryTreeNodeThd(const T& d)
:_data(d)
, _left(NULL)
, _right(NULL)
, _leftTag(LINK)
, _rightTag(LINK)
, _parent(NULL)
{}
};
// 基類迭代器
template<class T>
struct __BinaryTreeIterator
{
typedef BinaryTreeNodeThd< T> Node;
typedef __BinaryTreeIterator<T> Self;
Node* _node;
__BinaryTreeIterator(Node* node)
:_node(node)
{}
T& operator *()
{
return _node->_data;
}
T* operator ->()
{
return &(operator *());
}
bool operator =(const Self& s)
{
return _node == s._node;
}
bool operator !=(const Self& s)
{
return _node != s._node;
}
virtual Self& operator++()=0;
};
template<class T>
struct __BinaryTreeInIterator : public __BinaryTreeIterator<T>//中序迭代器
{
typedef BinaryTreeNodeThd<T> Node;
typedef __BinaryTreeInIterator<T> Self;
__BinaryTreeInIterator(Node* node)
:__BinaryTreeIterator(node)
{ }
Self& operator++()
{
if (_node->_rightTag == THREAD)
{
_node = _node->_right;
}
else
{
_node = _node->_right;
while (_node->_leftTag == LINK)
{
_node = _node->_left;
}
}
return *this;
}
};
template<class T>
struct __BinaryTreePrevIterator : public __BinaryTreeIterator<T>//前序迭代器
{
typedef BinaryTreeNodeThd<T> Node;
typedef __BinaryTreePrevIterator<T> Self;
__BinaryTreePrevIterator(Node* node)
:__BinaryTreeIterator(node)
{}
Self& operator ++ ()
{
if (_node->_rightTag == LINK)
{
_node = _node->_left;
}
else
{
_node = _node->_right;
}
return *this;
}
};
template<class T>
struct BinaryTreeThd
{
public:
typedef BinaryTreeNodeThd<T> Node;
typedef __BinaryTreeIterator<T> Iterator;
typedef __BinaryTreeInIterator<T> InIterator;
typedef __BinaryTreePrevIterator<T> PrevIterator;
BinaryTreeThd(T* a, size_t n, const T& invalid)
:_root(NULL)
{
size_t index = 0;
Node* parent = NULL;
_root = _CreatTree(a, n, index, invalid,parent);
}
InIterator InBegin()
{
Node* cur = _root;
while (cur&&cur->_leftTag==LINK)
{
cur = cur->_left;
}
return cur;
}
InIterator InEnd()
{
return NULL;
}
PrevIterator PrevBegin()
{
return _root;
}
PrevIterator PrevEnd()
{
return NULL;
}
void _InOrderThreading(Node* cur, Node*& prev)
{
if (cur == NULL)
{
return;
}
_InOrderThreading(cur->_left, prev);
if (cur->_left == NULL)//當cur左為空時,線索化cur左
{
cur->_leftTag = THREAD;
cur->_left = prev;
}
if (prev&&prev->_right == NULL)//當prev右為空時,線索化prev右
{
prev->_rightTag = THREAD;
prev->_right = cur;
}
prev = cur;
_InOrderThreading(cur->_right, prev);
}
// 中序線索化
void InOrderThreading()
{
Node* prev = NULL;
_InOrderThreading(_root, prev);
prev->_rightTag = THREAD;
}
void _PrevThreading(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)
{
_PrevThreading(cur->_left, prev);
}
if (cur->_rightTag == LINK)
{
_PrevThreading(cur->_right, prev);
}
}
// 前序線索化
void PrevThreading()
{
Node* prev = NULL;
_PrevThreading(_root, prev);
prev->_rightTag = THREAD;
}
void _PostOrderThreading(Node* cur, Node*& prev)
{
if (cur == NULL)
{
return;
}
_PostOrderThreading(cur->_left, prev);
_PostOrderThreading(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;
}
// 後序線索化
void PostOrderThreading()
{
Node* prev = NULL;
_PostOrderThreading(_root, prev);
}
void InOrderThd()//中序遍歷
{
Node* cur = _root;
while (cur)
{
while (cur->_leftTag==LINK)
{
cur = cur->_left;
}
cout << cur->_data << " ";
if (cur->_rightTag == THREAD)
{
cur = cur->_right;
cout << cur->_data << " ";
}
cur = cur->_right;
}
cout << endl;
}
void PrevOrderThd()//先序遍歷
{
Node* cur = _root;
while (cur)
{
while (cur->_leftTag == LINK)
{
cout << cur->_data << " ";
cur = cur->_left;
}
cout << cur->_data << " ";
cur = cur->_right;
}
cout << endl;
}
void PostOrderThd()//後序遍歷
{
Node* cur = _root;
Node*prev = NULL;
while (cur)
{
//第一步:找樹最左邊的節點
while (cur->_left!=prev&&cur->_leftTag == LINK)
{
cur = cur->_left;
}
//第二步:訪問後繼
while (cur&&cur->_rightTag == THREAD)
{
cout << cur->_data << " ";
prev = cur;
cur = cur->_right;
}
//判斷此時cur是不是指向了根節點
if (cur == _root)
{
cout << cur->_data << " ";
return;
}
while (cur!=NULL&&cur->_right == prev)
{
cout << cur->_data << " ";
prev = cur;
cur = cur->_parent;//往上一級走
}
if (cur&&cur->_rightTag == LINK)
{
cur = cur->_right;
}
}
cout << endl;
}
protected:
Node* _CreatTree(const T *a, size_t size, size_t &index, const T& invalid,Node*& parent)//建立二叉樹
{
assert(a);
Node* node = NULL;
if (a[index] != invalid&&index < size)
{
node = new Node(a[index]);
node->_parent = parent;
node->_left = _CreatTree(a, size, ++index, invalid,node);
node->_right = _CreatTree(a, size, ++index, invalid,node);
}
return node;
}
private:
Node* _root;
};
//簡單模式
void TestBinaryTreeThd1()
{
int a1[] = {1, 2, 3, '#', '#', 4, '#' , '#', 5, 6};
BinaryTreeThd<int> t1(a1, sizeof(a1)/sizeof(a1[0]), '#');
t1.InOrderThreading();
t1.InOrderThd();
BinaryTreeThd<int>::InIterator it1 = t1.InBegin();
while(it1 != t1.InEnd())
{
cout<<*it1<<" ";
++it1;
}
cout <<endl;
BinaryTreeThd<int> t2(a1, sizeof(a1) / sizeof(a1[0]), '#');
t2.PrevThreading();
BinaryTreeThd<int>::PrevIterator it2 = t2.PrevBegin();
while(it2 != t2.PrevEnd())
{
cout<<*it2<<" ";
++it2;
}
cout << endl;
}
// 繼承加多型
void TestBinaryTreeThd2()
{
int a1[] = { 1, 2, 3, '#', '#', 4, '#', '#', 5, 6 };
BinaryTreeThd<int> t1(a1, sizeof(a1) / sizeof(a1[0]), '#');
t1.InOrderThreading();
t1.InOrderThd();
BinaryTreeThd<int>::Iterator& it1 = t1.InBegin();
while (it1 != t1.InEnd())
{
cout << *it1 << " ";
++it1; // 多型
}
cout << endl;
BinaryTreeThd<int> t2(a1, sizeof(a1) / sizeof(a1[0]), '#');
t2.PrevThreading();
BinaryTreeThd<int>::Iterator& it2 = t2.PrevBegin();
while (it2 != t2.PrevEnd())
{
cout << *it2 << " ";
++it2;
}
cout << endl;
}
//test.cpp
using namespace std;
#include"BinaryTreeNodeThd.h"
#include"assert.h"
void TestBinaryTreeThd()
{
int array[] = { 1, 2, 3, '#', '#', 4, '#', '#', 5, 6, '#', '#', '#' };
BinaryTreeThd<int> t(array,13, '#');
t.InOrderThreading();
t.InOrderThd();
BinaryTreeThd<int> t1(array, 13, '#');
t1.PrevThreading();
t1.PrevOrderThd();
BinaryTreeThd<int> t2(array, 13, '#');
t2.PostOrderThreading();
t2.PostOrderThd();
}
int main()
{
TestBinaryTreeThd();
cout << endl << "***********************************************************" << endl;
TestBinaryTreeThd1();
cout << endl << "***********************************************************" << endl;
TestBinaryTreeThd2();
system("pause");
return 0;
}
測試執行結果: