#include "stdafx.h" #include <iostream> #include <stack> #include <queue> #include <Windows.h> using namespace std; typedef struct _Node { int data; struct _Node *left; struct _Node *right; bool isVisit; //用于后序非递归遍历,表示节点是否可以访问 _Node() { data = 0; left = NULL; right = NULL; isVisit = false; } }Node, *PNode; //****************二叉树的递归建造******************** //约定:输入0表示该节点的子树为NULL void RecurCreate(PNode pRoot) { int data; cin>>data; if (0 != data) { pRoot = new Node; pRoot->data = data; RecurCreate(pRoot->left); RecurCreate(pRoot->right); } } //假定二叉树如下图所示,利用前序和中序、后序与中序可以唯一确定一棵二叉树的原理 // 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); } //****************二叉树的递归遍历******************** //前序递归遍历 void PreRecurTraversal(PNode pRoot) { if (NULL != pRoot) { cout<<pRoot->data<<'\t'; PreRecurTraversal(pRoot->left); PreRecurTraversal(pRoot->right); } } //中序递归遍历 void MidRecurTraversal(PNode pRoot) { if (NULL != pRoot) { MidRecurTraversal(pRoot->left); cout<<pRoot->data<<'\t'; MidRecurTraversal(pRoot->right); } } //序后递归遍历 void PostRecurTraversal(PNode pRoot) { if (NULL != pRoot) { PostRecurTraversal(pRoot->left); PostRecurTraversal(pRoot->right); cout<<pRoot->data<<'\t'; } } //****************二叉树的非递归遍历******************** //第一种前序非递归遍历 void PreTraversalOne(PNode pRoot) { PNode pTree = pRoot; stack<PNode> s; while (!s.empty() || NULL != pTree) { while (NULL != pTree) { cout<<pTree->data<<'\t'; s.push(pTree); pTree = pTree->left; } if (!s.empty()) { pTree = s.top(); s.pop(); pTree = pTree->right; } } } //第二种前序非递归遍历 void PreTraversalTwo(PNode pRoot) { PNode pTree = pRoot; stack<PNode> s; s.push(pTree); while (!s.empty()) { pTree = s.top(); cout<<pTree->data<<'\t'; s.pop(); if (NULL != pTree->right) //1、右子树进栈 { s.push(pTree->right); } if (NULL != pTree->left) //2、左子树进栈 { s.push(pTree->left); } } } //中序非递归遍历 void MidTraversal(PNode pRoot) { PNode pTree = pRoot; stack<PNode> s; while (!s.empty() || NULL != pTree) { while (NULL != pTree) { s.push(pTree); pTree = pTree->left; } if (!s.empty()) { pTree = s.top(); cout<<pTree->data<<'\t'; s.pop(); pTree = pTree->right; } } } //后序非递归遍历 void PostTraversal(PNode pRoot) { PNode pTree = pRoot; stack<PNode> s; while (!s.empty() || NULL != pTree) { while (NULL != pTree) { s.push(pTree); pTree = pTree->left; } if (!s.empty()) { pTree = s.top(); if (pTree->isVisit) { cout<<pTree->data<<'\t'; s.pop(); pTree = NULL; } else { pTree->isVisit = true; pTree = pTree->right; } } } } //层序非递归遍历——用队列,注意与第二种非递归前序遍历的区别 void LevelTraversal(PNode pRoot) { PNode pTree = pRoot; queue<PNode> q; q.push(pTree); while (!q.empty()) { pTree = q.front(); q.pop(); cout<<pTree->data<<'\t'; if (NULL != pTree->left) //1、左子树进队列 { q.push(pTree->left); } if (NULL != pTree->right) //2、右子树进队列 { q.push(pTree->right); } } } //辅助函数,设置控制台的颜色 void SetConsoleTextColor(WORD dwColor) { HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE); if (INVALID_HANDLE_VALUE == handle) { return; } SetConsoleTextAttribute(handle, dwColor); } int _tmain(int argc, _TCHAR* argv[]) { PNode pRoot1 = NULL; PNode pRoot2 = NULL; cout<<endl<<"******************根据前序和中序建造二叉树********************"<<endl<<endl; PreAndMidRecurCreate(pRoot1, 0, 0, MAX_NUM); SetConsoleTextColor(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY); cout<<endl<<"******************层序遍历二叉树********************"<<endl<<endl; LevelTraversal(pRoot1); SetConsoleTextColor(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY); cout<<endl<<"******************递归遍历二叉树********************"<<endl<<endl; cout<<endl<<" **********前序递归遍历二叉树**********"<<endl<<endl; PreRecurTraversal(pRoot1); cout<<endl<<" **********中序递归遍历二叉树**********"<<endl<<endl; MidRecurTraversal(pRoot1); cout<<endl<<" **********后序递归遍历二叉树**********"<<endl<<endl; PostRecurTraversal(pRoot1); SetConsoleTextColor(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE); cout<<endl<<"******************根据后序和中序建造二叉树********************"<<endl<<endl; PostAndMidRecurCreate(pRoot2, MAX_NUM - 1, 0, MAX_NUM); SetConsoleTextColor(FOREGROUND_GREEN | FOREGROUND_INTENSITY); cout<<endl<<"******************非递归遍历二叉树********************"<<endl<<endl; cout<<endl<<" **********前序非递归遍历二叉树**********"<<endl<<endl; PreTraversalOne(pRoot2); cout<<endl; PreTraversalTwo(pRoot2); cout<<endl<<" **********中序非递归遍历二叉树**********"<<endl<<endl; MidTraversal(pRoot2); cout<<endl<<" **********后序非递归遍历二叉树**********"<<endl<<endl; PostTraversal(pRoot2); return 0; }
输出效果如图所示