二叉树的简单面试题汇总

本文汇总了二叉树的常见面试题,包括前中后序遍历(递归与非递归)、层序遍历、求二叉树高度、叶子节点个数、第K层节点个数、判断节点存在、最近公共祖先、平衡二叉树判断、最远节点距离、重建二叉树、完全二叉树判断、二叉树镜像以及二叉搜索树转双向链表等知识点。
摘要由CSDN通过智能技术生成

目录

1.前中后序遍历(递归与非递归)

1.前序遍历

1.递归

2.非递归

2.中序遍历

1.递归

2.非递归

3.后序遍历

1.递归

2.非递归

2.层序遍历

3.求二叉树高度(深度)

4.求叶子节点个数

5.求二叉树第K层节点个数

1.求二叉树第K层节点个数(递归)

2.非递归实现求二叉树第k层的节点数

6.判断一个节点是否在一棵二叉树上

7.求两个节点的最近公共祖先

1.搜索树

2.三叉链

3.一般二叉树

8.判断一棵二叉树是否是平衡二叉树

9.求二叉树中最远两个节点的距离

10. 由前序遍历和中序遍历重建二叉树

11. 判断一棵树是否是完全二叉树

12.求二叉树的镜像(即左右子树交换)

13.将二叉搜索树转换成一个排序的双向链表。要求不能创建任何新的结点,只能调整树中结点指针的指向。


1.前中后序遍历(递归与非递归)

1.前序遍历

1.递归

void preOrder1(BinTree *root)     
{
	if (root != NULL)
	{
		cout << root->data << " ";
		preOrder1(root->lchild);
		preOrder1(root->rchild);
	}
}

2.非递归

对于任一结点P:

     1)访问结点P,并将结点P入栈;

     2)判断结点P的左孩子是否为空,若为空,则取栈顶结点并进行出栈操作,并将栈顶结点的右孩子置为当前的结点P,循环至1);若不为空,则将P的左孩子置为当前的结点P;

     3)直到P为NULL并且栈为空,则遍历结束。

void preOrder2(BinTree *root)     
{
	stack<BinTree*> s;
	BinTree *p = root;
	while (p != NULL || !s.empty())
	{
		while (p != NULL)
		{
			cout << p->data << " ";
			s.push(p);
			p = p->lchild;
		}
		if (!s.empty())
		{
			p = s.top();
			s.pop();
			p = p->rchild;
		}
	}
}

2.中序遍历

1.递归

void inOrder1(BinTree *root)     
{
	if (root != NULL)
	{
		inOrder1(root->lchild);
		cout << root->data << " ";
		inOrder1(root->rchild);
	}
}

2.非递归

 对于任一结点P,

   1)若其左孩子不为空,则将P入栈并将P的左孩子置为当前的P,然后对当前结点P再进行相同的处理;

   2)若其左孩子为空,则取栈顶元素并进行出栈操作,访问该栈顶结点,然后将当前的P置为栈顶结点的右孩子;

   3)直到P为NULL并且栈为空则遍历结束。

void inOrder2(BinTree *root)     
{
	stack<BinTree*> s;
	BinTree *p = root;
	while (p != NULL || !s.empty())
	{
		while (p != NULL)
		{
			s.push(p);
			p = p->lchild;
		}
		if (!s.empty())
		{
			p = s.top();
			cout << p->data << " ";
			s.pop();
			p = p->rchild;
		}
	}
}

3.后序遍历

1.递归

void postOrder1(BinTree *root)    
{
	if (root != NULL)
	{
		postOrder1(root->lchild);
		postOrder1(root->rchild);
		cout << root->data << " ";
	}
}

2.非递归

要保证根结点在左孩子和右孩子访问之后才能访问,因此对于任一结点P,先将其入栈。如果P不存在左孩子和右孩子,则可以直接访问它;或者P存 在左孩子或者右孩子,但是其左孩子和右孩子都已被访问过了,则同样可以直接访问该结点。若非上述两种情况,则将P的右孩子和左孩子依次入栈,这样就保证了 每次取栈顶元素的时候,左孩子在右孩子前面被访问,左孩子和右孩子都在根结点前面被访问。

void postOrder3(BinTree *root)     
{
	stack<BinTree*> s;
	BinTree *cur;                      //当前结点 
	BinTree *pre = NULL;                 //前一次访问的结点 
	s.push(root);
	while (!s.empty())
	{
		cur = s.top();
		if ((cur->lchild == NULL&&cur->rchild == NULL) ||
			(pre != NULL && (pre == cur->lchild || pre == cur->rchild)))
		{
			cout << cur->data << " ";  //如果当前结点没有孩子结点或者孩子节点都已被访问过 
			s.pop();
			pre = cur;
		}
		else
		{
			if (cur->rchild != NULL)
				s.push(cur->rchild);
			if (cur->lchild != NULL)
				s.push(cur->lchild);
		}
	}
}

2.层序遍历

void printTree(BinTree *root)//层序遍历
{
	queue<BinTree *> s;
	s.push(root);
	while (!s.empty())
	{
		BinTree *p = s.front();
		cout << p->data << "";
		s.pop();
		if (p->lchild != NULL)
			s.push(p->lchild);
		if (p->rchild != NULL)
			s.push(p->rchild);
	}
}

3.求二叉树高度(深度)

int Depth(BinTree* root)
{
	if (root == NULL)
		return 0;
	int left = Depth(root->lchild);
	int right = Depth(root->rchild);
	return left > right ? left + 1 : right + 1;
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值