1. 程式人生 > >二叉樹線索化

二叉樹線索化

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

測試執行結果:
這裡寫圖片描述