#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; }
运行界面如下: