在面试中我们经常碰到二叉树的题目以及相关的题目,本文是本人对于面试中二叉树相关题目的一个总结。
二叉树的数据结构:包含数据以及左右孩子节点.
struct binary_tree_node
{
int data;
binary_tree_node* left_child;
binary_tree_node* right_child;
};
关于二叉树的的创建请看我另外一篇博文:
使用数组的方法建立一颗二叉树
在面试中我们经常碰到的相关的题目有:
1.三种遍历二叉树的方式
2.顶部开始逐层打印二叉树结点就是按层次输出二叉树
3.三种非递归版本遍历二叉树
4.二叉树节点的个数
5.二叉树的深度
6.已知前序遍历和中序遍历,重建二叉树
7.判断一颗二叉树是不是完全二叉树
1.三种遍历二叉树的方式:
前序:root 、 left、 right
中序:left 、root、right
后序:left、right、root
//Preorder traversing binary tree
void preoder_traverse(binary_tree_node *root)
{
if (root == NULL)
return;
else
{
cout << root->data << " ";
preoder_traverse(root->left_child);
preoder_traverse(root->right_child);
}
}
//inorder traversal
void inorder_traverse(binary_tree_node *root)
{
if (root == NULL)
return;
else
{
inorder_traverse(root->left_child);
cout << root->data << " ";
inorder_traverse(root->right_child);
}
}
//postorder traversal
void postorder_traverse(binary_tree_node *root)
{
if (root == NULL)
return;
else
{
postorder_traverse(root->left_child);
postorder_traverse(root->right_child);
cout << root->data << " ";
}
}
2.顶部开始逐层打印二叉树结点就是按层次输出二叉树
//-------------------------------------------------------------------------
//顶部开始逐层打印二叉树结点
void level_print(binary_tree_node*root)
{
if (root == NULL)
return;
queue<binary_tree_node*> q;
q.push(root);
while (!q.empty())
{
binary_tree_node*temp = q.front();
cout << temp->data << " ";
if (temp->left_child != NULL)
q.push(temp->left_child);
if (temp->right_child != NULL)
q.push(temp->right_child);
q.pop();
}
}
3.三种非递归版本遍历二叉树
<pre name="code" class="cpp">//------------------------------------------------------------------------------------
//非递归前序遍历
void preOrder_tree(binary_tree_node *root) //非递归前序遍历
{
stack<binary_tree_node*> s;
binary_tree_node *p = root;
while (p != NULL || !s.empty())
{
if (p != NULL)
{
cout << p->data << " ";
s.push(p);
p = p->left_child;
}
else
{
p = s.top();
s.pop();
p = p->right_child;
}
}
}
//中根遍历,使用stack实现
void inorder_tree(binary_tree_node*root)
{
if (root == NULL)
return;
stack<binary_tree_node*> s;
binary_tree_node* temp = root;
while (NULL != temp || !s.empty())
{
if (NULL != temp)
{
s.push(temp);
temp = temp->left_child;
}
else
{
temp = s.top();
s.pop();
cout << temp->data << " ";
temp = temp->right_child;
}
}
}
//非递归后序遍历
//要保证根结点在左孩子和右孩子访问之后才能访问,因此对于任一结点P,先将其入栈。
//如果P不存在左孩子和右孩子,则可以直接访问它;或者P存在左孩子或者右孩子,
//但是其左孩子和右孩子都已被访问过了,则同样可以直接访问该结点。若非上述两种情况,
//则将P的右孩子和左孩子依次入栈,这样就保证了每次取栈顶元素的时候,左孩子在右孩子
//前面被访问,左孩子和右孩子都在根结点前面被访问。
void postOrder_tree(binary_tree_node *root) //非递归后序遍历
{
stack<binary_tree_node*> s;
binary_tree_node *cur; //当前结点
binary_tree_node *pre = NULL; //前一次访问的结点
s.push(root);
while (!s.empty())
{
cur = s.top();
if ((cur->left_child == NULL&&cur->right_child == NULL) ||
(pre != NULL && (pre == cur->left_child || pre == cur->right_child)))
{
cout << cur->data << " "; //如果当前结点没有孩子结点或者孩子节点都已被访问过
s.pop();
pre = cur;
}
else
{
if (cur->right_child != NULL)
s.push(cur->right_child);
if (cur->left_child != NULL)
s.push(cur->left_child);
}
}
}
4.二叉树节点个数
//-------------------------------------------
//the num of the binary tree
int get_num(binary_tree_node *root)
{
if (root == 0)
return 0;
return get_num(root->left_child) + get_num(root->right_child) + 1;
}
5.二叉树的深度
//the depth of the binary tree
int depth(binary_tree_node *root)
{
if (root == 0)
return 0;
int depth_left = depth(root->left_child);
int depth_right = depth(root->right_child);
return (depth_left > depth_right) ? (depth_left + 1):(depth_right + 1);
}
6.已知前序遍历和中序遍历,重建二叉树
//----------------------------------------------
//已知前序和中序,重建二叉树
binary_tree_node*rebiuld_tree(int *preorder, int *inorder, int nodenum)
{
if (preorder == NULL || inorder == NULL || nodenum <= 0)
return NULL;
binary_tree_node*root = new binary_tree_node;
root->data = preorder[0];
root->left_child = NULL;
root->right_child = NULL;
int root_index_inorder = -1;
for (int i = 0; i < nodenum; ++i)
{
if (root->data == inorder[i])
root_index_inorder = i;
}
//重建左子树
int nodenumleft = root_index_inorder;
int *preOderleft = preorder + 1;
int *inOderleft = inorder;
root->left_child = rebiuld_tree(preOderleft, inOderleft, root_index_inorder);
//重建右字数
int nodenumright = nodenum - nodenumleft - 1;
int *preOrderright = preorder + nodenumleft + 1;
int *inOrderright = inorder + nodenumleft + 1;
root->right_child = rebiuld_tree(preOrderright, inOrderright, nodenumright);
return root;
}
7.判断一颗二叉树是不是完全二叉树
//判断一个二叉树是不是完全二叉树
bool iscompeletbinarytree(binary_tree_node*root)
{
if (root == NULL)
return false;
queue<binary_tree_node*> q;
q.push(root);
bool nochild = false;
bool result = true;
while (!q.empty())
{
binary_tree_node* temp;
temp = q.front();
if (nochild)//一旦出现 左右孩子为空的情况 或者 左孩子不为空右孩子为空,就要判断后面的节点
{
if (temp->left_child != NULL || temp->right_child != NULL)
{
return false;
break;
}
}
else//只要
{
if (temp->left_child != NULL&&temp->right_child != NULL)
{
q.push(temp->left_child);
q.push(temp->right_child);
}
else if (temp->left_child != NULL&&temp->right_child == NULL)
{
nochild = true;
q.push(temp->left_child);
}
else if (temp->left_child == NULL&&temp->right_child != NULL)
{
result = false;
break;
}
else
nochild = true;
}
}
return result;
}