二叉树的线索

#include "stdafx.h"
#include <iostream>
#include <iomanip>
#include <stack>
#include <queue>
#include <Windows.h>
using namespace std;

enum TYPE
{
    TYPE_LINK = 0,
    TYPE_CLUES,
};
typedef struct _Node
{
    int data;
    struct _Node *left;
    struct _Node *right;
    bool isVisit;        //用于后序非递归遍历,表示节点是否可以访问
    TYPE lType;          //标示左子树为指向左子树还是前驱
    TYPE rType;          //标示右子树为指向右子树还是后驱
    _Node()
    {
        data = 0;
        left = NULL;
        right = NULL;
        isVisit = false;
        lType = TYPE_LINK;
        rType = TYPE_LINK;
    }
}Node, *_PNode;

//假定二叉树如下图所示,利用前序和中序、后序与中序可以唯一确定一棵二叉树的原理
//                       1
//                     /   \
//                    2     3
//                  / \     / \
//                 4   5   6   7 
//               / \  /
//              8   9 10

const int MAX_NUM = 10;                             //二叉树的节点数
int pre[MAX_NUM] = {1, 2, 4, 8, 9, 5, 10, 3, 6, 7}; //前序遍历的数组
int mid[MAX_NUM] = {8, 4, 9, 2, 10, 5, 1, 6, 3, 7}; //中序遍历的数组
int post[MAX_NUM] = {8, 9, 4, 10, 5, 2, 6, 7,3, 1}; //后序遍历的数组

//获取前序数组的data在中序数组的索引
int GetPositionInMid(int data)
{
    for (int i = 0; i < MAX_NUM; i++)
    {
        if (mid[i] == data)
        {
            return i;
        }
    }
}

//利用前序和中序可以唯一确定一棵二叉树
//参数说明
// pRoot   —— 需要建造节点的指针引用
// iPre    —— 表示pRoot节点的左子树(右子树)在前序数组的第一个索引
// iMid    —— 表示pRoot节点的左子树(右子树)在中序数组的第一个索引
// length  —— 表示pRoot节点的左子树(右子树)的长度
void PreAndMidRecurCreate(_PNode &pRoot, int iPre, int iMid, int length)
{
    if (length <= 0)
    {
        return;
    }
    pRoot = new Node;
    pRoot->data = pre[iPre];
    int pos = GetPositionInMid(pre[iPre]);
    PreAndMidRecurCreate(pRoot->left, iPre + 1, iMid, pos - iMid);
    PreAndMidRecurCreate(pRoot->right, iPre + (pos - iMid) + 1, pos + 1, length - (pos - iMid) - 1);
}

//利用后序和中序可以唯一确定一棵二叉树
//参数说明
// pRoot   —— 需要建造节点的指针引用
// iPost   —— 表示pRoot节点的左子树(右子树)在后序数组的第一个索引
// iMid    —— 表示pRoot节点的左子树(右子树)在中序数组的第一个索引
// length  —— 表示pRoot节点的左子树(右子树)的长度
void PostAndMidRecurCreate(_PNode &pRoot, int iPost, int iMid, int length)
{
    if (length <= 0)
    {
        return;
    }
    pRoot = new Node;
    pRoot->data = post[iPost];
    int pos = GetPositionInMid(post[iPost]);
    PostAndMidRecurCreate(pRoot->left, iPost - 1 - (length - (pos - iMid) - 1), iMid, pos - iMid);
    PostAndMidRecurCreate(pRoot->right, iPost - 1, pos + 1, length - (pos - iMid) - 1);
}
//****************************************二叉树的线索*******************************************begin

_PNode prePreNode;   //前序线索二叉树指向的节点前驱
_PNode preMidNode;   //中序线索二叉树指向的节点前驱
_PNode prePostNode;  //后序线索二叉树指向的节点前驱

//前序线索二叉树的递归函数
void PreInClues(_PNode &pRoot)
{
    if (NULL != pRoot)
    {
        if (NULL == pRoot->left)   //1、如果当前节点左子树为空,则线索
        {
            pRoot->left = prePreNode;
            pRoot->lType = TYPE_CLUES;
        }
        if (NULL == prePreNode->right)//2、如果前驱节点右子树为空,则线索
        {
            prePreNode->right = pRoot;
            prePreNode->rType = TYPE_CLUES;
        }
        prePreNode = pRoot;
        if (pRoot->lType == TYPE_LINK)
        {
            PreInClues(pRoot->left);
        }
        if (pRoot->rType == TYPE_LINK)
        {
            PreInClues(pRoot->right);
        }
    }
}

//前序线索二叉树
//参数说明   pPreRoot —— 指向根节点的指针
//         pRoot    ——  根节点的指针
void PreTraversalInClues(_PNode &pPreRoot, _PNode &pRoot)
{
    pPreRoot = new Node;
    pPreRoot->right = pPreRoot;
    pPreRoot->rType = TYPE_CLUES;
    pPreRoot->lType = TYPE_LINK;
    if (NULL == pRoot)
    {
        pPreRoot->left = pPreRoot;
    }
    else
    {
        pPreRoot->left = pRoot;
        prePreNode = pPreRoot;
        PreInClues(pRoot);
        prePreNode->right = pPreRoot;
        prePreNode->rType = TYPE_CLUES;
        pPreRoot->right = prePreNode;
    }
}

//中序线索化的输出
void PreCluesOutput(_PNode pPreRoot)
{
    _PNode pNode = pPreRoot->left;
    while (pNode != pPreRoot)
    {
        cout<<pNode->data<<'\t';
        if (pNode->lType == TYPE_LINK)
        {
            pNode = pNode->left;
        }
        else 
        {
            pNode = pNode->right;
        }
    }
}

//中序线索二叉树的递归函数
void MidInClues(_PNode &pRoot)
{
    if (NULL != pRoot)
    {
        MidInClues(pRoot->left);
        if (NULL == pRoot->left)  //1、如果当前节点左子树为空,则线索
        {
            pRoot->left = preMidNode;
            pRoot->lType = TYPE_CLUES;
        }
        if (NULL == preMidNode->right) //2、如果前驱节点右子树为空,则线索
        {
            preMidNode->right = pRoot;
            preMidNode->rType = TYPE_CLUES;
        }
        preMidNode = pRoot;
        MidInClues(pRoot->right);
    }
}

//中序线索二叉树
void MidTraversalInClues(_PNode &pPreRoot, _PNode &pRoot)
{
    pPreRoot = new Node;
    pPreRoot->right = pPreRoot;
    pPreRoot->rType = TYPE_CLUES;
    pPreRoot->lType = TYPE_LINK;
    if (NULL == pRoot)
    {
        pPreRoot->left = pPreRoot;
    }
    else
    {
        pPreRoot->left = pRoot;
        preMidNode = pPreRoot;
        MidInClues(pRoot);
        preMidNode->right = pPreRoot;
        preMidNode->rType = TYPE_CLUES;
        pPreRoot->right = preMidNode;
    }
}

//中序线索化的输出
void MidCluesOutput(_PNode pPreRoot)
{
    _PNode pNode = pPreRoot->left;
    while (pNode != pPreRoot)
    {
        while (pNode->lType ==  TYPE_LINK)
        {
            pNode = pNode->left;
        }
        cout<<pNode->data<<'\t';
        while (pNode->rType == TYPE_CLUES && pNode->right != pPreRoot)
        {
            pNode = pNode->right;
            cout<<pNode->data<<'\t';
        }
        pNode = pNode->right;
    }
}

//****************************************二叉树的线索*******************************************end
int _tmain(int argc, _TCHAR* argv[]) { _PNode pRoot1 = NULL; _PNode pRoot2 = NULL; _PNode pPreRoot = NULL; _PNode pMidRoot = NULL; //cout<<endl<<"******************根据前序和中序建造二叉树********************"<<endl<<endl; PreAndMidRecurCreate(pRoot1, 0, 0, MAX_NUM); //cout<<endl<<"******************根据后序和中序建造二叉树********************"<<endl<<endl; PostAndMidRecurCreate(pRoot2, MAX_NUM - 1, 0, MAX_NUM);
cout
<<endl<<"******************输出前序线索二叉树********************"<<endl<<endl; PreTraversalInClues(pPreRoot, pRoot1); PreCluesOutput(pPreRoot); cout<<endl<<"******************输出中序线索二叉树********************"<<endl<<endl; MidTraversalInClues(pMidRoot, pRoot2); MidCluesOutput(pMidRoot); cout<<endl; return 0; }

运行界面如下:

posted @ 2012-08-07 20:47  venow  阅读(345)  评论(0编辑  收藏  举报