二叉树面试题总汇

1、前序遍历(递归与非递归)

//前序遍历:先访问根节点,再左子树,再右子树
void PrevOrder(Node* root)
{
	if (root == NULL)
		return ;
	cout << root->value << " ";
	PrevOrder(root->Lchild);
	PrevOrder(root->Rchild);
}
//前序非递归,利用栈,先访问根节点并依次把左路节点依次压入栈,拿出来在子问题解决
void PrevOrder_No(Node* root)
{
	if(root == NULL)
		return;
	stack<Node*> s;
	Node* cur = root;
	while (cur || !s.empty())
	{
		while (cur)
		{
			cout << cur->value << " ";
			s.push(cur);
			cur = cur->Lchild;
		}
		cur = s.top()->Rchild;
		s.pop();
	}
	cout << endl;
}

2、中序遍历(递归与非递归)

//中序遍历  递归,左根右
void MidTreeOrder(Node* root)
{
	if (root == NULL)
		return;
	MidTreeOrder(root->Lchild);
	cout << root->value << " ";
	MidTreeOrder(root->Rchild);

}
//中序,非递归(同前序一样思想,不过是从栈中拿出来再访问节点)
void MidTreeOrder_No(Node* root)
{
	if (root == NULL)
		return;
	Node* cur = root;
	stack<Node*> s1;
	while (cur || !s1.empty())
	{
		while (cur)
		{
			s1.push(cur);
			cur = cur->Lchild;
		}
		cur = s1.top();
		cout << cur->value << " ";
		s1.pop();
		cur = cur->Rchild;
	}
	cout << endl;
}

3、后序遍历

//后续遍历:先访问左节点,再访问右节点,再访问根节点
void PostTreeOrder(Node* root)
{
	if (root == NULL)
		return;
	PostTreeOrder(root->Lchild);
	PostTreeOrder(root->Rchild);
	cout << root->value << " ";

}
//后续,非递归
void PostTreeOrder_No(Node* root)
{
	if (root == NULL)
		return;
	Node* cur = root;
	int flag = 0;
	Node* ptag = NULL;
	stack<Node*> s2;
	s2.push(cur);
	cur = cur->Lchild;
	while ( !s2.empty())
	{
		while (cur)
		{
			s2.push(cur);
			cur = cur->Lchild;
		}
		ptag = NULL;//ptag指向已访问过的cur(null)
		flag = 1;//设置当前cur已访问
		//现在一种右路没有节点(需要循环输出),一种右路有节点(子问题  ——需要循环压入)
		while (!s2.empty() && flag ==1 )
		{
			cur = s2.top();
			if (cur->Rchild == ptag)//右孩子不存在,或者右孩子已经访问过
			{
				cout << cur->value << " ";
				s2.pop();
				ptag = cur;   //重置
			}
			else
			{                         //访问右孩子,重置flag
				cur = cur->Rchild;
				flag = 0;
			}
		}

	}
}

4、求树的深度

int BinaryTreeDepth(Node* root)
{
	
	if (root == NULL)
		return 0;
	int lenleft = BinaryTreeDepth(root->Lchild);
	int lenright = BinaryTreeDepth(root->Rchild);
	return lenleft > lenright ? lenleft + 1 : lenright + 1;

}

5、判断一颗树是不是平衡二叉树

//判断一棵树是不是平衡二叉树
bool IsBalancedTree_old(Node* root)
{
	if (root == NULL)
		return true;
	int lenleft = BinaryTreeDepth(root->Lchild);//每往下一层,计算一次深度,时间复杂度N^2
	int lenright = BinaryTreeDepth(root->Rchild);
	int temp = lenleft - lenright;
	if (temp >1 || temp < -1)
		return false;
	return IsBalancedTree_old(root->Lchild) && IsBalancedTree_old(root->Rchild);//满足条件,计算它的下一层的左右子树
}




//判断是否为平衡二叉树(优化)
bool _IsBlancedtree_new(Node* root,int* pDepth)
{
	if (root == NULL)
	{
		*pDepth = 0;
		return true;
	}
	int left, right;
	if (_IsBlancedtree_new(root->Lchild, &left) && _IsBlancedtree_new(root->Rchild, &right))//后序遍历思想
	{
		int temp = left - right;
		if (temp <= 1 && temp >= -1)//拿到深度值
		{
			*pDepth = left > right ? left + 1 : right + 1;
			return true;
		}
	}
	
	return false;
}
bool IsBlancedTree_new(Node* root)
{
	int pDepth;
	bool tag = _IsBlancedtree_new(root, &pDepth);
	return tag;
}

6、得到树的节点的个数

//得到树的节点个数
void _GetTreeSize(Node* root, size_t& size)
{
	if (root == NULL)
		return;
	++size;
	_GetTreeSize(root->Lchild,size);
	_GetTreeSize(root->Rchild,size);
}

size_t GetTreeSize(Node* root)
{
	size_t size;
	_GetTreeSize(root, size);
	return size;
}

7、得到树的叶子节点的个数

//叶子节点的个数:利用前序遍历思想
int MunLeavesNodeOfTree(Node* root)
{
	if (root == NULL)
		return 0;
	
	Node* cur = root; 
	stack<Node*> s4;
	int count = 0;
	while (cur || !s4.empty())
	{
		while (cur)
		{
			s4.push(cur);
			cur = cur->Lchild;
		}
		cur = s4.top();
		s4.pop();
		if (cur->Rchild == NULL && cur->Lchild == NULL)
			count++;
		cur = cur->Rchild;
	}
	return count;
}

8、计算二叉树第K层节点个数

//第K层节点个数:
int GetNumKOfTree(Node* root, int k)
{
	if (root == NULL || k <1)
		return 0;
	if (k == 1)
		return 1;
	//求第k层节点个数,返回左子树k-1层节点个数与右子树k-1层节点个数之和
	int numLeft = GetNumKOfTree(root->Lchild, k - 1); // 左子树中k-1层的节点个数  
	int numRight = GetNumKOfTree(root->Rchild, k - 1); // 右子树中k-1层的节点个数  
	return (numLeft + numRight);
}

9、判断一个值是否在二叉树当中

//判断一个值是否存在二叉树中
bool JudgeKOfTree(Node* root, size_t K)
{
	if (root == NULL)
		return false;
	if (root->value == K)
		return true;
	return JudgeKOfTree(root->Lchild,K)||JudgeKOfTree(root->Rchild,K);
	//左右子树只要有一颗存在就返回ture
}

10、求一颗二叉树镜像

//求一颗二叉树的镜像 :两棵树左右对称
void  MirrorRecursively(Node* root)
{
	if (root == NULL)
		return ;
	if (root->Lchild == NULL && root->Rchild == NULL)
		return ;
	Node* temp = root->Lchild;//交换左右子树
	root->Lchild = root->Rchild;
	root->Rchild = temp;
	if (root->Lchild)//递归下去
		MirrorRecursively(root->Lchild);
	if (root->Rchild)
		MirrorRecursively(root->Rchild);
}

11、二叉树的销毁

void DestoryTree(Node*& root)//防止野指针
{
	if (root == NULL)
		return;
	DestoryTree(root->Lchild);
	DestoryTree(root->Rchild);
	delete root;
	root = NULL;

}

12、判断一棵树是否是完全二叉树,一个子树没有孩子,后面的子树都不能有孩子,利用队列;


bool IsCompleteTree(Node* root)
{
	if (root == NULL)
		return true;
	queue<Node*> s;
	bool mustnochild = false;
	s.push(root);
	while (!s.empty())
	{
		Node* cur = s.front();
		s.pop();
		if (mustnochild == true)//左右子树都没有孩子了
		{
			if (cur->Lchild != NULL || cur->Rchild != NULL)
				return false;
		}
		if (cur->Lchild == NULL && cur->Rchild == NULL)
			mustnochild = true;
		if (cur->Lchild != NULL && cur->Rchild == NULL)//有左孩子,没有右孩子
		{
			s.push(cur->Lchild);
			mustnochild = true;
		}
		if (cur->Lchild == NULL && cur->Rchild != NULL)//没左孩子,有右孩子
			return false;
		if (cur->Lchild != NULL && cur->Rchild != NULL)//左右都有孩子,则插入
		{
			s.push(cur->Lchild);
			s.push(cur->Rchild);
		}
	}
	return true;
}

13、给定一颗二叉树,和其中的一个节点,怎么找到中序遍历的下一个节点


//左,根,右,
Node* GetNextNode(Node* pnode)//假设一定在,
{
	if (pnode == NULL)
		return NULL;
	Node* cur = pnode;
	if (cur->Rchild != NULL)//cur作为根
	{
		cur = cur->Rchild;
		while (cur->Lchild)
			cur = cur->Lchild;
		return cur;
    }
	if (cur->Parent != NULL && cur->Parent->Lchild == cur)//cur作为左子树
		return cur->Parent;
	if (cur->Parent != NULL && cur->Parent->Rchild == cur)//cur作为右子树某一点
	{
		while (cur->Parent && cur->Parent->Rchild == cur)
		{
			cur = cur->Parent;
		}
		cur = cur->Parent;
		return cur;
	}
	return NULL;
}

14、判断一颗二叉树是不是对称的

bool IsSymmet(Node* root1, Node* root2)
{
	if (root1 == NULL && root2 == NULL)
		return true;
	if (root1 == NULL || root2 == NULL)
		return false;
	if (root1->value != root2->value)
		return false;
	return IsSymmet(root1->Lchild, root2->Rchild) && IsSymmet(root1->Rchild, root2->Lchild);
}
bool IsSymmet(Node* root)
{
	return IsSymmet(root, root);
}

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

void _ToList(Node* cur, Node*& prev)
{
	if (cur == NULL)
		return;

	_ToList(cur->Lchild, prev);
	// 
	cur->Lchild = prev;
	if (prev)
		prev->Rchild = cur;

	prev = cur;

	_ToList(cur->Rchild, prev);
}

Node* ToList(Node* root)
{
	Node* prev = NULL;
	_ToList(root, prev);

	Node* head = root;
	while (head && head->Lchild)
	{
		head = head->Lchild;
	}

	return head;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值