各种二叉树的判断

216 阅读5分钟

二叉树的宽度优先遍历

宽度优先遍历根据维基百科的解释如下:

广度优先搜索算法(英语:Breadth-First Search,缩写为BFS),又译作宽度优先搜索,或横向优先搜索,是一种图形搜索算法。简单的说,BFS是从根节点开始,沿着树的宽度遍历树的节点。如果所有节点均被访问,则算法中止。广度优先搜索的实现一般采用open-closed表。

对于一棵二叉树进行宽度优先遍历,可以采用队列的方式进行,即先进先出。具体思路如下:

先将根节点入队列,弹出根节点并且将其孩子入队列(左孩子先入队列)。

无标题-2021-10-13-0831.png

过程示意图如下:

无标题-2021-10-13-0831.png

代码实现如下:

//宽度遍历二叉树
class Node {
	constructor({leftChild, rightChild, value}) {
		this.leftChild = leftChild || null;
		this.rightChild = rightChild || null;
		this.value = value;
	}
}


let node7 = new Node({leftChild: null, rightChild: null, value: 7});
let node6 = new Node({leftChild: null, rightChild: null, value: 6});
let node5 = new Node({leftChild: null, rightChild: null, value: 5});
let node4 = new Node({leftChild: null, rightChild: null, value: 4});
let node3 = new Node({leftChild: node6, rightChild: node7, value: 3});
let node2 = new Node({leftChild: node4, rightChild: node5, value: 2});
let node1 = new Node({leftChild: node2, rightChild: node3, value: 1});

function bfs(tree) {
	if (tree === null) return [];
	let Queque = [];
	Queque.push(tree);
	let printArray = [];

	while(Queque.length > 0) {
		let node = Queque.shift();
		printArray.push(node.value);
		node.leftChild&&Queque.push(node.leftChild);
		node.rightChild&&Queque.push(node.rightChild);
	}
	return printArray;
}


console.log(bfs(node1)); //[ 1, 2, 3, 4, 5, 6, 7 ]

求一棵二叉树的宽度

在广度优先遍历的前提下,建立一种规则。该规则明确了遍历的节点是该层的第几个 count、该层的最后一个节点是哪个 currentEnd、下一层最后一个节点是哪个nextEnd、遍历到一层时,从节点到该层上一层的最大宽度 maxCount

当遍历到的节点等于 currentEnd 时,表示该层遍历已经结束,重置变量,比较 countmaxCount,开始下一层的遍历。

流程图如下:

无标题-2021-10-13-0831.png

过程示意图如下:

无标题-2021-10-13-0831.png

代码实现

//二叉树的最大宽度
class Node {
	constructor({leftChild, rightChild, value}) {
		this.leftChild = leftChild || null;
		this.rightChild = rightChild || null;
		this.value = value;
	}
}

let node8 = new Node({leftChild: null, rightChild: null, value: 8});
let node7 = new Node({leftChild: null, rightChild: null, value: 7});
let node6 = new Node({leftChild: null, rightChild: null, value: 6});
let node5 = new Node({leftChild: null, rightChild: null, value: 5});
let node4 = new Node({leftChild: node5, rightChild: node6, value: 4});
let node3 = new Node({leftChild: node8, rightChild: node7, value: 3});
let node2 = new Node({leftChild: node4, rightChild: null, value: 2});
let node1 = new Node({leftChild: node2, rightChild: node3, value: 1});



function maxBreadth (tree) {
	if (tree === null ) {
		return 0;
	}

	let queue = [tree];
	let currentEnd = tree;
	let nextEnd = tree;
	let count = 0;
	let maxCount = 0;

	while (queue.length > 0) {
		count++;
		let el = queue.shift();

		if (el.leftChild) {
			queue.push(el.leftChild);
			nextEnd = el.leftChild;
		}

		if (el.rightChild) {
			queue.push(el.rightChild);
			nextEnd = el.rightChild;
		}

		if (el === currentEnd) {
			maxCount = maxCount >= count ? maxCount : count;
			currentEnd = nextEnd;
			nextEnd = null;
			count = 0;
		}

	}
	return maxCount;
}

console.log(maxBreadth (node1))//3

判断一棵二叉树是否是搜索二叉树

搜索二叉树根据维基百科的解释如下:

二叉查找树(英语:Binary Search Tree),也称为二叉查找树有序二叉树(ordered binary tree)或排序二叉树(sorted binary tree),是指一棵空树或者具有下列性质的二叉树

  1. 若任意节点的左子树不空,则左子树上所有节点的值均小于它的根节点的值;
  2. 若任意节点的右子树不空,则右子树上所有节点的值均大于它的根节点的值;
  3. 任意节点的左、右子树也分别为二叉查找树;

也就是说对于一棵二叉树来说,其中序遍历的结果是升序。所以,可以打印其中序遍历结果,查看其是否时升序。

判断一棵二叉树是完全二叉树

完全二叉树根据维基百科的解释如下:

在一颗二叉树中,若除最后一层外的其余层都是满的,并且最后一层要么是满的,要么在右边缺少连续若干节点,则此二叉树为完全二叉树(Complete Binary Tree)。

也就是说,用数组表示该二叉树的话,该数组必须是连续的,不允许中间有值不存在。

无标题-2021-10-13-0831.png

判断方式:当满足条件 1 ,不满足条件 2,则不是完全二叉树。

  1. 节点 node 左右孩子不同时存在;即节点 node 可能只有左孩子或者右孩子或者没有孩子。
  2. 节点 node 后的节点都必须是叶节点;也就是说节点 node 后面的节点都不能有孩子。

判断一棵二叉树是满二叉树

一棵深度为k,且有 2k12^k - 1 个节点的二叉树,称为完美二叉树(Perfect Binary Tree)。这种树的特点是每一层上的节点数都是最大节点数。

也就是说是否是满二叉树,需要获取二叉树的高度 k 以及节点个数 n。只要满足 n=2k1n=2^k - 1,则是满二叉树。

//判断是否是满二叉树
class Node {
	constructor({leftChild, rightChild, value}) {
		this.leftChild = leftChild || null;
		this.rightChild = rightChild || null;
		this.value = value;
	}
}


let node7 = new Node({leftChild: null, rightChild: null, value: 7});
let node6 = new Node({leftChild: null, rightChild: null, value: 6});
let node5 = new Node({leftChild: null, rightChild: null, value: 5});
let node4 = new Node({leftChild: null, rightChild: null, value: 4});
let node3 = new Node({leftChild: node6, rightChild: node7, value: 3});
let node2 = new Node({leftChild: node4, rightChild: node5, value: 2});
let node1 = new Node({leftChild: node2, rightChild: node3, value: 1});



function getData(node) {
	if (node === null) return {
		height: 0,
		number: 0,
		isBalance: true
	};

	let {height: leftHeight, isBalance: isLeftBalance, number: leftNumber} =  getData(node.leftChild);
	let {height: rightHeight, isBalance: isRigthBalance, number: rightNumber} =  getData(node.rightChild);

	return {
		height: Math.max(leftHeight + 1, rightHeight + 1),
		isBalance: isLeftBalance&&isRigthBalance&&(Math.abs(leftHeight - rightHeight) <= 1),
		number: leftNumber + rightNumber + 1
	}
}


const data = getData(node1);
console.log(isFull(data))

function isFull(data) {
	return Math.pow(2, data.height) - 1 === data.number;
}

判断一棵二叉树是否是平衡二叉树

平衡二叉搜索树(英语:Balanced Binary Search Tree)是一种结构平衡的二叉搜索树,它是一种每个节点的左右两子树高度差都不超过一的二叉树。它能在 O(logn)O(log n) 内完成插入、查找和删除操作,最早被发明的平衡二叉搜索树为AVL树。

判断是否是平衡二叉树的关键是对于每一个节点,它的左右两树的高度差不超过 1。可以使用递归的方式求解。

代码实现

//判断是否是平衡二叉树
class Node {
	constructor({leftChild, rightChild, value}) {
		this.leftChild = leftChild || null;
		this.rightChild = rightChild || null;
		this.value = value;
	}
}


let node7 = new Node({leftChild: null, rightChild: null, value: 7});
let node6 = new Node({leftChild: null, rightChild: null, value: 6});
let node5 = new Node({leftChild: null, rightChild: null, value: 5});
let node4 = new Node({leftChild: null, rightChild: null, value: 4});
let node3 = new Node({leftChild: node6, rightChild: node7, value: 3});
let node2 = new Node({leftChild: node4, rightChild: node5, value: 2});
let node1 = new Node({leftChild: node2, rightChild: node3, value: 1});



function getData(node) {
	if (node === null) return {
		height: 0,
		number: 0,
		isBalance: true
	};

	let {height: leftHeight, isBalance: isLeftBalance, number: leftNumber} =  getData(node.leftChild);
	let {height: rightHeight, isBalance: isRigthBalance, number: rightNumber} =  getData(node.rightChild);

	return {
		height: Math.max(leftHeight + 1, rightHeight + 1),
		isBalance: isLeftBalance&&isRigthBalance&&(Math.abs(leftHeight - rightHeight) <= 1),
		number: leftNumber + rightNumber + 1
	}
}


const data = getData(node1);
console.log(data);
console.log(isBalanceTree(data));