数据结构与算法(七)

news/2024/7/6 1:52:08

二叉树

如果说树中的每个结点最多只能有两个子结点,这样的树我们就称为二叉树,二叉树可以为空。

特点:

  • 每个结点最多有两棵子树,所以二叉树中不存在度大于二的结点棵树中,最大的结点的度称为树的度,结点的度:结点所拥有的了树的个数
  • 左子树和右子树是有顺序的,次序不能任意的颠倒
  • 即使树某结点只有一棵子树,也要去区分它是左子树还是右子树

性质:

  • 在二叉树中,第i层上最多有2^i-1次结点 (i>=1)  第一层: 2 ^1-1
  • 在二叉树中,如果深度为k,那么最多有2^k - 1个结点

形态:

  • 空树
  • 只有一个根结点
  • 只有一个左子树
  • 只有一个右子树
  • 左子树、右子树都有

满二叉树:在一棵二叉树中,所有的分支结点都存在左子树和右子树,并目叶了都在同一层上。

全二叉树: 除最后一层外,每一层上的结点数均达到最人值。最后一层只缺少有边的若干结点

满二叉树一定是完全二叉树,反过来不一定成立

二叉树的存储:数组、链表,最合适用链表

二叉搜索树

二叉搜索树,BST,binary search tree。二叉查找树、二叉排序树。

二叉搜索树其实就是普通的二叉树上加了一些限制 

限制与要求

二叉树对于结点是没有任何的限制,但是在二叉搜索树中在插入子结点的有一些特殊的要求:

  • 非空左子树的所有的键值都小于其根结点的键值
  • 非空右子树的所有键值都大于其根结点的键值
  • 左右子树本身也都是二叉搜索树

二叉搜索树的特点:相对较小的值总是保存在左子结点上,相对较大的值总是保存在右子结点上 

class Node {
	constructor(value) {
		this.value = value;
		this.left = null;
		this.right = null;
	}
}
// 相对小的值:左边 相对大的值:右边
class BinarySearchTree {
	constructor() {
		// 根节点
		this.root = null;
	}
	// 插入值比较
	insertNode(node, newNode) {
		if (newNode.value > node.value) {
			// 右边
			if (node.right === null) {
				node.right = newNode
			} else {
				this.insertNode(node.right, newNode);
			}
		} else if (newNode.value < node.value) {
			// 左边
			if (node.left === null) {
				node.left = newNode
			} else {
				this.insertNode(node.left, newNode);
			}
		}
	}
	// 插入,判断空树
	insert(value){
		let newNode = new Node(value);
		if(this.root === null){
			this.root = newNode;
		}else{
			this.insert(this.root,newNode)
		}
	}
}
const bst = new BinarySearchTree();

遍历

遍历:不重复的访问二叉树中所有的结点,

方式:先序遍历,中序遍历,后序遍历

1.先序遍历

  • 访问根结点
  • 先序遍历其左子树
  • 先序遍历其右子树

2.中序遍历

  • 先递归遍历其左子树,从最后一个左子树开始存入数组,
  • 然后回溯遍历双亲结点,
  • 再是右子树。递归循环

3.后序遍历

  • 后序遍历其左子树
  • 后序遍历其右子树
  • 访问根结点
class Node {
	constructor(value) {
		this.value = value;
		this.left = null;
		this.right = null;
	}
}
// 相对小的值:左边 相对大的值:右边
class BinarySearchTree {
	constructor() {
		// 根节点
		this.root = null;
	}
	// 先序遍历
	preOrederTraversal(cb){
		this.preOrderNode(this.root,cb);
	}
	preOrderNode(node,cb){
		// 空节点直接返回
		if(node === null) return
		// 打印
		cb(node.value);
		//遍历所有左子树
		this.preOrderNode(node.left,cb);
		// 遍历所有右子树
		this.preOrderNode(node.right,cb);
	}
	// 中序遍历
	inOrederTraversal(cb){
		this.inOrderNode(this.root,cb);
	}
	inOrderNode(node,cb){
		// 空节点直接返回
		if(node === null) return
		//遍历所有左子树
		this.inOrderNode(node.left,cb);
		// 打印
		cb(node.value);
		// 遍历所有右子树
		this.inOrderNode(node.right,cb);
	}
	// 后序遍历
	afterOrederTraversal(cb){
		this.afterOrderNode(this.root,cb);
	}
	afterOrderNode(node,cb){
		// 空节点直接返回
		if(node === null) return
		//遍历所有左子树
		this.afterOrderNode(node.left,cb);
		// 遍历所有右子树
		this.afterOrderNode(node.right,cb);
		// 打印
		cb(node.value);
	}
}
const bst = new BinarySearchTree();
const rst =  []
const cb = (val)=>{
	rst.push(val);
}
bst.preOrederTraversal(cb);

4.最大值与最小值

max(){
		let node = this.root;
		while(node.right !== null){
			node = node.right;
		}
		return node.value
	}
	min(){
		let node = this.root;
		while(node.left !== null){
			node = node.left;
		}
		return node.value
	}

5、寻找特定的值

search(val) {
		let node = this.root;
		while (node !== null) {
			if (node.value > val) {
				node = node.left;
			} else if (node.value < val) {
				node = node.right;
			}else{
				return true;
			}
		}
	}

6.删除

三种情况

  • 没有子树

  • 仅有一棵子树

  • 有两棵子树(保证中序遍历顺序不变)


二叉搜索树的优点:作为数据存储的结构有重要的意义,可以快速的找到给定的关键字的数据项,并且可以快速的插入和删除数据

二叉搜索树的缺点:具有局限性。同样的数据,可以对应不同的二叉搜索树

比较好的二叉搜索树的结构:左右分布均匀的,但是我们插入连续的数据的时候,会导致数据分布不均匀 我们就把这个分布不均匀的树称之为非平衡树
平衡树: AVL,红黑树 

当向二叉搜索树中插入新结点后,如果能保证每个结点的左右子树高度之差的绝对值不超过1(需要对树中的结点进行调整),即可以降低树的高度,从而减少平均搜索长度。

 


http://lihuaxi.xjx100.cn/news/1170275.html

相关文章

【深入浅出Maven开发实战】「入门教程系列」带你零基础学习和开发使用Maven开发工具实战指南(实战技术总结)

Maven介绍 由于Java的生态非常丰富&#xff0c;无论你想实现什么功能&#xff0c;都能找到对应的工具类&#xff0c;这些工具类都是以jar包的形式出现的&#xff0c;例如Spring,SpringMVC、MyBatis、数据库驱动&#xff0c;等等&#xff0c;都是以jar包的形式出现的&#xff0…

工作记录:在线 word - 列表

需求&#xff1a;上传 word 文档&#xff0c;在页面的富文本编辑器中展示、编辑后&#xff0c;再导出成 word 格式。 我负责开发列表功能 为什么不用 ul 一开始想用<ul> <li> 去实现列表&#xff0c;但随即发现一些问题&#xff1a; 问题一&#xff1a;word 中的…

Redis 的数据类型和命令帮助

文章结构 Redis 数据类型1. Redis全局命令&#xff08;跟key有关系&#xff0c;而跟value无关&#xff09;2. StringsGetting and setting StringsManaging counters 3. Lists(L)Basic commandsBlocking commands 4. Sets(S)Basic commands 5. Hashes(H)Basic commands 6. Sort…

flask实现简易图书管理系统

项目结构 技术选型 flask 做后端, 提供数据和渲染html 暂时没有提供mysql, 后续会更新操作mysql和样式美化的版本 起一个flask服务 flask是python的一个web框架, 下面演示如何提供http接口, 并返回json数据 main.py # flask创建http接口 from flask import Flask, request, jso…

SelFlow: Self-Supervised Learning of Optical Flow

本文提出了一种用于光流的自监督学习方法。该方法从非遮挡像素中提取可靠的流估计&#xff0c;并使用这些预测作为真值来学习幻觉遮挡的光流。 本文设计了一个简单的 CNN&#xff0c;以利用 来自多个帧的时间信息 来更好地进行流估计。本方法可以在 MPI Sintel、KITTI 2012 和 …

jenkins 使用教程

1 拉取镜像 docker pull jenkins/jenkins 2 mkdir-p /usr/local/docker/jenkins_docker cd usr/local/docker/jenkins_docker mkdir data 编写 vim docker-compose.yml version: "1.0.0" services: jenkins: image: jenkins/jenkins containe…

JDK动态代理和CGLIB动态代理

JDK动态代理和CGLIB动态代理 JDK动态代理和CGLIB动态代理 JDK动态代理和CGLIB动态代理 ① JDK动态代理只提供接口的代理&#xff0c;不支持类的代理&#xff0c;要求被代理类实现接口。JDK动态代理的核心是InvocationHandler接口和Proxy类&#xff0c;在获取代理对象时&#x…

Three.js--》实现3d圣诞贺卡展示模型

目录 项目搭建 初始化three.js基础代码 加载环境模型 设置环境纹理 添加水面并设置阴影效果 实现幽灵小球的运动 实现相机切换和文字切屏 实现漫天星星和爱心样式 今天简单实现一个three.js的小Demo&#xff0c;加强自己对three知识的掌握与学习&#xff0c;只有在项目…