数据结构 —— 二叉树

news2024/10/5 16:30:23

1.树的概念及结构

1.1树的概念

树是一种非线性的数据结构,它有着多分支,层次性的特点。

由于其形态类似于自然界中倒过来的数,所以我们将这种数据结构称为“树形结构”

注意: 树形结构中,子树之间不能有交集,否它就不是树形结构

 

1.2 树的相关概念

  • 结点的度:一个结点含有的子树的个数称为该结点的度; 如上图:A的为6
  • 叶结点或终端结点:度为0的结点称为叶结点; 如上图:BCHI...等结点为叶结点
  • 非终端结点或分支结点:度不为0的结点; 如上图:DEFG...等结点为分支结点
  • 双亲结点或父结点:若一个结点含有子结点,则这个结点称为其子结点的父结点; 如上图:AB的父结点
  • 孩子结点或子结点:一个结点含有的子树的根结点称为该结点的子结点; 如上图:BA的孩子结点
  • 兄弟结点:具有相同父结点的结点互称为兄弟结点; 如上图:BC是兄弟结点
  • 树的度:一棵树中,最大的结点的度称为树的度; 如上图:树的度为6
  • 结点的层次:从根开始定义起,根为第1层,根的子结点为第2层,以此类推;
  • 树的高度或深度:树中结点的最大层次; 如上图:树的高度为4
  • 堂兄弟结点:双亲在同一层的结点互为堂兄弟;如上图:HI互为兄弟结点
  • 结点的祖先:从根到该结点所经分支上的所有结点;如上图:A是所有结点的祖先
  • 子孙:以某结点为根的子树中任一结点都称为该结点的子孙。如上图:所有结点都是A的子孙
  • 森林:由mm>0)棵互不相交的树的集合称为森林;

1.3树的表示 

树的表示我们使用:孩子兄弟表示法

设计一个数的节点,其中包含数据域(存储数据)、指针域(左孩子指针,右兄弟指针)

typedef int DataType;
struct Node
{
 struct Node* firstChild1; // 第一个孩子结点
 struct Node* pNextBrother; // 指向其下一个兄弟结点
 DataType data; // 结点中的数据域
};

这种数的设计方法,我们可以通过左孩子指针找到 A节点 的第一个孩子(B),在通过孩子的右兄弟指针把 A节点 的所有孩子都找到

1.4 树在实际中的运用

树在实际中的运用:电脑中的数目录

2.二叉树的概念及结构 

2.1二叉树的概念 

在实际运用中,二叉树要比树更加实用

二叉树其实就是特殊的一种树,它的每个节点最多有两个子节点,通常被称为左子节点和右子节点

  •  二叉树不存在度大于2的结点
  •  二叉树的子树有左右之分,次序不能颠倒,因此二叉树是有序树

2.2现实中的二叉树

 2.3特殊的二叉树

 

  •  满二叉树:二叉树的每一层都是满的(特殊的完全二叉树)
  • 完全二叉树:二叉树的最后一层不一定是满的,但是它是连续的

向下面这个二叉树,最后一层并不连续,因此它并非是完全二叉树:

2.4二叉树的性质

2.5二叉树的存储结构

二叉树一般可以使用两种结构存储,一种顺序结构,一种链式结构
1. 顺序存储
顺序结构存储就是使用 数组来存储 ,一般使用数组 只适合表示完全二叉树 ,因为不是完全二叉树会有空间的浪费。而现实中使用中只有堆才会使用数组来存储
二叉树顺序存储在物理上是一个数组,在逻辑上是一颗二叉树
2. 链式存储
二叉树的链式存储结构是指,用链表来表示一棵二叉树,即用链来指示元素的逻辑关系。
通常的方法是:链表中每个结点由三个域组成,数据域和左右指针域,左右指针分别用来给出该结点左孩子和右孩子所在的链结点的存储地址 。链式结构又分为二叉链和三叉链,目前我们使用二叉链的新式学习
二叉链式实现的二叉树:

3.二叉树的顺序存储结构 

顺序存储结构只推荐完全叉树来进行存储,一般的二叉树容使用顺序结构进行存储,容易造成空间的大量浪费,现实中我们通常把堆(一种二叉树)使用顺序结构的数组来存储,需要注意的是这里的堆和操作系统虚拟进程地址空间中的堆是两回事,一个是数据结构,一个是操作系统中管理内存的一块区域分段

堆在这篇文章中有所介绍 ———— 数据结构 - 堆

4.二叉树的链式结构的实现

在进行二叉树链式结构的实现时,我们首先回顾二叉树是:

1. 空树
2. 非空:根结点,根结点的左子树、根结点的右子树组成的

每一颗二叉树都可以看做是递归形成的因为:

每一颗二叉树都可以拆分成:根节点 左子树 右子树

它的左子树可以被拆分成 :根节点 左子树 右子树

它的右子树右也可以被拆分成 :根节点 左子树 右子树

依次类推直到变成一颗空树,不能被拆分,所以才会说二叉树可以看做是递归形成,二叉树可以被拆分成一个一个的小问题(即一个一个的子树 根节点),直到变成空树不能再被拆分,因此后序基本操作中基本都是按照递归概念实现的

4.1二叉树的前置声明

typedef int BTDataType;

typedef struct BinaryTreeNode    //二叉树的单个节点
{
 BTDataType _data;
 struct BinaryTreeNode* _left;   //左孩子
 struct BinaryTreeNode* _right;  //右孩子
}BTNode;

4.2二叉树的遍历

4.2.1前序、中序以及后序遍历

二叉树的遍历是指按照某种规则访问树中的所有节点,并且每个节点只被访问一次。访问结点所做的操作依赖于具体的应用问题。遍历是二叉树上最重要的运算之一,也是二叉树上进行其它运算的基础。

按照规则,二叉树的遍历有:前序/中序/后序的递归结构遍历 

1. 前序遍历 (Preorder Traversal )—— 访问顺序:根节点 —>左子树 —>右子树
2. 中序遍历(Inorder Traversal)——访问顺序:左子树 —>根节点 —>右子树
3. 后序遍历(Postorder Traversal)——访问顺序:左子树 —>右子树—>根节
前序遍历递归图解

 

 

前序遍历结果: 1 2 3 4 5 6
中序遍历结果: 3 2 1 5 4 6
后序遍历结果: 3 2 5 6 4 1
前中后序遍历的方式大抵相同,这里不做过多赘述
代码实现:
// 二叉树前序遍历 
void BinaryTreePrevOrder(BTNode* root) {

	if (root == NULL)  //当访问的数为NULL树时停止访问
	{
		printf("N ");
		return;
	}

	printf("%d ",root->_data);//先便利根节点,整形的数据类型

	BinaryTreePrevOrder(root->_left);//左子树
	BinaryTreePrevOrder(root->_right);//右子树

}
// 二叉树中序遍历
void BinaryTreeInOrder(BTNode* root) {

	if (root == NULL)
	{
		printf("N ");
		return;
	}

	BinaryTreeInOrder(root->_left);//左子树
	printf("%d ", root->_data);//根节点
	BinaryTreeInOrder(root->_right);//右子树
}

// 二叉树后序遍历
void BinaryTreePostOrder(BTNode* root) {
	if (root == NULL)
	{
		printf("N ");
		return;
	}

	BinaryTreePostOrder(root->_left);//左子树
	BinaryTreePostOrder(root->_right);//右子树
	printf("%d ", root->_data);//根节点
}

 

4.2.2层序遍历 

层序遍历 :除了先序遍历、中序遍历、后序遍历外,还可以对二叉树进行层序遍历。设二叉树的根结点所在层数为1 ,层序遍历就是从所在二叉树的根结点出发,首先访问第一层的树根结点,然后从左到右访问第 2 层上的结点,接着是第三层的结点,以此类推,自上而下,自左至右逐层访问树的结点的过程就是层序遍历。

 

 代码实现:

二叉树的层序遍历并不是通过递归来完成的,而是通过 —— 数据结构中的队列来实现的

遍历的原理是从根节点开始,首先访问根节点,然后将根节点的左右子节点依次入队。接下来,从队列中取出一个节点(队首节点),访问该节点,再将其未被访问的左右子节点入队。重复此过程,直到队列为空,即所有节点都被访问过。

动图理解:

 

// 层序遍历
void BinaryTreeLevelOrder(BTNode* root) {
	//创建队列
	Queue qu;
	QueueInit(&qu);
	QueuePush(&qu, root);

	//开始拖家带口,当队列为NULL时,说明已经遍历完成,循环结束
	while (!QueueEmpty(&qu))
	{
		//先访问队头的元素
		BTNode* bt = QueueFront(&qu);//获取队头元素
		printf("%d ", bt->_data);

		//将树的左右孩子都带入队列中,NULL孩子除外
		if (bt->_left)
			QueuePush(&qu, bt->_left);
		if (bt->_right)
			QueuePush(&qu, bt->_right);

        //队头数据处队列
		QueuePop(&qu);
	}
    
    //销毁队列
	QueueDestroy(&qu);

}

5.二叉树总代码

队列的相关功能:

Queue.h

#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<stdbool.h>

typedef struct BinaryTreeNode* QDataType;   //队列中的元素是树的节点
// 链式结构:表示队列 
typedef struct QListNode
{
	struct QListNode* _next;
	QDataType _data;
}QNode;

// 队列的结构 
typedef struct Queue
{
	QNode* _front;
	QNode* _rear;
	int size;
}Queue;

// 初始化队列 
void QueueInit(Queue* q);
// 队尾入队列 
void QueuePush(Queue* q, QDataType data);
// 队头出队列 
void QueuePop(Queue* q);
// 获取队列头部元素 
QDataType QueueFront(Queue* q);
// 获取队列队尾元素 
QDataType QueueBack(Queue* q);
// 获取队列中有效元素个数 
int QueueSize(Queue* q);
// 检测队列是否为空,如果为空返回非零结果,如果非空返回0 
int QueueEmpty(Queue* q);
// 销毁队列 
void QueueDestroy(Queue* q);

Queue.c

#define _CRT_SECURE_NO_WARNINGS 1
#include"Queue.h"

// 初始化队列 
void QueueInit(Queue* q) {
	assert(q);

	q->size = 0;
	q->_front = NULL;
	q->_rear = NULL;
}
// 队尾入队列 
void QueuePush(Queue* q, QDataType data) {
	assert(q);

	QNode* newnode = (QNode*)malloc(sizeof(QNode));
	if (newnode == NULL)
	{
		perror("QueuePush()::malloc()");
		return;
	}

	newnode->_data = data;
	newnode->_next = NULL;
	
	//队列为NULL
	if (q->_front == NULL)
	{
		q->_front = q->_rear = newnode;
	}
	else
	{
		q->_rear->_next = newnode;
		q->_rear = q->_rear->_next;
	}

	q->size++;
}
// 队头出队列 
void QueuePop(Queue* q) {
	assert(q);
	assert(q->size != 0);

	//单个节点
	if (q->_front == q->_rear)
	{
		free(q->_front);
		q->_front = q->_rear = NULL;
	}
	//多个节点
	else
	{
		QNode* next = q->_front->_next;
		free(q->_front);
		q->_front = next;
	}

	q->size--;
}
// 获取队列头部元素 
QDataType QueueFront(Queue* q) {

	assert(q);
	assert(q->_front);//队头不能为NULL

	return q->_front->_data;
}
// 获取队列队尾元素 
QDataType QueueBack(Queue* q) {
	assert(q);
	assert(q->_rear);//队尾不能为NULL

	return q->_rear->_data;
}
// 获取队列中有效元素个数 
int QueueSize(Queue* q) {

	return q->size;
}
// 检测队列是否为空,如果为空返回非零结果,如果非空返回0 
int QueueEmpty(Queue* q) {
	assert(q);

	return q->size == 0;
}
// 销毁队列 
void QueueDestroy(Queue* q) {
	assert(q);

	QNode* cur = q->_front;
	while (cur)
	{
		QNode* next = cur->_next;
		free(cur);
		cur = next;
	}

	q->_front = q->_rear = NULL;
	q->size = 0;

	//这个应该留给用户去释放
	/*free(q);
	q = NULL;*/
}

二叉树相关功能:

BinaryTree.h

#pragma once
#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
#include"Queue.h"
typedef char BTDataType;

typedef struct BinaryTreeNode
{
	BTDataType _data;
	struct BinaryTreeNode* _left;
	struct BinaryTreeNode* _right;
}BTNode;


// 二叉树销毁
void BinaryTreeDestory(BTNode** root);

// 二叉树节点个数
int BinaryTreeSize(BTNode* root);

// 二叉树叶子节点个数
int BinaryTreeLeafSize(BTNode* root);

// 二叉树第k层节点个数
int BinaryTreeLevelKSize(BTNode* root, int k);

// 二叉树查找值为x的节点
BTNode* BinaryTreeFind(BTNode* root, BTDataType x);

// 二叉树前序遍历 
void BinaryTreePrevOrder(BTNode* root);

// 二叉树中序遍历
void BinaryTreeInOrder(BTNode* root);

// 二叉树后序遍历
void BinaryTreePostOrder(BTNode* root);

// 层序遍历
void BinaryTreeLevelOrder(BTNode* root);

// 判断二叉树是否是完全二叉树
int BinaryTreeComplete(BTNode* root);

BTNode* CreatBinaryTree();

BinaryTree.c

#define _CRT_SECURE_NO_WARNINGS 1
#include"BinaryTree.h"
BTNode* BuyNode(BTDataType x) {

	BTNode* newnode = (BTNode*)malloc(sizeof(BTNode));
	if (newnode == NULL)
	{
		perror("Buynode()::malloc()");
		return newnode;
	}

	newnode->_data = x;
	newnode->_left = NULL;
	newnode->_right = NULL;
	return newnode;
}

// 二叉树前序遍历 
void BinaryTreePrevOrder(BTNode* root) {

	if (root == NULL)  //当访问的数为NULL树时停止访问
	{
		printf("N ");
		return;
	}

	printf("%d ",root->_data);//先便利根节点,整形的数据类型

	BinaryTreePrevOrder(root->_left);//左子树
	BinaryTreePrevOrder(root->_right);//右子树

}
// 二叉树中序遍历
void BinaryTreeInOrder(BTNode* root) {

	if (root == NULL)
	{
		printf("N ");
		return;
	}

	BinaryTreeInOrder(root->_left);//左子树
	printf("%d ", root->_data);//根节点
	BinaryTreeInOrder(root->_right);//右子树
}

// 二叉树后序遍历
void BinaryTreePostOrder(BTNode* root) {
	if (root == NULL)
	{
		printf("N ");
		return;
	}

	BinaryTreePostOrder(root->_left);//左子树
	BinaryTreePostOrder(root->_right);//右子树
	printf("%d ", root->_data);//根节点
}

//求二叉树的高度
int maxDepth(BTNode* root) {

	if (root == NULL)   //如果为空树则返回 0 
	{
		return 0;
	}

	int lefthigh = maxDepth(root->_left);    //记录树的左子树高度
	int righthigh = maxDepth(root->_right); //记录树的右子树高度

    //左子树高则返回左子树的高度    右子树高则返回右子树高度
	return lefthigh > righthigh ? lefthigh + 1 : righthigh + 1; 

}

// 二叉树叶子节点个数
int BinaryTreeLeafSize(BTNode* root) {

	if (root == NULL)  //如果为空树则返回 0 
		return 0;

	if (root->_left == NULL && root->_right == NULL)  //如果是叶子节点就返回 1 
		return 1;

    //返回左子树 与 右子树总共的叶子节点
	return BinaryTreeLeafSize(root->_left) + BinaryTreeLeafSize(root->_right);
}

// 二叉树第k层节点个数
int BinaryTreeLevelKSize(BTNode* root, int k) {

    //将找第k层问题转化成:层序遍历按照树的层次进行遍历,每次遍历一层,直到遍历到第k层或者遍历完整个树。   

	if (root == NULL)    //如果为空树则返回 0 
		return 0;

	if (root != NULL && k == 1) //当不为空且k为1时,到达所找层,返回1
		return 1;
	
    //一层一层的往下找
	if (root != NULL && k > 1)
		return BinaryTreeLevelKSize(root->_left,k - 1) 
        + BinaryTreeLevelKSize(root->_right,k - 1);
}

// 二叉树查找值为x的节点
//向这种找值的,一定要记录,把记录的递归返回
BTNode* BinaryTreeFind(BTNode* root, BTDataType x) {

	if (root == NULL)
		return NULL;

	if (root->_data == x)
		return root;

	BTNode* find1 = NULL;
	BTNode* find2 = NULL;

	
	find1 = BinaryTreeFind(root->_left, x);  //记录所找的节点

	if (find1)//如果左边找到了就不用去右边找了
		return find1;

	find2 = BinaryTreeFind(root->_right, x);
		return find2;
}

// 二叉树销毁
void BinaryTreeDestory(BTNode** root) {

	if (*root == NULL)
		return;
	BinaryTreeDestory(&((*root)->_left));//先销毁左子树
	BinaryTreeDestory(&((*root)->_right));//在销毁右子树
	free(*root);
	*root = NULL;
}

// 二叉树节点个数
int BinaryTreeSize(BTNode* root) {
	if (root == NULL)
		return 0;

	return BinaryTreeSize(root->_left)+ BinaryTreeSize(root->_right) + 1;
}

// 层序遍历
void BinaryTreeLevelOrder(BTNode* root) {
	//创建队列
	Queue qu;
	QueueInit(&qu);
	QueuePush(&qu, root);

	//开始拖家带口,当队列为NULL时,说明已经遍历完成,循环结束
	while (!QueueEmpty(&qu))
	{
		//先访问队头的元素
		BTNode* bt = QueueFront(&qu);//获取队头元素

		printf("%d ", bt->_data);

		//将树的左右孩子都带入队列中
		if (bt->_left)
			QueuePush(&qu, bt->_left);
		if (bt->_right)
			QueuePush(&qu, bt->_right);

		QueuePop(&qu);
	}

	QueueDestroy(&qu);


}

// 判断二叉树是否是完全二叉树
int BinaryTreeComplete(BTNode* root) {

	//创建队列
	Queue qu;
	QueueInit(&qu);
	QueuePush(&qu, root);

	//开始拖家带口,当队列为NULL时,说明已经遍历完成,循环结束
	while (!QueueEmpty(&qu))
	{
		//队列中存的数据是,树节点的指针,我们先访问队头的元素
		BTNode* bt = QueueFront(&qu);//获取队头元素

		if (bt == NULL)
		{
			break;
		}


		//将树的左右孩子都带入队列中,NULL也不例外
		QueuePush(&qu, bt->_left);
		QueuePush(&qu, bt->_right);

		QueuePop(&qu);
	}

	while (!QueueEmpty(&qu))
	{
		BTNode* bt = QueueFront(&qu);//获取队头元素

		//如果在遇到非空的节点,说明它不是一个完全二叉树返回false
		if (bt)
		{
			return false;
		}

		QueuePop(&qu);
	}

	QueueDestroy(&qu);

	return true;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1866810.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

一加全机型TWRP合集/橙狐recovery下载-20240603更新-支持一加12/Ace3V手机

TWRP是目前安卓平台的刷机神器&#xff0c;可快速刷写第三方ROM或官方系统&#xff0c;刷入TWRP之前需要解锁BL&#xff0c;目前已适配一加多个机型。ROM乐园小编20240603整理&#xff0c;涵盖一加1到一加Ace3V多机型专用TWRP文件&#xff0c;个人机型橙狐recovery适配相对完整…

MySQL 8 命令安装卸载教程

一、下载MySQL8 下载连接 MySQL :: Download MySQL Community Server 我下载的是当前最新版8.4 二、安装 1.解压 解压到需要安装的位置&#xff0c;例如我的位置&#xff1a; 2.创建配置文件 新建文本文档&#xff0c;复制下面配置文件&#xff08;注意修改路经&#xff09;…

DPDK使用make编译并运行示例程序

环境&#xff1a; VMware Workstation 16 Pro 16.2.4 虚拟机系统&#xff1a;Centos 8 DPDK版本&#xff1a;stable-20.11.10 下载源码后&#xff0c;使用meson和ninja编译完成、配置并挂载大页、内核和VFIO设置完成&#xff0c;在dpdk源码目录下的build/…

小程序 UI 风格,引人入胜

小程序 UI 风格&#xff0c;引人入胜

OceanBase 4.X-2F1A 仲裁高可用方案初探

作者&#xff1a;郑增权&#xff0c;爱可生 DBA 团队成员&#xff0c;OceanBase 和 MySQL 数据库技术爱好者。 爱可生开源社区出品&#xff0c;原创内容未经授权不得随意使用&#xff0c;转载请联系小编并注明来源。 本文约 1500 字&#xff0c;预计阅读需要 5 分钟。 背景 对…

10个国内免费AI绘画网站汇总【2024最新】

迎战MidJourney和Stable Diffusion&#xff1a;10款国产AI绘画神器&#xff0c;让你轻松创作出超凡艺术品&#xff01;不论你是初学者还是资深艺术家&#xff0c;这些AI绘画平台都能帮你轻松入门。快来探索这些AI绘画网站&#xff0c;释放你的创意潜能&#xff01; 1、AI绘画创…

Linux系统之nice命令的基本使用

Linux系统之nice命令的基本使用 一、nice命令介绍1.1 nice命令简介1.2 进程优先级介绍 二、nice命令基本语法2.1 nice命令的help帮助信息2.2 nice命令选项解释 三、nice命令的基本使用3.1 查看进程优先级3.2 使用nice启动进程3.3 提高优先级 四、注意事项 一、nice命令介绍 1.…

YCSB基准测试

1、Redis: 下载成功后&#xff0c;加载数据&#xff0c;运行 启动redis: /usr/local/redis/bin/redis-server ./bin/ycsb load redis -P workloads/workloade -p redis.hostlocalhost -p redis.port6379 -p recordcount10000 -p operationcount10000 -threads 32 ./bin/y…

Vue3-尚硅谷笔记

1. Vue3简介 2020年9月18日&#xff0c;Vue.js发布版3.0版本&#xff0c;代号&#xff1a;One Piece&#xff08;n 经历了&#xff1a;4800次提交、40个RFC、600次PR、300贡献者 官方发版地址&#xff1a;Release v3.0.0 One Piece vuejs/core 截止2023年10月&#xff0c;最…

简述RocketMQ从了解到使用

概念篇 背景: 随着队列和虚拟主题使用的增加,ActiveMQ IO模块达到了一个瓶颈。我们尽力通过节流、断路器或降级来解决这个问题,但效果并不理想。于是我们尝试了流行的消息传递解决方案Kafka。不幸的是,Kafka不能满足我们的要求,其尤其表现在低延迟和高可靠性方面,详见下…

后端之路第三站(Mybatis)——入门配置

一、Mybatis是啥&#xff1f; 就是一个用java来操控数据库的框架语言 之前学的datagrip或者navicat这些软件里我们操作数据库&#xff0c;原理是我们编写完的操作语句发送到服务器传送到数据库系统&#xff0c;然后数据库执行完之后再发送给服务器返回给datagrip或者navicat显…

服务器数据恢复—用raid6阵列磁盘组建raid5阵列如何恢复原raid数据?

服务器存储数据恢复环境&#xff1a; 华为OceanStor 5800存储&#xff0c;该存储中有一组由10块硬盘组建的raid6磁盘阵列&#xff0c;供企业内部使用&#xff0c;服务器安装linux操作系统EXT3文件系统&#xff0c;划分2个lun。 服务器存储故障&#xff1a; 管理员发现存储中rai…

多家国产大模型提供OpenAI API服务替代方案,谷歌将推出明星网红AI聊天机器人

ChatGPT狂飙160天&#xff0c;世界已经不是之前的样子。 更多资源欢迎关注 1、OpenAI终止对中国提供服务 6月25日凌晨&#xff0c;多个用户收到OpenAI的推送邮件&#xff0c;信中称&#xff0c;自今年7月9日起&#xff0c;将开始阻止来自非支持国家和地区的API&#xff08;应…

pythons工具——裁剪labelme的json不规则多边形标签保存成矩形图像

原图labelme标注 使用以下程序&#xff0c;裁剪labelme的json不规则多边形标签保存成矩形图像 import os import cv2 import math import json import numpy as np from PIL import Image, ImageDrawdef calculate_bounding_box(points):"""计算多边形的最小外…

高校心理咨询管理系统

摘 要 随着高校学生心理问题的增多&#xff0c;心理咨询服务在高校中的重要性日益凸显。然而&#xff0c;传统的心理咨询管理方式存在着诸多问题&#xff0c;如信息不透明、咨询师资源不足等。为了解决这些问题&#xff0c;本文设计并实现了一种基于Java Web的高校心理咨询管理…

Java Stream API揭秘:掌握List流操作,打造高效数据处理流程

序言 Java Stream API是Java 8中引入的一个非常重要的功能组成部分&#xff0c;它提供了一种声明式的处理数据集合的方法。它主要特点是基于函数式编程的理念&#xff0c;允许我们以更加简洁、高效的方式进行集合的处理、转换和过滤。通过Stream API&#xff0c;我们可以灵活地…

Animate软件为什么默认只能导出mov格式视频?

很多同学在学习Animate软件的时候&#xff0c;经常会有一个问题&#xff0c;就是制作好动画导出视频时&#xff0c;只能选择mov格式&#xff0c;而且导出文件特别大&#xff0c;为什么Animate软件默认只能导出mov格式的视频呢&#xff1f;这里简单说一下自己的看法。 首先&…

打破数据分析壁垒:SPSS复习必备(十)

Means过程 统计学上的定义和计算公式 定义&#xff1a;Means过程是SPSS计算各种基本描述统计量的过程&#xff0c;其实就是按照用户指定条件&#xff0c;对样本进行分组计算均数和标准差&#xff0c;如按性别计算各组的均数和标准差。 用户可以指定一个或多个变量作为分组变…

分布式系统:常见的陷阱和复杂性

分布式系统的复杂性是工程师和开发人员面临的重要挑战。复杂性往往会随着系统的发展而增加&#xff0c;因此积极主动非常重要。让我们来谈谈您可能会遇到哪些类型的复杂性以及在工作中应对它的有效策略。 分布式系统和复杂性 在开发中&#xff0c;分布式系统是相互连接并执行…

文华wh6均线交易策略多空波段止盈止损提示主图指标公式源码

文华wh6均线交易策略多空波段止盈止损提示主图指标公式源码&#xff1a; EMA120:EMA(C,120); RSV:(CLOSE-LLV(LOW,9))/(HHV(HIGH,9)-LLV(LOW,9))*100; K:SMA(RSV,3,1); D:SMA(K,3,1); J:3*K-2*D; DRAWTEXT(C>EMA120&&J<0,L,多),VALIGN0; DRAWTEXT(C<EMA…