编程之美3.9重建二叉树-非递归实现

本文详细介绍了如何将递归算法转换为非递归算法,以二叉树的前序遍历为例进行深入探讨。通过对比递归与非递归实现,展示了两种方法的边界条件调整,并提供了完整的代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

看了书上的递归算法,想转成非递归算法。

模仿前序遍历二叉树的非递归实现。

element结构体的定义见下边的完整代码。

非递归算法:

void ReBuild1(char* pPreOrder, char* pInOrder, int nTreeLen, Node** pRoot) //模仿前序遍历二叉树的非递归算法
{
	element s[TREELEN];
	int top = -1;
	int leftLen;
	if(nTreeLen<=0 || !pPreOrder || !pInOrder)
		return;
	while(top != -1 || nTreeLen>0)
	{
		while(nTreeLen>0)
		{
			Node* pTemp = new Node;
			pTemp->chValue = *pPreOrder;
			pTemp->pLeft = NULL;
			pTemp->pRight = NULL;
			*pRoot = pTemp;
			char* pLeftEnd = pInOrder;
			leftLen = 0;
			while(*pPreOrder != *pLeftEnd)
			{
				leftLen++;
				if(leftLen>nTreeLen)
					return;
				pLeftEnd++;
			}
			top++;
			s[top].pPreOrder = pPreOrder;
			s[top].pInOrder = pInOrder;
			s[top].leftLen = leftLen;
			s[top].len = nTreeLen;
			s[top].pRoot = pRoot;
			pPreOrder++;  //对应ReBuild(pPreOrder+1,pInOrder,leftLen,pRoot->pLeft);
			pRoot = &((*pRoot)->pLeft);
			nTreeLen = leftLen;
		}
		if(top != -1)
		{
			pPreOrder = s[top].pPreOrder;
			pInOrder = s[top].pInOrder;
			leftLen = s[top].leftLen;
			nTreeLen = s[top].len;
			pRoot = s[top].pRoot;
			top--;
			pPreOrder = pPreOrder+leftLen+1; //对应ReBuild(pPreOrder+leftLen+1,pInOrder+leftLen+1,nRightLen,pRoot->pRight);
			pInOrder = pInOrder+leftLen+1;
			nTreeLen = nTreeLen-leftLen-1;
			pRoot = &((*pRoot)->pRight);
		}

	}
}


把书上递归算法的边界条件稍微改了下。

递归算法:

void ReBuild(char* pPreOrder, char* pInOrder, int nTreeLen, Node* &pRoot) //递归 不带返回值
{
	if(nTreeLen <= 0 || !pPreOrder || !pInOrder)
		return;
	Node* pTemp = new Node;
	pTemp->chValue = *pPreOrder;
	pTemp->pLeft = NULL;
	pTemp->pRight = NULL;
	pRoot = pTemp;
	char* pLeftEnd = pInOrder;
	int leftLen = 0;
	while(*pPreOrder != *pLeftEnd)
	{
		leftLen++;
		if(leftLen>nTreeLen)
			return;
		pLeftEnd++;
	}
	int nRightLen = nTreeLen-leftLen-1;
	ReBuild(pPreOrder+1,pInOrder,leftLen,pRoot->pLeft);
	ReBuild(pPreOrder+leftLen+1,pInOrder+leftLen+1,nRightLen,pRoot->pRight);
}


完整的代码:

#include<iostream>
using namespace std;

#define TREELEN 6

struct Node
{
	Node* pLeft;
	Node* pRight;
	char chValue;
};

struct element
{
	char* pPreOrder;
	char* pInOrder;
	int leftLen;
	int len;
	Node** pRoot;
};

void ReBuild(char* pPreOrder, char* pInOrder, int nTreeLen, Node* &pRoot) //递归 不带返回值
{
	if(nTreeLen <= 0 || !pPreOrder || !pInOrder)
		return;
	Node* pTemp = new Node;
	pTemp->chValue = *pPreOrder;
	pTemp->pLeft = NULL;
	pTemp->pRight = NULL;
	pRoot = pTemp;
	char* pLeftEnd = pInOrder;
	int leftLen = 0;
	while(*pPreOrder != *pLeftEnd)
	{
		leftLen++;
		if(leftLen>nTreeLen)
			return;
		pLeftEnd++;
	}
	int nRightLen = nTreeLen-leftLen-1;
	ReBuild(pPreOrder+1,pInOrder,leftLen,pRoot->pLeft);
	ReBuild(pPreOrder+leftLen+1,pInOrder+leftLen+1,nRightLen,pRoot->pRight);
}

void ReBuild1(char* pPreOrder, char* pInOrder, int nTreeLen, Node** pRoot) //模仿前序遍历二叉树的非递归算法
{
	element s[TREELEN];
	int top = -1;
	int leftLen;
	if(nTreeLen<=0 || !pPreOrder || !pInOrder)
		return;
	while(top != -1 || nTreeLen>0)
	{
		while(nTreeLen>0)
		{
			Node* pTemp = new Node;
			pTemp->chValue = *pPreOrder;
			pTemp->pLeft = NULL;
			pTemp->pRight = NULL;
			*pRoot = pTemp;
			char* pLeftEnd = pInOrder;
			leftLen = 0;
			while(*pPreOrder != *pLeftEnd)
			{
				leftLen++;
				if(leftLen>nTreeLen)
					return;
				pLeftEnd++;
			}
			top++;
			s[top].pPreOrder = pPreOrder;
			s[top].pInOrder = pInOrder;
			s[top].leftLen = leftLen;
			s[top].len = nTreeLen;
			s[top].pRoot = pRoot;
			pPreOrder++;  //对应ReBuild(pPreOrder+1,pInOrder,leftLen,pRoot->pLeft);
			pRoot = &((*pRoot)->pLeft);
			nTreeLen = leftLen;
		}
		if(top != -1)
		{
			pPreOrder = s[top].pPreOrder;
			pInOrder = s[top].pInOrder;
			leftLen = s[top].leftLen;
			nTreeLen = s[top].len;
			pRoot = s[top].pRoot;
			top--;
			pPreOrder = pPreOrder+leftLen+1; //对应ReBuild(pPreOrder+leftLen+1,pInOrder+leftLen+1,nRightLen,pRoot->pRight);
			pInOrder = pInOrder+leftLen+1;
			nTreeLen = nTreeLen-leftLen-1;
			pRoot = &((*pRoot)->pRight);
		}

	}
}

Node* ReBuild2(char* pPreOrder, char* pInOrder, int nTreeLen) //递归 带返回值
{
	if(nTreeLen<=0 || !pPreOrder || !pInOrder)
		return NULL;
	Node* pTemp = new Node;
	pTemp->chValue = *pPreOrder;
	int leftLen = 0;
	char* pEnd = pInOrder;
	while(*pPreOrder != *pEnd)
	{
		leftLen++;
		pEnd++;
		if(leftLen > nTreeLen)
			return NULL;
	}
	int rightLen = nTreeLen - leftLen - 1;
	pTemp->pLeft = ReBuild2(pPreOrder+1,pInOrder,leftLen);
	pTemp->pRight = ReBuild2(pPreOrder+leftLen+1,pEnd+1,rightLen);
	return pTemp;
}

void PreOrder(Node* root)
{
	if(root == NULL) return;
	cout<<root->chValue<<endl;
	PreOrder(root->pLeft);
	PreOrder(root->pRight);
	delete root;  //释放内存
}

int main()
{
	char preOrder[TREELEN]={'a','b','d','c','e','f'};
	char inOrder[TREELEN]={'d','b','a','e','c','f'};
	Node* pRoot = NULL;
	ReBuild(preOrder,inOrder,TREELEN,pRoot);
	PreOrder(pRoot); //释放内存
	cout<<"************************"<<endl;
	ReBuild1(preOrder,inOrder,TREELEN,&pRoot);
	PreOrder(pRoot); //释放内存
	cout<<"************************"<<endl;
	pRoot = ReBuild2(preOrder,inOrder,TREELEN);
	PreOrder(pRoot); //释放内存
	system("pause");
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值