【数据结构】线索化二叉树的基本操作

二叉树的线索化源码:

BinSearchTree.h:
#pragma once
#ifndef __BINSEARCH_H__
#define __BINSEARCH_H__

#include<iostream>
#include<stdio.h>
#include<stack>
#include<queue>

using namespace std;

//搜索二叉树节点

enum BinThread{LINK,THREAD};

template<class T>
struct BinTreeNodeThd
{
    BinTreeNodeThd(const T& data)
    :_data(data)
    , _pLeft(NULL)
    , _pRight(NULL)
    , _pParent(NULL)
    , _pLeftThread(LINK)
    , _pRightThread(LINK)
    {}
    T _data;
    BinTreeNodeThd<T>* _pLeft;
    BinTreeNodeThd<T>* _pRight;
    BinThread _pLeftThread;
    BinThread _pRightThread;//标记是否需要线索化
    BinTreeNodeThd<T>* _pParent;//父母节点
};

template<class T>
class BinSearchTree
{
    typedef BinTreeNodeThd<T> Node;
    typedef Node* pNode;
public:
    //构造函数
    //空搜索二叉树的构造
    BinSearchTree()
        :_pRoot(NULL)
    {}

    //带参的搜索二叉树构造函数
    BinSearchTree(const T* arr, size_t size, const T& invalid){
        size_t index = 0;
        pNode parent = NULL;
        _CreateNewTree(_pRoot,arr, size, index, invalid,parent);
    }

    //前序递归遍历
    void PreOrder(){
        cout << "前序递归遍历" << endl;
        _PreOrder(_pRoot);
        cout << endl;
    }

    //前序非递归遍历线索化后的二叉树
    void PreOrderNor(){
        cout << "前序非递归遍历" << endl;
        _PreOrderNor(_pRoot);
        cout << endl;
    }
    //中序递归遍历
    void InOrder(){
        cout << "中序递归遍历" << endl;
        _InOrder(_pRoot);
        cout << endl;
    }

    //中序非递归遍历线索化后的二叉树
    void InOrderNor(){
        cout << "中序非递归遍历" << endl;
        _InOrderNor(_pRoot);
        cout << endl;
    }

    //后序递归遍历
    void PostOrder(){
        cout << "后序递归遍历" << endl;
        _PostOrder(_pRoot);
        cout << endl;
    }

    //后序非递归遍历线索化后的二叉树
    void PostOrderNor(){
        cout << "后序非递归遍历" << endl;
        _PostOrderNor(_pRoot);
        cout << endl;
    }

    //前序线索化二叉树
    void PreThread(){
        cout << "前序线索化二叉树" << endl;
        pNode prev = NULL;
        _PreThread(_pRoot, prev);
    }

    //中序线索化二叉树
    void InThread(){
        cout << "中序线索化二叉树" << endl;
        pNode prev = NULL;
        _InThread(_pRoot, prev);
    }

    //后序线索化二叉树
    void PostThread(){
        cout << "后序线索化二叉树" << endl;
        pNode prev = NULL;
        _PostThread(_pRoot, prev);
    }

protected:
    //创建搜索二叉树
    void _CreateNewTree(pNode& pRoot,const T* arr, size_t size, size_t& index, const T& invalid,pNode& parent){
        if (index < size && arr[index] != invalid){
            pRoot = new Node(arr[index]);
            pRoot->_pParent = parent;
            _CreateNewTree(pRoot->_pLeft,arr, size, ++index, invalid,pRoot);
            _CreateNewTree(pRoot->_pRight,arr, size, ++index, invalid,pRoot);
        }
    }

    //前序递归遍历
    void _PreOrder(pNode pRoot){
        if (pRoot){
            cout << pRoot->_data << "  ";
            _PreOrder(pRoot->_pLeft);
            _PreOrder(pRoot->_pRight);
        }
    }

    //前序非递归遍历线索化后的二叉树
    void _PreOrderNor(pNode pRoot){
        if (NULL == pRoot)
            return;
        pNode pCur = pRoot;
        while (pCur){
            //遍历当前节点
            while (LINK == pCur->_pLeftThread){
                cout << pCur->_data << "  ";
                pCur = pCur->_pLeft;
            }
            cout << pCur->_data << "  ";
            //不管是当前节点的右子树,或是线索化后指向的下个节点,都可以用此步来进入下一层子循环
            pCur = pCur->_pRight;
        }


    }

    //中序递归遍历
    void _InOrder(pNode pRoot){
        if (pRoot){
            _InOrder(pRoot->_pLeft);
            cout << pRoot->_data << "  ";
            _InOrder(pRoot->_pRight);
        }
    }

    //中序非递归遍历线索化后的二叉树
    void _InOrderNor(pNode pRoot){
        if (NULL == pRoot)
            return;
        pNode pCur = pRoot;
        while (pCur){
            //先找到左子树最左边的节点
            while (LINK == pCur->_pLeftThread)
                pCur = pCur->_pLeft;
            //遍历该节点的根节点(该节点一定没有左子树,因为上面的while循环)
            cout << pCur->_data << "  ";
            //遍历该节点的下一节点(线索化后的右指针域)
            while (THREAD == pCur->_pRightThread){
                pCur = pCur->_pRight;
                cout << pCur->_data << "  ";
            }
            //遍历该节点的右子树,进入下一层子循环
            pCur = pCur->_pRight;
        }
    }

    //后序递归遍历
    void _PostOrder(pNode pRoot){
        if (pRoot){
            _PostOrder(pRoot->_pLeft);
            _PostOrder(pRoot->_pRight);
            cout << pRoot->_data << "  ";
        }
    }

    //后序非递归遍历线索化后的二叉树
    void _PostOrderNor(pNode pRoot){
        if (NULL == pRoot)
            return;
        pNode pCur = pRoot;
        pNode prev = NULL;
        while (pCur){

            //先找到左子树的最左节点
            if (pCur && pCur->_pLeft != prev){
                //if 防止左边重复走两次
                while (LINK == pCur->_pLeftThread)
                    pCur = pCur->_pLeft;
            }
            //左为空,右也为空,访问后继节点
            while (THREAD == pCur->_pRightThread){
                cout << pCur->_data << "  ";
                prev = pCur;//标记刚刚访问的节点
                pCur = pCur->_pRight;
            }
            //处理根节点
            if (pRoot == pCur && (NULL == pRoot->_pRight || prev == pRoot->_pRight)){
                cout << pCur->_data << "  ";
                return;
            }

            //防止右单支的情况出现
            //需要加入父母节点,形成父母孩子节点,可以访问前驱节点
            while (pCur && prev == pCur->_pRight/* && pRoot != pCur*/){
                cout << pCur->_data << "  ";
                prev = pCur;
                pCur = pCur->_pParent;
            }
            //遍历右子树,进行下一次子循环
            if (pCur && NULL != pCur->_pRight && prev != pCur->_pRight){
                if (pCur && LINK == pCur->_pRightThread)
                    pCur = pCur->_pRight;
            }
        }
    }

    //前序线索化二叉树
    void _PreThread(pNode& pRoot, pNode& prev){
        if (pRoot){
            //线索化当前节点
            //线索化当前节点的左指针域
            if (NULL == pRoot->_pLeft){
                pRoot->_pLeft = prev;
                pRoot->_pLeftThread = THREAD;
            }
            //线索化当前节点的右指针域
            if (prev && NULL == prev->_pRight){
                prev->_pRight = pRoot;
                prev->_pRightThread = THREAD;
            }
            //标记刚刚进行线索化的节点
            prev = pRoot;
            //线索化左子树
            if (LINK == pRoot->_pLeftThread)
                _PreThread(pRoot->_pLeft, prev);
            //线索化右子树
            if (LINK == pRoot->_pRightThread)
                _PreThread(pRoot->_pRight, prev);
        }
    }

    //中序线索化二叉树
    void _InThread(pNode& pRoot, pNode& prev){
        if (pRoot){
            //线索化左子树
            _InThread(pRoot->_pLeft, prev);
            //线索化当前节点
            //线索化当前节点的左指针域
            if (NULL == pRoot->_pLeft){
                pRoot->_pLeft = prev;
                pRoot->_pLeftThread = THREAD;
            }
            //线索化当前节点的右指针域
            if (prev && NULL == prev->_pRight){
                prev->_pRight = pRoot;
                prev->_pRightThread = THREAD;
            }
            //标记刚刚进行线索化的节点
            prev = pRoot;

            //线索化右子树
            if (LINK == pRoot->_pRightThread)
                _InThread(pRoot->_pRight, prev);
        }
    }

    //后序线索化二叉树
    void _PostThread(pNode& pRoot, pNode& prev){
        if (pRoot){
            //线索化左子树
            _PostThread(pRoot->_pLeft, prev);
            //线索化右子树
            _PostThread(pRoot->_pRight, prev);
            //线索化当前节点
            //线索化当前节点的左指针域
            if (NULL == pRoot->_pLeft){
                pRoot->_pLeft = prev;
                pRoot->_pLeftThread = THREAD;
            }
            //线索化当前节点的右指针域
            if (prev && NULL == prev->_pRight){
                prev->_pRight = pRoot;
                prev->_pRightThread = THREAD;
            }
            //标记刚刚进行线索化的节点
            prev = pRoot;
        }
    }

private:
    pNode _pRoot;
};

#endif //__BINSEARCH_H__
test.c:
#include"bintree.h"
#include"BinSearchTree.h"
#include<Windows.h>
#include<stdio.h>
#include<stdlib.h>
#include<iostream>
using namespace std;
//测试搜索二叉树
void test1(){
    //普通场景
    char arr[] = { 'A', 'B', 'D', '#', '#', '#', 'C', 'E', '#', '#', 'F' };
    //char arr2[] = { '1', '2', '#', '#', '3' };
    BinSearchTree<char> bt(arr, sizeof(arr) / sizeof(arr[0]), '#');
    //左子树有可能走两次
    char arr1[] = { 'A', 'B', 'D', 'E', '#', '#', 'F', '#', '#', '#', 'C' };
    BinSearchTree<char> bt1(arr1, sizeof(arr1) / sizeof(arr1[0]), '#');
    //左单支
    char arr2[] = { 'A', 'B', 'C', 'D' };
    BinSearchTree<char> bt2(arr2, sizeof(arr2) / sizeof(arr2[0]), '#');
    //右单支
    char arr3[] = { 'A', '#', 'B', '#', 'C', '#', 'D' };
    BinSearchTree<char> bt3(arr3, sizeof(arr3) / sizeof(arr3[0]), '#');

    //测试后序非递归遍历线索化后的二叉树
    cout << "场景:普通场景" << endl;
    bt.PostOrder();
    bt.PostThread();
    bt.PostOrderNor();
    cout << endl;
    cout << "场景:左子树有可能走两次" << endl;
    bt1.PostOrder();
    bt1.PostThread();
    bt1.PostOrderNor();
    cout << endl;
    cout << "场景:左单支" << endl;
    bt2.PostOrder();
    bt2.PostThread();
    bt2.PostOrderNor();
    cout << endl;
    cout << "场景:右单支" << endl;
    bt3.PostOrder();
    bt3.PostThread();
    bt3.PostOrderNor();
    cout << endl;   

    //测试前序递归遍历、前序线索化二叉树、前序非递归遍历
    //bt.PreOrder();
    //bt.PreThread();
    //bt.PreOrderNor();

    //测试中序递归遍历、中序线索化二叉树、中序非递归遍历
    //bt.InOrder();
    //bt.InThread();
    //bt.InOrderNor();
}

int main(){
    test1();
    system("pause");
    return 0;
}

测试结果:

前序线索化二叉树:

这里写图片描述

这里写图片描述

前序测试结果:

这里写图片描述


中序线索化二叉树:

这里写图片描述

这里写图片描述

中序测试结果:

这里写图片描述


后续线索化二叉树:

场景一:普通场景

这里写图片描述

这里写图片描述

场景二:特殊场景(左子树有可能走两次)

这里写图片描述

这里写图片描述

场景三:左单支

这里写图片描述

这里写图片描述

场景四:右单支

这里写图片描述

这里写图片描述


后续测试结果:

这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值