问题一:完成一个函数,输入一颗二叉树,该函数输出它的镜像。二叉树节点定义如下:
struct BinaryTreeNode
{
int m_nValue;
BinaryTreeNode *m_pLeft;
BinaryTreeNode *m_pRight;
};
解题思路:二叉树的镜像过程可以理解为所有左右子节点交换的过程,先前序遍历这个树的每个节点,如果遍历到的节点有子节点,就交换它的两个子节点。当交换完所有非叶节点的左右子节点后,就得到了树的镜像。
void GetMirrorTree(BinaryTreeNode * pNode)
{
if(pNode == nullptr)
return;
if(pNode->m_pLeft == nullptr && pNode->m_pRight == nullptr)
return;
BinaryTreeNode *pTemp = pNode->m_pLeft;
pNode->m_pLeft = pNode->m_pRight;
pNode->m_pRight = pTemp;
if(pNode->m_pLeft)
GetMirrorTree(pNode->m_pLeft);
if(pNode->m_pRight)
GetMirrorTree(pNode->m_pRight);
}
问题二:实现一个函数,用来判断一棵二叉树是不是对称的。如果一个二叉树和它的镜像一样,那么它是对称的。
解题思路:利用二叉树遍历算法,二叉树一共有前序遍历、中序遍历和后序遍历。前序遍历是先遍历父节点,再遍历它的左子节点,最后遍历它的右子节点;定义一种类前序遍历的遍历算法:先遍历父节点,再遍历它的右子节点,最后遍历它的左子节点,如果两种遍历算法遍历的结果是一样的,那么二叉树就是对称的。
bool isSymmetry(BinaryTreeNode *pNode1, BinaryTreeNode *pNode2)
{
if(pNode1 == nullptr && pNode2 == nullptr)
return true;
if(pNode1 == nullptr || pNode2 == nullptr)
return false;
if(pNode1->m_nValue != pNode2->m_nValue)
return false;
return isSymmetry(pNode1->m_pLeft, pNode2->m_pRight) &&
isSymmetry(pNode1->m_pRight, pNode2->m_pLeft);
}
bool isSymmetrical(BinaryTreeNode *pNode)
{
return isSymmetry(pNode, pNode);
}
问题三:从上到下打印出二叉树的每个节点,同一层的节点按照从左到右的顺序打印。
解题思路:这其实是一种二叉树遍历方法,只不过不是前序、中序和后序遍历。可以这样考虑,先打印根节点,然后把根节点的两个子节点保存到一个容器中,此时,容器里就有两个节点了,然后取出容器中第一个节点打印,并把该节点的两个自己欸但放入容器后面,以此方法处理。从容器中取数按照先入先出的方法,因此容器应该是一个队列。
void PrintNodeFromTopToBottom(BinaryTreeNode *pTreeRoot)
{
if(!pTreeRoot)
return;
std::deque<BinaryTreeNode *> dequeTreeNode;
dequeTreeNode.push(pTreeNode);
while(dequeTreeNode.size())
{
BinaryTreeNode *pNode = dequeTreeNode.front();
dequeTreeNode.pop();
printf("%d ", dequeTreeNode->m_nValue);
if(pNode->m_pLeft)
dequeTreeNode.push_back(pNode->m_pLeft);
if(pNode->m_pRight)
dequeTreeNode.push_back(pNode->m_pRight);
}
}
问题四:从上到下按层打印二叉树,同一层的节点按从左到右的顺序打印,每一层打印到一行。
解题思路:和上面的题一样,通过一个队列来保存将要打印的节点,另外为了把二叉树的每一行打印到一行里,需要两个变量,一个用来表示当前层中还没有打印的节点,另一个用来表示下一层节点的数目。
void PrintHierarchy(BinaryTreeNode *pTreeRoot)
{
if(pTreeRoot == nullptr)
return;
std::queue<BinaryTreeNode*> nodes;
nodes.push(pTreeRoot);
int nextLevel = 0;
int toBePrinted =1;
while(!node.size())
{
BinaryTreeNode *pNode = nodes.front();
printf("%d ", pNode->m_nValue);
if(pNode->m_pLeft)
{
nodes.push(pNode->m_pLeft);
++nextLevel;
}
if(pNode->m_pRight)
{
nodes.push(pNode->m_pRight);
++nextLevel;
}
nodes.pop();
--toBePrinted;
if(toBePrinted == 0)
{
printf("\n");
toBePrinted = nextLevel;
nextLevel = 0;
}
}
}
问题五:之字形打印二叉树,实现一个函数按照之字形顺序打印二叉树,即第一行从左到右的顺序打印,第二行从右到左的顺序打印,第三行又是从左到右的顺序打印,一次类推。
解题思路:按之字形顺序打印二叉树需要两个栈,我们再打印某一层节点时,把下一层的子节点保存到相应的栈里。如果当前打印的时奇数层,则先保存左子节点再保存右子节点到第一个栈里;如果当前打印的时偶数层,则先保存右子节点再保存左子节点到第二个栈里。
void Print(BinaryTreeNode *pTreeRoot)
{
if(pTreeRoot == nullptr)
return;
std::stack<BinaryTreeNode*> levels[2];
int current = 0;
int next = 1;
levels[current].push(pTreeRoot);
while(!levels[0].empty() || !levels[1].empty())
{
BinaryTreeNode *pNode = levels[current].top();
levels[current].pop();
printf("%d ",pNode->m_nValue);
if(current == 0)
{
if(pNode->m_pLeft != nullptr)
levels[next].push(pNode->m_pLeft);
if(pNode->m_pRight != nullptr)
levels[next].push(pNode->m_pRight);
}
else
{
if(pNode->m_pRight != nullptr)
levels[next].push(pNode->m_pRight);
if(pNode->m_pLeft != nullptr)
levels[next].push(pNode->m_pLeft);
}
if(levels[current].empty())
{
printf("\n");
current = 1 - current;
next = 1 - next;
}
}
}