算法导论 10.4-5 O(n)时间非递归遍历二叉树

一、题目

写一个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;
}


 

2.caselib.h
#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();
};

3.caselib.cpp
//#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();
}

4.funclib.h
#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);

5.funclib.cpp
#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;
}


你可能感兴趣的:(算法,二叉树,遍历,算法导论,非递归)