二叉树的层次遍历+每一层单行输出

给定一棵二叉树,要求按层次遍历该二叉树,每一层将单独输出一行

难点就在于每一层的结点输出一行。

本着鄙视递归的潜意识,先用迭代来做,递归的做法放在最后。

类似于广度优先遍历,故采用队列 做为辅助记忆结构。

struct TreeNode
{
	int val;
	struct TreeNode *left;
	struct TreeNode *right;
	TreeNode(int x) :val(x), left(nullptr), right(nullptr) {}
};

本题的难点就在于每一层要单独一行输出。对此,叶劲峯提出了一个算法,其主要特点是在
队列中每一层的最后一个节点之后插入一个傀儡节点,当我们遇到一个傀儡节点时,就输出换行符,因为此时我们知道已经遍历了一层,要开始新的一层了。

叶劲峯的方法比较好地解决了换行判断的问题。但空间复杂度还有下降的空间。我们记k为所有层中的结点最多的那一层的结点数,则他的算法的空间复杂度为O(k+logN)。k一般都为N/2,即空间复杂度为O(N/2+logN)。若给定的N个结点的树高度为N,则其空间复杂度为O(1.5N)。

能不能换种方法,在同样简便的情况下,使空间复杂度在最坏的情况下只有O(0.5N)?

答案是该方法是存在的。

方法说起来很简单,只要仔细想,应该都能想出这种方法来。

定义两个变量curLevelCount和nextLevelCount来分别保存当前层和下一层的结点数。

显然,curLevelCount的初始值为1,因为只有一个根结点,而nextLevelCount由于未知,故置为0.

void levelOrder(TreeNode* root)
{
	if(nullptr == root)
		return nullptr;
	int curLevelCount = 1, nextLevelCount = 0;
	std::queue<int> q;
	q.push(root);
	TreeNode* curPtr = nullptr;
	while(!q.empty())
	{
		curPtr = q.front();
		q.pop();
		std::cout << curPtr->val << " ";
		curLevelCount--;
		
		if(nullptr != curPtr->left)
		{
			q.push(curPtr->left);
			nextLevelCount++;
		}
		if(nullptr != curPtr->right)
		{
			q.push(curPtr->right);
			nextLevelCount++;
		}
		if(0 == curLevelCount)
		{
			endl(std::cout);
			curLevelCount = nextLevelCount;
			nextLevelCount = 0;
		}
	}
}

迭代方法结束。

下面开始讲解递归的方法。

递归解法就有一点无脑了。

我们用一个形参来表示当前层数,指定层数的结点才输出。

既然需要指定层数,我们就要获取给定树的高度。因为给定的二叉树并不一定是完全二叉树,所以即使给定了结点总数,也不能直接计算出树的高度。

//计算指定树的高度
int getTreeHeight(TreeNode* root)
{
	if(nullptr == root)
		return 0;
	int leftHeight = getTreeHeight(root->left);
	int rightHeight = getTreeHeight(root->right);
	return std::max(leftHeight, rightHeight)+1;
}
void printNodeAtLevel(TreeNode* root,int level)  
{  
    if(nullptr == root || level < 0 )  
        return;  
  
    if(0 == level)  
    {  
        std::cout << root->val << " ";  
        return;  
    }  
  
    // 左子树的 level - 1 级  
    printNodeAtLevel(root->left,  level - 1);  
  
    // 右子树的 level - 1 级  
    printNodeAtLevel(root->right, level - 1);  
}

void levelOrder(const TreeNode* root)
{
	if(nullptr == root)
		return;
	int totalLevel = getTreeHeight(root);
	for(int i = 0; i < totalLevel; i++)
	{
		printNodeAtLevel(root, i);
		endl(std::cout); //打印完一层,换行
	}
}

点赞