二叉树的基本操作及面试题

1.二叉树概念
二叉树(Binary Tree)是n(n >= 0)个结点的有限集合,该集合或者为空集(称为空二叉树),或者由一个根结点和两棵互不相交的、分别称为根结点的左子树和右子树组成。


2.二叉树的特点

  • 每个结点最多有两个子树,所以二叉树中不存在度大于2的结点;注意不是只有两棵子树,而是最多有,没有子树或者由一棵子树都是可以的。
  • 左右子树是有顺序的次序不能任意颠倒。
  • 即使树中摸个结点只有一棵子树,也要区分它是左子树还是右子树。

3.二叉树的基本形态
这里写图片描述

  • (1)空二叉树
  • (2)只有一个根结点
  • (3)根结点只有左子树
  • (4)根结点只有右子树
  • (5)根结点既有左子树又有右子树
    注:因此二叉树由以上5种情况组成。

4.特殊二叉树
【1.斜树】
在这里插入图片描述

顾名思义,斜树一定是要斜的,但往哪斜还是有讲究的;所有结点只有左子树的二叉树叫左斜树,所有结点只有右子树的二叉树叫右斜树,这两者统称为斜树。斜树有很明显的特点,就是每一层都只有一个结点,结点的个数与二叉树的深度相同。

【2.满二叉树】
在这里插入图片描述
在一棵二叉树中,如果所有分支结点都存在左子树和右子树,并且所有的叶子结点都在同一层上,这样的二叉树称为满二叉树。

特点:

  • (1)叶子只能出现在最下一层,出现在其他层就不可能达到平衡。
  • (2)非叶子结点的度一定是2,否则就是“缺胳膊少腿”了。
  • (3)在同样深度的二叉树中,满二叉树的结点个数最多,叶子数最多。

【3.完全二叉树】
在这里插入图片描述
对一棵具有n个结点的二叉树按层序编号,如果编号为i(1 <= i <= n)的结点与同样深度的满二叉树中编号为i的结点在二叉树中的位置完全相同,则这棵二叉树称为完全二叉树。

特点:

  • (1)叶子结点只能出现在最下两层。
  • (2)最下层的叶子一定集中在左部连续位置。
  • (3)倒数第二层,若有叶子结点,一定在右连续位置。
  • (4)如果结点度为1,则该结点只有左孩子,即不存在只有右子树的情况。
  • (5)同样结点的二叉树,完全二叉树的深度最小。

5.二叉树性质

  • 性质1 :在二叉树的第i层上至多有2^(i-1)个结点(i >= 1)。

  • 性质2 :深度为k的二叉树至多有2^k -1个结点(i >= 1)。

  • 性质3 :对任何一棵二叉树T,如果其终端结点为n0,度为2的结点树为n2,则n0 = n2 +1。

  • 性质4 :具有n个结点的完全二叉树的深度为㏒n +1(此处的㏒n表示不大于它的最大整数)。

  • 性质5 :如果对一棵有n个结点的完全二叉树的结点按层序编号,对任一结点i(1 <= i <= n)有:

    • 如果 i =1,则结点i是二叉树的根,无双亲;如果 i > 1,则双亲是结点不大于i/2的整数。
    • 如果 2i > n,则结点 i 无左孩子(结点 i 为叶子结点);否则左孩子是 2i。
    • 如果 2i + 1 > n,则结点 i 无右孩子;否则右孩子为 2i + 1。

6.完整代码块

/************************************/
//BinTree.h


typedef int BDataType;

typedef struct BTNode
{
	struct BTNode *_pLeft;
	struct BTNode *_pRight;
	BDataType data;
}BTNode;


//创建二叉树
void CrateBinTree(BTNode **pRoot, char *str, int size, int *index, BDataType inValid);

//前序遍历二叉树
void PreOrderBinTree(BTNode *pRoot);

//前序遍历二叉树(非递归)
void PreOrderBinTreeNor(BTNode *pRoot);

//中序遍历二叉树
void InOrderBinTree(BTNode *pRoot);

//中序遍历二叉树(非递归)
void InOrderBinTreeNor(BTNode *pRoot);

//后序遍历二叉树
void PostOrderBinTree(BTNode *pRoot);

//后序遍历二叉树(非递归)
void PostOrderBinTreeNor(BTNode *pRoot);

//层序遍历二叉树
void LevelOrderBintree(BTNode *pRoot);

//拷贝二叉树
BTNode *CopyBinTree(BTNode *pRoot);

//销毁二叉树
void DestoryBinTree(BTNode **pRoot);

//求二叉树结点数
int GetBTNodeCount(BTNode *pRoot);

//求叶子结点数
int GetLeafNodeCount(BTNode *pRoot);

//求低K层结点数
int GetKLevelNodeCount(BTNode *pRoot, int k);

//求二叉树的高度
int HeightBinTree(BTNode *pRoot);

//判断一个结点是否在二叉树中
int IsBTNodeBinTree(BTNode*pRoot, BTNode *pNode);

//查找一个结点的双亲结点
BTNode * GetBTNodeParent(BTNode *pRoot, BTNode *pNode);

//判断是否是完全二叉树
int IsCompleteBinTree(BTNode *pRoot);

//二叉树的镜像
void MirrorBinTree(BTNode *pRoot);

//二叉树的镜像(非递归)
void MirrorBinTreeNor(BTNode *pRoot);

//获取一个结点的左孩子结点
BTNode *LeftChild(BTNode *pRoot);

//获取一个结点的右孩子结点
BTNode *RightChild(BTNode *pRoot);



/************************************/
//BinTree.c
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
#include "LQueue.h"
#include "Stack.h"



void Swap(BTNode **left, BTNode **right)
{
	BTNode *tmp;
	tmp = *left;
	*left = *right;
	*right = tmp;
}


//创建新结点
static BTNode *BuyBTNode(BDataType data)
{
	BTNode *pNewNode;
	pNewNode = (BTNode *)malloc(sizeof(BTNode));
	if (NULL == pNewNode)
	{
		printf("创建新结点失败!\n");
		assert(0);
	}
	pNewNode->data = data;
	pNewNode->_pLeft = NULL;
	pNewNode->_pRight = NULL;
}

//创建二叉树
void CrateBinTree(BTNode **pRoot, char *str, int size, int *index, BDataType invalid)
{
	if (*index < size && invalid != str[*index])
	{
		//创建根结点
		*pRoot = BuyBTNode(str[*index]);
		
		++(*index);
		//创建左子树
		CrateBinTree(&((*pRoot)->_pLeft), str, size, index, invalid);

		++(*index);
		//创建右子树
		CrateBinTree(&((*pRoot)->_pRight), str, size, index, invalid);
	}
}

//前序遍历二叉树
void PreOrderBinTree(BTNode *pRoot)
{
	if (pRoot)
	{
		printf("%c", pRoot->data);
		PreOrderBinTree(pRoot->_pLeft);
		PreOrderBinTree(pRoot->_pRight);
	}
}

//前序遍历二叉树(非递归)
void PreOrderBinTreeNor(BTNode *pRoot)
{
	Stack s;
	BTNode *pCur = NULL;
	if (NULL == pRoot)
		return NULL;

	StackInit(&s);
	StackPush(&s, pRoot);
	while (!StackEmpty(&s))
	{
		pCur = StackTop(&s);
		printf("%c", pCur->data);
		StackPop(&s);
		if (pCur->_pRight)
			StackPush(&s, pCur->_pRight);
		if (pCur->_pLeft)
			StackPush(&s, pCur->_pLeft);
	}
}

//中序遍历二叉树
void InOrderBinTree(BTNode *pRoot)
{
	if (pRoot)
	{
		InOrderBinTree(pRoot->_pLeft);
		printf("%c", pRoot->data);
		InOrderBinTree(pRoot->_pRight);
	}
}

//中序遍历二叉树(非递归)
void InOrderBinTreeNor(BTNode *pRoot)
{
	Stack s;
	BTNode *pCur = pRoot;
	if (NULL == pRoot)
		return;
	StackInit(&s);
	while (!StackEmpty(&s) || pCur)
	{
		while (pCur)
		{
			StackPush(&s, pCur);
			pCur = pCur->_pLeft;
		}

		pCur = StackTop(&s);
		printf("%c", pCur->data);
		StackPop(&s);
		pCur = pCur->_pRight;
	}
}

//后序遍历二叉树
void PostOrderBinTree(BTNode *pRoot)
{
	if (pRoot)
	{
		PostOrderBinTree(pRoot->_pLeft);
		PostOrderBinTree(pRoot->_pRight);
		printf("%c", pRoot->data);
	}
}

//后序遍历二叉树(非递归)
void PostOrderBinTreeNor(BTNode *pRoot)
{
	Stack s;
	BTNode *pTop = NULL;
	BTNode *pPre = NULL;
	BTNode *pCur = pRoot;
	if (NULL == pRoot)
		return;
	StackInit(&s);
	while (!StackEmpty(&s) || pCur)
	{
		while (pCur)
		{
			StackPush(&s, pCur);
			pCur = pCur->_pLeft;
		}

		pTop = StackTop(&s);
		if (NULL == pTop->_pRight || pPre == pTop->_pRight)
		{
			printf("%c", pTop->data);
			pPre = pTop;
			StackPop(&s);
		}
		else
			pCur = pTop->_pRight;
	}
}

//层序遍历
void LevelOrderBintree(BTNode *pRoot)
{
	LQueue q;
	BTNode *pCur = NULL;
	if (NULL == pRoot)
		return;
	LQueueInit(&q);
	LQueuePush(&q, pRoot);
	while (!LQueueEmpty(&q))
	{
		pCur = LQueueTop(&q);
		printf("%c", pCur->data); 
		if (pCur->_pLeft)
			LQueuePush(&q, pCur->_pLeft);
		if (pCur->_pRight)
			LQueuePush(&q, pCur->_pRight);
		LQueuePop(&q);
	}
}

//拷贝二叉树
BTNode *CopyBinTree(BTNode *pRoot)
{
	if (NULL == pRoot)
		return;
	if (pRoot)
		pRoot = BuyBTNode(pRoot->data);
	if (pRoot->_pLeft)
		CopyBinTree(pRoot->_pLeft);
	if (pRoot->_pRight)
		CopyBinTree(pRoot->_pRight);
	return pRoot;
}

//销毁二叉树
void DestoryBinTree(BTNode **pRoot)
{
	if (NULL == *pRoot)
		return;

	DestoryBinTree(&((*pRoot)->_pLeft));
	DestoryBinTree(&((*pRoot)->_pRight));

	free(*pRoot);
	*pRoot = NULL;
}

//求二叉树结点数
int GetBTNodeCount(BTNode *pRoot)
{
	if (NULL == pRoot)
		return 0;
	return GetBTNodeCount(pRoot->_pLeft) + GetBTNodeCount(pRoot->_pRight) + 1;
}

//求叶子结点数
int GetLeafNodeCount(BTNode *pRoot)
{
	if (NULL == pRoot)
		return 0;
	if (NULL == pRoot->_pLeft && NULL == pRoot->_pRight)
		return 1;
	return GetLeafNodeCount(pRoot->_pLeft) + GetLeafNodeCount(pRoot->_pRight);
}

//求低K层结点数
int GetKLevelNodeCount(BTNode *pRoot, int k)
{
	if (NULL == pRoot || 0 == k)
		return 0;
	if (1 == k)
		return 1;
	return GetKLevelNodeCount(pRoot->_pLeft, k - 1) + GetKLevelNodeCount(pRoot->_pRight, k - 1);
}

//求二叉树的高度
int HeightBinTree(BTNode *pRoot)
{
	if (NULL == pRoot)
		return 0;
	return (HeightBinTree(pRoot->_pLeft) > HeightBinTree(pRoot->_pRight)) ? HeightBinTree(pRoot->_pLeft)+1 : HeightBinTree(pRoot->_pRight)+1;
}

//判断一个结点是否在二叉树中
int IsBTNodeBinTree(BTNode*pRoot, BTNode *pNode)
{
	if (NULL == pRoot || NULL == pNode)
		return 0;
	if (pRoot == pNode)
		return 1;
	if (IsBTNodeBinTree(pRoot->_pLeft, pNode))
		return 1;
	return IsBTNodeBinTree(pRoot->_pRight, pNode);
}

//查找一个结点的双亲结点
BTNode * GetBTNodeParent(BTNode *pRoot, BTNode *pNode)
{
	BTNode *Parent = NULL;
	if (NULL == pRoot || NULL == pNode || (NULL == pRoot->_pLeft && NULL == pRoot->_pRight))
		return NULL;
	if (pRoot->_pLeft == pNode || pRoot->_pRight == pNode)
		return pRoot;
	if (Parent = GetBTNodeParent(pRoot->_pLeft, pNode))
		return Parent;
	return GetBTNodeParent(pRoot->_pRight, pNode);
}

//判断是否是完全二叉树
int IsCompleteBinTree(BTNode *pRoot)
{
	LQueue q;
	int flag = 0;
	BTNode *pCur = NULL;
	if (NULL == pRoot)
		return 1;

	LQueueInit(&q);
	LQueuePush(&q, pRoot);
	while (!LQueueEmpty(&q))
	{
		pCur = LQueueTop(&q);
		LQueuePop(&q);
		if (1 == flag)
		{
			if (pCur->_pLeft || pCur->_pRight)
				return 0;
		}

		else
		{
			if (pCur->_pLeft && pCur->_pRight)
			{
				LQueuePush(&q, pCur->_pRight);
				LQueuePush(&q, pCur->_pLeft);
				flag = 0;
			}
			else if (pCur->_pLeft)
			{
				LQueuePush(&q, pCur->_pLeft);
				flag = 1;
			}
			else if (pCur->_pRight)
				return 0;
			else
				flag = 1;
		}
		/*LQueuePop(&q);*/
	}
	return 1;
}

//二叉树的镜像
void MirrorBinTree(BTNode *pRoot)
{
	if (NULL == pRoot)
		return;
	Swap(&pRoot->_pLeft, &pRoot->_pRight);

	if (pRoot->_pLeft)
		MirrorBinTree(pRoot->_pLeft);
	if(pRoot->_pRight)
		MirrorBinTree(pRoot->_pRight);
	
}

//二叉树的镜像(非递归)
void MirrorBinTreeNor(BTNode *pRoot)
{
	LQueue q;
	BTNode *pCur = NULL;
	if (NULL == pRoot)
		return;
	LQueueInit(&q);
	LQueuePush(&q, pRoot);
	while (!LQueueEmpty(&q))
	{
		pCur = LQueueTop(&q);
		printf("%c", pCur->data);
		
		if (pCur->_pLeft)
			LQueuePush(&q, pCur->_pLeft);
		if (pCur->_pRight)
			LQueuePush(&q, pCur->_pRight);
	
		Swap(&pCur->_pLeft, &pCur->_pRight);
		LQueuePop(&q);
	}
}

//获取一个结点的左孩子结点
BTNode *LeftChild(BTNode *pNode)
{
	return (pNode != NULL) ? pNode->_pLeft : NULL;
}

//获取一个结点的右孩子结点
BTNode *RightChild(BTNode *pNode)
{
	return (pNode != NULL) ? pNode->_pRight : NULL;
}


void BinTree()
{
	BTNode *pRoot;
	BTNode *pCP;
	char str[] = "ABD###CE##F";
	int size = strlen(str);
	int index = 0;
	int count = 0;

	CrateBinTree(&pRoot, &str, size, &index, '#');
	
	printf("前序遍历:");
	PreOrderBinTree(pRoot);
	printf("\n");
	printf("前序遍历(非递归):");
	PreOrderBinTreeNor(pRoot);
	printf("\n");

	printf("中序遍历:");
	InOrderBinTree(pRoot);
	printf("\n");
	printf("中序遍历(非递归):");
	InOrderBinTreeNor(pRoot);
	printf("\n");

	printf("后序遍历:");
	PostOrderBinTree(pRoot);
	printf("\n");
	printf("后序遍历(非递归):");
	PostOrderBinTreeNor(pRoot);
	printf("\n");

	printf("层序遍历:");
	LevelOrderBintree(pRoot);
	printf("\n");


	printf("MirrorBinTree:");
	MirrorBinTree(pRoot);
	PreOrderBinTree(pRoot);
	printf("\n");
	printf("MirrorBinTreeNor:");
	MirrorBinTreeNor(pRoot);
	//PreOrderBinTree(pRoot);
	printf("\n");
	

	pCP = CopyBinTree(pRoot);
	printf("CopyBinTree:");
	PreOrderBinTree(pRoot);
	printf("\n");


	printf("二叉树结点数 = %d\n", GetBTNodeCount(pRoot));
	printf("二叉树叶子结点数 = %d\n", GetLeafNodeCount(pRoot));
	printf("第K层结点数 = %d\n", GetKLevelNodeCount(pRoot, 3));
	printf("二叉树高度 = %d\n", HeightBinTree(pRoot));

	printf("%c\n", GetBTNodeParent(pRoot, 'B'));

	if (IsCompleteBinTree(pRoot))
		printf("是一个完全二叉树\n");
	else 
		printf("不是一个完全二叉树\n");

	if (IsBTNodeBinTree(pRoot, 'B'))
		printf("该结点在二叉树中\n");
	else
		printf("该结点不在二叉树中\n");


	DestoryBinTree(&pRoot);
}



  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值