二叉树简单接口的实现

本文介绍了二叉树的基本性质,包括根节点的层数、节点数的区间、完全二叉树的特性等,并通过实例解析了前序、中序、后序遍历的逻辑。此外,还提供了计算二叉树节点个数、叶子节点个数及高度的接口实现,并讲解了如何查找二叉树中特定值的节点。
摘要由CSDN通过智能技术生成

目录

二叉树的性质

笔试题(选择)

前序、中序、后序遍历

二叉树前中后序遍历代码实现

相关节点计算接口实现


二叉树的性质

 1和2中规定了根节点的层数是1,注意有的书上或OJ题中会标明根节点的层数,也可能是0.

深度为h的二叉树的节点数区间是 [ 2^(h-1) , 2^h -1] 

3、这一点是前人根据经验总结出来的,能很方便解决一些选择题、计算题。

4、上一节讲的堆选数,时间复杂度之所以是O(logN),就是由此得来。

5、在孩子节点不超出数组下标的前提下:左孩子节点下标 = 双亲节点下标*2+1

右孩子节点下标 = 双亲节点下标*2+1。

利用性质可以解决一些相关笔试题。

笔试题(选择)

题一:

 利用性质3,很容易得出B。

题二:

 A、非完全二叉树肯定不能采用顺序结构,因为它的物理结构不一定是连续的,可能两个数据之间会空很多空间。

 C、队列,一般使用链表结构,因为顺序表结构不适合头删。

B,D都可以,单选选A,多选就选A,C。

题三:

 这题是第一题的延伸,也是利用性质3.

假设 一棵完全二叉树度为2的节点有N个,则叶子节点有N+1个,度为1的节点设有K个。

2N+K+1 = 2n,可以画一个完全二叉树实验一下,发现度为1的节点要么只有1个要么没有。

所以K = 1 或 K=0 ,带入上式,K = 1时,2N+2 = 2n, N = n-1,叶子节点个数为n

K = 0,N不是整数,排除,所以选A。

前序、中序、后序遍历

 

 用画图的方式我带大家理解一下这三种遍历方式。

前序:(先访问根--->左节点--->右节点)

 一棵树访问结束返回或遇NULL返回。

前序节点访问顺序:

1--->2--->3--->NULL--->NULL--->NULL--->4--->5--->NULL--->NULL--->6--->NULL--->NULL

中序:(先访问左节点--->根--->右节点)

同理:

前序节点访问顺序:

NULL--->3--->NULL--->2--->NULL--->1--->NULL--->5--->NULL--->4--->NULL--->6--->NULL

后序:(先访问左节点--->根--->右节点)

同理:

前序节点访问顺序:

NULL--->NULL--->3--->NULL--->2--->NULL--->NULL--->5--->NULL--->NULL--->6--->4--->1

二叉树前中后序遍历代码实现

为了方便,这里就写在一个项目里面,用最简单的方式创建。

创建简易二叉树:

#include<stdio.h>
#include<stdlib.h>
#include<assert.h>

typedef int BTDataType;

typedef struct BinaryTree
{
	BTDataType data;
	struct BinaryTree* left;
	struct BinaryTree* right;
}BTNode;

BTNode* CreateTree()
{
	BTNode* n1 = (BTNode*)malloc(sizeof(BTNode));
	assert(n1);
	BTNode* n2 = (BTNode*)malloc(sizeof(BTNode));
	assert(n2);
	BTNode* n3 = (BTNode*)malloc(sizeof(BTNode));
	assert(n3);
	BTNode* n4 = (BTNode*)malloc(sizeof(BTNode));
	assert(n4);
	BTNode* n5 = (BTNode*)malloc(sizeof(BTNode));
	assert(n5);
	BTNode* n6 = (BTNode*)malloc(sizeof(BTNode));
	assert(n6);

	n1->data = 1;
	n2->data = 2;
	n3->data = 3;
	n4->data = 4;
	n5->data = 5;
	n6->data = 6;

	n1->left = n2;
	n1->right = n4;
	n2->left = n3;
	n2->right = NULL;
	n3->left = NULL;
	n3->right = NULL;
	n4->left = n5;
	n4->right = n6;
	n5->left = NULL;
	n5->right = NULL;
	n6->left = NULL;
	n6->right = NULL;

	return n1;
}

前中后序遍历实现:

void PreOrder(BTNode* root)
{
	if (root == NULL)
	{
		printf("NULL ");
		return;
	}
	printf("%d ", root->data);
	PreOrder(root->left);
	PreOrder(root->right);
}

void InOrder(BTNode* root)
{
	if (root == NULL)
	{
		printf("NULL ");
		return;
	}
	InOrder(root->left);
	printf("%d ", root->data);
	InOrder(root->right);
}

void AfterOrder(BTNode* root)
{
	if (root == NULL)
	{
		printf("NULL ");
		return;
	}
	AfterOrder(root->left);
	AfterOrder(root->right);
	printf("%d ", root->data);
}

	int main()
	{
		BTNode* root = CreateTree();
		PreOrder(root);
		printf("\n");
		InOrder(root);
		printf("\n");
		AfterOrder(root);
		printf("\n");

		return 0;
	}

代码没什么好说的,看不出什么东西,我们画图来观察调用方式。

以前序为例:

 大体调用逻辑如上所示,中序和后序也一样,大家可以自行参考画图。

相关节点计算接口实现

一、计算二叉树的节点个数的接口实现

int TreeSize(BTNode* root)
{
	return root == NULL ? 0 : TreeSize(root->left) + TreeSize(root->right) + 1;
}

二、计算叶子节点个数的接口

int TreeLeafSize(BTNode* root)
{
	if (root == NULL)
		return 0;
	if (root->left == NULL && root->right == NULL)
		return 1;
	
	return TreeLeafSize(root->left) + TreeLeafSize(root->right);
}

三、计算树的高度的接口

int TreeHight(BTNode* root)
{
	if (root == NULL)
		return 0;
	int lefthight = TreeHight(root->left);
	int righthight = TreeHight(root->right);

	return lefthight > righthight ? lefthight+1:righthight + 1;
}

 

计算二叉树第k层节点个数

 

int BinaryTreeLevelKSize(BTNode* root, int k)
{
	if (root == NULL)
	{
		return 0;
	}
	if (k == 1)
	{
		return 1;
	}
	return BinaryTreeLevelKSize(root->left, k - 1) +
		   BinaryTreeLevelKSize(root->right, k - 1);

 

 二叉树查找值为x的节点

 先画图分析:这里采用的是前序遍历,先看根是不是要找的数,是就返回节点,不是就找左子树,重复上面步骤,再找右子树。

注意这里代码的关键是在于返回值,如果找到了就保存节点返回上一层,如果左右子树都没找到,注意,一定要记得返回一个NULL,否则上一层就接收不到返回值了。这个NULL与根节点为NULL所返回的NULL不一样,因为它们返回的地方不一样。

代码如下:

BTNode* BinaryTreeFind(BTNode* root, BTDataType x)
{
	if (root == NULL)
	{
		return NULL;
	}
	if (root->data == x)
		return root;

	BTNode* leftret = BinaryTreeFind(root->left, x);
	if (leftret)
		return leftret;

	BTNode* rightret = BinaryTreeFind(root->right, x);
	if (rightret)
		return rightret;
		
	return NULL;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
/* * 二叉树节点ADT接口 */ package dsa; public interface BinTreePosition extends Position { //判断是否有父亲(为使代码描述简洁) public boolean hasParent(); //返回当前节点的父节点 public BinTreePosition getParent(); //设置当前节点的父节点 public void setParent(BinTreePosition p); //判断是否为叶子 public boolean isLeaf(); //判断是否为左孩子(为使代码描述简洁) public boolean isLChild(); //判断是否有左孩子(为使代码描述简洁) public boolean hasLChild(); //返回当前节点的左孩子 public BinTreePosition getLChild(); //设置当前节点的左孩子(注意:this.lChild和c.parent都不一定为空) public void setLChild(BinTreePosition c); //判断是否为右孩子(为使代码描述简洁) public boolean isRChild(); //判断是否有右孩子(为使代码描述简洁) public boolean hasRChild(); //返回当前节点的右孩子 public BinTreePosition getRChild(); //设置当前节点的右孩子(注意:this.rChild和c.parent都不一定为空) public void setRChild(BinTreePosition c); //返回当前节点后代元素的数目 public int getSize(); //在孩子发生变化后,更新当前节点及其祖先的规模 public void updateSize(); //返回当前节点的高度 public int getHeight(); //在孩子发生变化后,更新当前节点及其祖先的高度 public void updateHeight(); //返回当前节点的深度 public int getDepth(); //在父亲发生变化后,更新当前节点及其后代的深度 public void updateDepth(); //按照中序遍历的次序,找到当前节点的直接前驱 public BinTreePosition getPrev(); //按照中序遍历的次序,找到当前节点的直接后继 public BinTreePosition getSucc(); //断绝当前节点与其父亲的父子关系 //返回当前节点 public BinTreePosition secede(); //将节点c作为当前节点的左孩子 public BinTreePosition attachL(BinTreePosition c); //将节点c作为当前节点的右孩子 public BinTreePosition attachR(BinTreePosition c); //前序遍历 public Iterator elementsPreorder(); //中序遍历 public Iterator elementsInorder(); //后序遍历 public Iterator elementsPostorder(); //层次遍历 public Iterator elementsLevelorder(); }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值