写一个O(n)时间的非递归过程,输出给定的含n个结点的二叉树中每个结点的关键字。要求只能用除树本身以外的固定量的额外存储空间,而且在过程中不能修改该树,哪怕是暂时的
采用类似中序遍历的处理方法,对一个结点,可以分为以下几种情况
1.从父结点进入子结点进行处理
(1)如果有左孩子,就处理左孩子
(2)返回到自己
(3)访问自己
(4)如果有右孩子,就处理右孩子
(5)返回到自己的父结点
2.从左孩子返回,说明左孩子已经处理过,自己还没访问,自己的右孩子也没有处理过,就进行1-(2)
3.从右孩子返回,说明左右孩子都已经处理,自己也访问过,就返回到更上层
4.返回到根结点时,遍历结束
1.main.cpp
#include "caselib.h" int main() { CTestFrame test; //test.inputNullWillShowErrorHint(); test.oneNoteWillSecuss(); test.rootWithLeftChildWillSecuss(); test.rootWithRightChildWillSecuss(); test.treeWithGraph10_4_1WillSecuss(); test.onlyLeftChildWillSecuss(); getchar(); return 0; }
#include <vector> #include <string> using namespace std; class CTestFrame { typedef bool (CTestFrame::*pFunc)(); vector<int> outputDataVec; vector<int> inputDataVec; vector<int> expectOutputDataVec; void prepare(int* inputData, int *expectOutputData, int inLen, int outLen); bool testStep(); void backup(); void assertTrue(CTestFrame::pFunc testedFunc, string errorPrint); public: void inputNullWillShowErrorHint(); void oneNoteWillSecuss(); void rootWithLeftChildWillSecuss(); void rootWithRightChildWillSecuss(); void treeWithGraph10_4_1WillSecuss(); void onlyLeftChildWillSecuss(); };
//#include <iofstream> #include "funclib.h" #include "caselib.h" void CTestFrame::prepare(int* inputData, int *expectOutputData, int inLen, int outLen) { int dataNum = 0; for(int i = 0; i < inLen; i++) { inputDataVec.push_back(inputData[i]); if(inputData[i] != NONODE) dataNum++; } //assert(dataNum == outLen) for(int i = 0; i < outLen; i++) expectOutputDataVec.push_back(expectOutputData[i]); } bool CTestFrame::testStep() { bool ret = false; biTree *pBiTree = new biTree(inputDataVec); outputDataVec = nonRecursivePrint(pBiTree); delete pBiTree; if(outputDataVec.size() != expectOutputDataVec.size()) ret = false; else { ret = true; for(int i =0; i < outputDataVec.size(); i++) { if(outputDataVec[i] != expectOutputDataVec[i]) { ret = false; break; } } } return ret; } void CTestFrame::backup() { inputDataVec.clear(); outputDataVec.clear(); expectOutputDataVec.clear(); } void CTestFrame::assertTrue(CTestFrame::pFunc testedFunc, string errorPrint) { if((this->*testedFunc)() != true) { cout<<"failed: "<<errorPrint<<endl; } } void CTestFrame::inputNullWillShowErrorHint() { bool ret = true; try { nonRecursivePrint(NULL); }catch(...) { ret = false; } if(ret == false) cout<<"No error hint when input is a NULL pointer!"<<endl; } void CTestFrame::oneNoteWillSecuss() { int inputData[1] = {5}; int expectOutputData[1] = {5}; prepare(inputData, expectOutputData, 1, 1); assertTrue(&CTestFrame::testStep, "The result is not correct when the bi-tree contains only one note"); backup(); } void CTestFrame::rootWithLeftChildWillSecuss() { int inputData[2] = {5, 10}; int expectOutputData[2] = {10, 5}; prepare(inputData, expectOutputData, 2, 2); assertTrue(&CTestFrame::testStep, "A root with a left node will not secuss"); backup(); } void CTestFrame::rootWithRightChildWillSecuss() { int inputData[3] = {5, NONODE, 10}; int expectOutputData[2] = {5, 10}; prepare(inputData, expectOutputData, 3, 2); assertTrue(&CTestFrame::testStep, "A root with a right node will not secuss"); backup(); } void CTestFrame::treeWithGraph10_4_1WillSecuss() { int inputData[10] = {18, 12, 10, 7, 4, 2, 21, NONODE, NONODE, 5}; int expectOutputData[8] = {7, 12, 5, 4, 18, 2, 10, 21}; prepare(inputData, expectOutputData, 10, 8); assertTrue(&CTestFrame::testStep, "test case with graph in Exercise 10.4_1 will fail"); backup(); } void CTestFrame::onlyLeftChildWillSecuss() { int inputData[8] = {1, 2, NONODE, 3, NONODE, NONODE, NONODE, 4}; int expectOutputData[4] = {4,3,2,1}; prepare(inputData, expectOutputData, 8, 4); assertTrue(&CTestFrame::testStep, "only left child will false"); backup(); }
#include <iostream> #include <vector> using namespace std; #define NONODE -0x7FFFFFF struct biTreeNode { int key; biTreeNode *pLeftChild; biTreeNode *pRightChild; biTreeNode *pParent; biTreeNode(){} biTreeNode(int x):key(x),pLeftChild(NULL),pRightChild(NULL){} }; //二叉树 struct biTree { biTreeNode *pRootNode; biTree(const vector<int> nodeKeyVec); ~biTree(); }; //遍历并输出 vector<int> nonRecursivePrint(biTree *pTree);
#include "funclib.h" #include <queue> #define LEFT 0 #define RIGHT 1 void freeNode(biTreeNode *pCurrentNode); void addNodeToChild(biTreeNode* pCurrentNode, biTreeNode* pChild, bool leftOrRight); bool isChildExist(const biTreeNode* pCurrentNode, bool leftOrRight); bool isChildLeftOrRight(const biTreeNode* pCurrentNode); void visitNode(const biTreeNode* pCurrentNode, vector<int> &nodeKeyVec); bool isRootNode(const biTreeNode* pCurrentNode, biTree* pTree); bool isReturnFromLeft(const biTreeNode* pCurrentNode); biTree::~biTree() { freeNode(pRootNode); } biTree::biTree(const vector<int> nodeKeyVec) { pRootNode = new biTreeNode(nodeKeyVec[0]); queue<biTreeNode*> nodeQueue; nodeQueue.push(pRootNode); for(int i = 1; i < nodeKeyVec.size(); i = i+2) { biTreeNode *pCurrentNode = nodeQueue.front(); nodeQueue.pop(); if(pCurrentNode != NULL && i < nodeKeyVec.size() && nodeKeyVec[i] != NONODE) { biTreeNode* pLeftChild = new biTreeNode(nodeKeyVec[i]); addNodeToChild(pCurrentNode, pLeftChild, LEFT); nodeQueue.push(pLeftChild); } else nodeQueue.push(NULL); if(pCurrentNode != NULL && i+1 < nodeKeyVec.size() && nodeKeyVec[i+1] != NONODE) { biTreeNode* pRightChild = new biTreeNode(nodeKeyVec[i+1]); addNodeToChild(pCurrentNode, pRightChild, RIGHT); nodeQueue.push(pRightChild); } else nodeQueue.push(NULL); } } vector<int> nonRecursivePrint(biTree *pTree) { //assert(pTree != NULL); vector<int> retDataVec; biTreeNode *pCurrentNode = pTree->pRootNode; while(pCurrentNode != NULL) { if(isChildExist(pCurrentNode, LEFT)) { pCurrentNode = pCurrentNode->pLeftChild; continue; } visitNode(pCurrentNode, retDataVec); if(isChildExist(pCurrentNode, RIGHT)) { pCurrentNode = pCurrentNode->pRightChild; continue; } while(isRootNode(pCurrentNode, pTree) == false) { biTreeNode *pParent = pCurrentNode->pParent; if(isReturnFromLeft(pCurrentNode) == true) { visitNode(pParent, retDataVec); if(isChildExist(pParent, RIGHT) == true) { pCurrentNode = pParent->pRightChild; break; } else { pCurrentNode = pParent; } } else { pCurrentNode = pParent; } } if(isRootNode(pCurrentNode, pTree) == true) return retDataVec; } } void freeNode(biTreeNode *pCurrentNode) { if(pCurrentNode != NULL) { freeNode(pCurrentNode->pLeftChild); freeNode(pCurrentNode->pRightChild); delete pCurrentNode; } } void addNodeToChild(biTreeNode* pCurrentNode, biTreeNode* pChild, bool leftOrRight) { if(leftOrRight == LEFT) pCurrentNode->pLeftChild = pChild; else pCurrentNode->pRightChild = pChild; pChild->pParent = pCurrentNode; } bool isChildExist(const biTreeNode* pCurrentNode, bool leftOrRight) { bool ret = false; if(leftOrRight == LEFT && pCurrentNode->pLeftChild != NULL) ret = true; else if(leftOrRight == RIGHT && pCurrentNode->pRightChild != NULL) ret = true; return ret; } bool isChildLeftOrRight(const biTreeNode* pCurrentNode) { //assert(pCurrentNode->pParent != NULL); bool ret = LEFT; if(pCurrentNode == pCurrentNode->pParent->pLeftChild) ret = LEFT; else if(pCurrentNode == pCurrentNode->pParent->pRightChild) ret = RIGHT; return ret; } void visitNode(const biTreeNode* pCurrentNode, vector<int> &nodeKeyVec) { //assert(pCurrentNode != NULL); nodeKeyVec.push_back(pCurrentNode->key); } bool isRootNode(const biTreeNode* pCurrentNode, biTree* pTree) { bool ret = false; if(pCurrentNode == pTree->pRootNode) ret = true; else ret = false; return ret; } bool isReturnFromLeft(const biTreeNode* pCurrentNode) { bool ret = false; if(isChildLeftOrRight(pCurrentNode) == LEFT) ret = true; else ret = false; return ret; }