判断某个二叉树是不是二分搜索树

题目

给出一个二叉树,判断它是不是一个二分搜索树(BST).二分搜索树的定义如下:

        一、节点的左子树所包含的值小于此节点的值。

        二、节点的右子树所包含的值大于此节点的值。

        三、节点的左右子树均为二分搜索树。

lnput: [5,1,4,null,null,3,6]

Output: false

Input: [2,1,3]

output: true

解析

按照数组的索引构建一颗二叉树如下所示:

注意:为了方便查找索引规律,数组索引是从1开始的。

可以看出此一维数组中的索引值有以下关系:

        1、左子树的索引值是父节点的索引值乘2。

        2、右子树的索引值是父节点的索引值乘2加1。

        3、按照二分搜索树的规律,二分搜索树的节点应该是对称的,不存在只有左子树或者只有右子树的节点

        因此二分搜索数的节点必须是奇数。

实现判断步骤

1.求数组中的数据在二叉树中分几层

思路:

   1、已知数据总个数,求层数

    数组按1生2 2生4 4生8 生成二叉树

    数据总个数 = 2^0 + 2^1+2^2+...2^n = 2^(n+1) - 1

    层数 = 向下取整( log2(数据个数) )

        2、每一层每个节点的左右子树和根节点进行对比        

思路:
搜索结果  二分搜索树判断函数(数组,长度)
{
	如果长度为奇数
	{
		返回 -1
	}

	求二叉树总层数

	循环开始每一层的比较 -- 循环变量为i
	{
		求第i层的数据总个数
		求第i层第一个数据的数组索引

		循环获取这一层上的左右子树对应的数组数据
		{
			如果 当前索引 > 数组长度 或者 左子树数组数据为NULL 或者 右子树数组数据为NULL
			{
				结束或者本组数据不用判断继续下一组
			}
			否则
			{
				// 对比对应下标数据,
				如果 左子树数组数据 > 父节点数据 或者 右子树数组数据 < 父节点数据
				{
					不满足二分搜索树条件,返回0
				}
			}
		}
	}

	// 如果对比了所有节点都满足二分搜索树条件,没有结束函数
	二分搜索树条件,返回1
}

3、代码实现

#include<stdio.h>
#include<math.h> 

// 先将二叉树按照层次放入数组中 
int isBinaryTree(int arr[],int size)
{
	// 如果数据是偶数则 有节点缺少左子树或者右子树 
	if(size % 2 == 0) return -1;  
	// 先求二叉树的层次,已知数组的长度求层数
	// 数组按1生2 2生4 4生8 生成二叉树, 
	// 	
	int fNum = (int)floor(log2(size));
	
	int i;   // 层次循环变量 
	int j;   // 每一层的数据循环变量 
	int num; // 每一层的数据总个数 
	int firstNum; // 每一层第一个数据的索引 
	int a;   // 存放每一次对比的左子树索引 
	
	// 从第1层开始对比到最后一层,顶层只有一个不用比较 
	for(i=1;i<fNum;i++)
	{		
		// 第i层的数据个数为:2^i 
		num = (int)pow(2,i);
		
		// 第i层的第一个数的索引为2^i
		firstNum = (int)pow(2,i);		
		
		// 第i层的第j个数据,j和j+1对应的数据是一个节点的左右子树 
		for(j=0;j<num;j+=2)
		{
			// 序号  对应数组的下标应该是a-1和a
			a = firstNum + j;   
			
			if(a > size || arr[a-1] == NULL || arr[a] == NULL)
			{
				// 如果该层的节点没有了或者数组中的数据已经是NULL了就继续后面的对比 
				continue;
			} 
			else
			{
				// 如果  数组中对应左子树上的数据 > 根节点的数据 
				// 或者  数组中对应右子树上的数据 < 根节点的数据 
				// 则 该二叉树不是二分搜索树--直接返回0 
				if(arr[a-1] > arr[a/2-1]  ||  arr[a] < arr[a/2-1])
				{
					return 0;
				}
			}
		}
		 
	} 
	
	// 如果对比了所有节点都满足  数组中对应左子树上的数据 < 根节点的数据 
	// 同时  数组中对应右子树上的数据 < 根节点的数据
	// 则 该二叉树不是二分搜索树--直接返回1 
	return 1; 
} 

int main()
{
	// int a[] = {2,1,3};
	// int a[] = {5,1,8,NULL,NULL,6,10};
	int a[] = {5,1,4,NULL,NULL,3,6};
	int len = sizeof(a) / sizeof(int);

	int res = isBinaryTree(a,len);
	
	if(res == 1)
	{
		printf("yes");
	}
	else if(res == 0) 
	{
		printf("no"); 
	}
	else if(res == -1)
	{
		printf("数组数据必须保持奇数个"); 
	}
	return 0;
} 

 

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-04-10 10:12:02       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-04-10 10:12:02       100 阅读
  3. 在Django里面运行非项目文件

    2024-04-10 10:12:02       82 阅读
  4. Python语言-面向对象

    2024-04-10 10:12:02       91 阅读

热门阅读

  1. C语言每日一题(66)三数之和

    2024-04-10 10:12:02       33 阅读
  2. Linux服务篇之FTP及SFTP

    2024-04-10 10:12:02       34 阅读
  3. C++_List的学习

    2024-04-10 10:12:02       29 阅读
  4. 【leetcode】大数相加

    2024-04-10 10:12:02       36 阅读
  5. 服务器硬件基础知识

    2024-04-10 10:12:02       30 阅读
  6. js的模块是怎么加载的

    2024-04-10 10:12:02       38 阅读
  7. 动态表单的实现和校验

    2024-04-10 10:12:02       30 阅读
  8. 如何控制台灯的亮度

    2024-04-10 10:12:02       40 阅读
  9. 3GPP-LTE Band31标准定义频点和信道(V17.3.0 (2022-09)

    2024-04-10 10:12:02       42 阅读
  10. 存储设备与网络监控运维实践

    2024-04-10 10:12:02       39 阅读
  11. C语言关键字

    2024-04-10 10:12:02       31 阅读
  12. C语言形参和实参有什么区别?

    2024-04-10 10:12:02       29 阅读
  13. C++设计模式之单例模式

    2024-04-10 10:12:02       30 阅读