欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

树的介绍 and 递归处理一些习题~

程序员文章站 2022-04-25 16:49:22
...

下面树的遍历前中后序采用了递归处理,但递归容易导致栈溢出,这里给出了非递归的方法

               https://blog.csdn.net/Z_JUAN1/article/details/80952209

一、 树

·   有一个特殊的结点,称为根节点,根节点没有前区关系

·   除了根节点外,其余结点被分为M(M>0)个互不相交的集合T1、T2....Tm,其中每一个集合Ti(1<= i <m)又是一颗结构与树类似的子树,每颗子树的根节点有且只有一个前驱,可以是0个或多个后继

so~树是递归定义的



树的介绍 and 递归处理一些习题~

结点:  12个节点

结点的度:结点A的度为3,结点B的度为2,结点J的度为0

叶节点:J F K L H I

祖先结点:K的祖先结点A C G

子孙结点:B的祖先结点E F J

孩子结点:结点A的孩子结点为B C D

双亲结点:结点A是结点B C D的双亲结点

兄弟结点:B C D 互为兄弟结点,E F G H I 互为堂兄弟结点

树的度:3(所有节点的度的最大值)

树的深度:4

二、二叉树

树的介绍 and 递归处理一些习题~

·  每个结点最多有两颗子树,即二叉树不存在度大于2的结点

·  二叉树的子树有左右之分,其子树的次序不可更改

满二叉树  &&   完全二叉树

满二叉树:所有的分支都存在左子树和右子树,并且所有的叶子节点都在同一层

树的介绍 and 递归处理一些习题~

完全二叉树:一棵具有N个结点的二叉树的结构与满二叉树的前N个结点的结构相同

树的介绍 and 递归处理一些习题~

基本操作:

遍历结点:前序、中序、后序


树的介绍 and 递归处理一些习题~

前序:A B D C E F

中序:D B A E C F

后序:D B E F C A

接下来我们看一些面试题吧~  

1.   创建二叉树

树是一个递归的过程,所以这类题中我们大量的用到了递归

因为每一个子树又可以是一棵独立的树

//创建根
TreeNode *GreatRoot(DataType data)
{
	TreeNode *pRoot = (TreeNode *)malloc(sizeof(TreeNode));
	assert(pRoot);
	pRoot->pleft = NULL;
	pRoot->pright = NULL;
	pRoot->data = data;
	return pRoot;
}
//创建二叉树
TreeNode *GreatTree(DataType preorder[], int size,int *pIndex)
{
	if (*pIndex >= size)
	{
		return NULL;
	}
	if (preorder[*pIndex] == '#')
	{
		*pIndex += 1;
		return NULL;
	}
	TreeNode *pRoot = GreatRoot(preorder[*pIndex]);
	*pIndex += 1;
	pRoot->pleft = GreatTree(preorder, size, pIndex);
	pRoot->pright = GreatTree(preorder, size, pIndex);

	return pRoot;
}

2.前中后遍历二叉树

//前序
void PreOrder(TreeNode *pRoot)
{
	if (pRoot == NULL);
	return ;

	printf("%c ",pRoot->data);
	PreOrder(pRoot->pleft);
	PreOrder(pRoot->pright);
	
}
//中序
void InOrder(TreeNode *pRoot)
{
	if (pRoot == NULL);
	return ;

	PreOrder(pRoot->pleft);
	printf("%c ", pRoot->data);
	PreOrder(pRoot->pright);
}
//后序
void PostOrder(TreeNode *pRoot)
{
	if (pRoot == NULL);
	return ;

	PreOrder(pRoot->pleft);
	PreOrder(pRoot->pright);
	printf("%c ", pRoot->data);
}

3.结点个数

//结点个数
int GetSize(TreeNode *pRoot)
{
	if (pRoot = NULL){
		return NULL;
	}
	return GetSize(pRoot->pleft) + GetSize(pRoot->pright) + 1;
}

4.叶子结点个数

//叶子结点个数
int GetLeafSize(TreeNode *pRoot)
{
	if (pRoot == NULL){
		return 0;
	}
	if (pRoot->pleft == NULL &&  pRoot->pright == NULL){
		return 1;
	}
	return GetLeafSize(pRoot->pleft) + GetLeafSize(pRoot->pright);
}

5.第k层的结点个数

找到第K层进行左树+右树

//第k层的结点个数
int GetKLevelSize(TreeNode *pRoot, int k)
{
	assert(k>=1);
	if (pRoot == NULL)
	{
		return 0;
	}
	if (k = 1)
	{
		return 1;
	}
	return  GetKLevelSize(pRoot->pleft, k - 1) 
		   + GetKLevelSize(pRoot->pright, k - 1);
}
6.判断一个节点是否在二叉树中


// 找到,返回结点地址,否则返回 NULL
TreeNode * Find(TreeNode *pRoot, DataType data)
{
	if (pRoot == NULL)
	{
		return NULL;
	}
	if (pRoot->data == data)
	{
		return pRoot;
	}
	TreeNode *pFound = Find(pRoot->pleft,data);
	if (pFound != NULL)
	{
		return pFound;
	}
	return Find(pRoot->pright, data);
}

7.树的高度

#define MAX(x,y)    ((x)>(y)?(x):(y))
int GetHeight(TreeNode *pRoot)
{
	if (pRoot == NULL)
	{
		return 0;
	}
	int left = GetHeight(pRoot->pleft);
	int right = GetHeight(pRoot->pright);
	return MAX(left, right) + 1;

}

8.层序遍历

a.初始化一个队列

b.将根节点的指针入队列

c.当队列为非空时,循环以下步骤:

       >   取队头元素并访问

       >   若该结点的左子树非空,将该结点的左子树入队列  

       >   若该结点的右子树非空,将该结点的右子树入队列  

//层序遍历
void LevelOrder(TreeNode *pRoot)
{
	if (pRoot == NULL)
	{
		printf("\n");
		return;
	}
	Queue queue;
	TreeNode *pFront;
	QueueInit(&queue);
	QueuePush(&queue, pRoot);

	while (!QueueIsEmpty(&queue))
	{
		pFront = QueueFront(&queue);

		QueuePop(&queue);
		printf("%c ", pFront->data);

		if (pFront->pleft != NULL){
			QueuePush(&queue, pFront->pleft);
		}
		if (pFront->pright != NULL){
			QueuePush(&queue, pFront->pright);
		}
	}
	printf("\n");
}
9.判断是否为完全二叉树
//是否为完全二叉树
// 是返回 1,不是返回 0
int IsComplete(TreeNode *pRoot)
{	
	if (pRoot == NULL){
		return 1;
	}
	Queue  queue;
	TreeNode *pFront;
	QueueInit(&queue);
	QueuePush(&queue, pRoot);
	

	while (!QueueIsEmpty(&queue))
	{
		pFront = QueueFront(&queue);

		QueuePop(&queue);
		if (pFront == NULL)
		{
			break;
		}
		QueuePush(&queue, pFront->pleft);
		QueuePush(&queue, pFront->pright);
	}
	while (!QueueIsEmpty(&queue))
	{
		pFront = QueueFront(&queue);
		QueuePop(&queue);
		if (pFront != NULL)
		{
			return 0;
		}
	}
	return 1;
}

看一下测试函数吧~

void Tree()
{
	DataType *preorder = "ABD###CE##F";
	//DataType *preorder = "AB##C";
	int index = 0;
	TreeNode *pRoot = GreatTree(preorder, strlen(preorder), &index);

	PreOrder(pRoot); printf("\n"); //前序
	InOrder(pRoot);  printf("\n"); //中序
	PostOrder(pRoot); printf("\n");  //后序

	printf("结点数: %d\n", GetSize(pRoot));
	printf("叶子结点数: %d\n", GetLeafSize(pRoot));

	int k = 2;
	printf("第 %d 层结点数: %d\n", k, GetKLevelSize(pRoot, k));

	char C;
	Find(pRoot, C);

	printf("树的高度为: %d\n", GetHeight(pRoot));

	LevelOrder(pRoot);

	printf("%d\n", IsComplete(pRoot));
	
}

相关标签: