【数据结构】树和二叉树——Lesson1

news2024/11/11 3:19:39

Hi~!这里是奋斗的小羊,很荣幸您能阅读我的文章,诚请评论指点,欢迎欢迎 ~~
💥💥个人主页:奋斗的小羊
💥💥所属专栏:C语言

🚀本系列文章为个人学习笔记,在这里撰写成文一为巩固知识,二为展示我的学习过程及理解。文笔、排版拙劣,望见谅。


目录

  • 前言
  • 一、树
    • 1、树的概念和结构
    • 2、相关术语
    • 3、树的表示
    • 4、树形结构应用场景
  • 二、二叉树
    • 1、概念和结构
    • 2、特殊的二叉树
    • 3、二叉树的存储
      • 3.1顺序存储
      • 3.2链式存储
    • 4、顺序结构实现二叉树
      • 4.1堆的结构和概念
      • 4.2堆的实现
        • 4.2.1向上调整算法
        • 4.2.2向下调整算法
      • 4.3堆的应用
        • 4.3.1堆排序
        • 4.3.2 TOP-K问题
    • 5、完整代码
  • 总结

前言

一、树

1、树的概念和结构

树是一种非线性的数据结构,它是由n(n>=0)个有限节点组成的一个具有层次关系的集合。它包含一个根节点以及若干子节点,子节点又可以有自己的子节点,以此类推。

  • 根节点: 根节点没有前驱结点
  • 子节点: 除根节点外,其余节点被分为m(m>0)个互不相交的集合,其中每一个集合又是一棵结构与树类似的子树。每棵子树的根节点有且只有一个前驱节点,可以有0个或多个后继节点。因此,树是递归定义的。

与现实中的树相比,这里的树更像是一棵倒挂的树。

在这里插入图片描述

在这里插入图片描述

树形结构中,子树之前不能有交集,否则就不是树形结构。

非树结构:
在这里插入图片描述

  • 子树是不相交的
  • 除了根节点,每个节点有且只有一个父节点
  • 一棵N个节点的树有N-1条边

2、相关术语

树有很多的术语,基本都是根据现实中的树和人类亲缘关系命名的,其中红色标记的是比较重要的概念。

  • 父节点/双亲节点 若一个节点有子节点,这个节点就是子节点的父节点(相对的),上图中A是B的父节点
  • 子节点 一个节点含有的子树的根节点称为该节点的子节点,上图B是A的子节点
  • 节点的度: 一个节点有几个孩子,它的度就是多少
  • 树的度: 一棵树中,最大节点的度就是树的度,上图树的度为2
  • 叶子节点/终端节点 度为0的节点称为叶子节点
  • 分支节点/非终端节点: 度不为0的节点
  • 兄弟节点: 具有相同父亲的节点就是兄弟节点(亲兄弟)
  • 节点的层次: 从根开始定义起,根为第一层,其子节点为第二层,以此类推
  • 树的高度/深度 树中节点的最大层次,上图树的深度为5
  • 节点的祖先: 从根到该节点所经分支上的所有节点
  • 路径: 一条从树中任意节点出发,沿父节点-子节点连接,达到任意节点的序列
  • 子孙: 以某节点为根的子树中任意一节点都称为该节点的子孙
  • 森林: 由m (m>0)棵互不相交的树(多棵树)的集合称为森林

3、树的表示

树结构相对线性表复杂的多,既要保存值域,还要保存节点和节点之间的关系,最常用的表示法是左孩子右兄弟表示法。

struct TreeNode
{
	struct Node* child;//左边开始的第一个孩子节点
	struct Node* brother;//右边的下一个兄弟节点
	int data;
};


4、树形结构应用场景

文件系统是计算机存储和管理文件的一种方式,它利用树形结构来组织和管理文件好文件夹。在文件系统中,树结构被广泛应用,它通过父节点和子节点之间的关系来表示不同层级的文件和文件夹之间的关联。

请添加图片描述


二、二叉树

1、概念和结构

二叉树是一种特殊的树,在树形结构中,我们最常用的就是二叉树,一棵二叉树是节点的一个有限集合,该集合由一个根节点加上两棵别称为左子树右子树的二叉树组成或者为空。
在这里插入图片描述

上图就是二叉树的基本结构。从上图可以看到,二叉树有以下特点:

二叉树的特点:

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

对于任意二叉树都是由以下几种情况复合而成的:


2、特殊的二叉树

  • 满二叉树: 一个二叉树,如果每一层的节点数都达到最大值,则这个二叉树就是满二叉树。一个层数为N的满二叉树的节点数为2^N-1。
  • 完全二叉树: 完全二叉树的前N-1层都是满的,最后一层不满且子节点从左到右必须是连续的。完全二叉树是效率很高的数据结构,完全二叉树是由满二叉树引出来的,因此满二叉树是一种特殊的完全二叉树。

在这里插入图片描述


3、二叉树的存储

3.1顺序存储

顺序存储就是使用数组来存储,一般使用数组只适合表示完全二叉树,如果不是完全二叉树要保证下标对应就会有空间浪费,因此完全二叉树适合用顺序结构存储。

请添加图片描述
可以看到非完全二叉树虽然也可以使用数组存储,但是存在空间浪费,所以非完全二叉树更适合链式存储。

这种存储结构有一个规律,可以根据下标来计算父子关系。

假设父亲在数组中的下标为:i

  • 左孩子在数组中的下标:2*i+1
  • 右孩子在数组中的下标:2*i+2

假设孩子在数组中的下标是:j

  • 父亲在数组中的下标就是(j-1)/ 2

实际中常把堆(一种二叉树)使用顺序结构的数组来存储,需要注意的是这里的堆和操作系统虚拟进程地址空间中的堆不是一回事,一个是数据结构,一个是操作系统中管理内存的一块区域划分。


3.2链式存储

二叉树的链式存储是指用链表来表示一棵二叉树,即用链表来指示元素的逻辑关系。
通常每个节点由三个域组成,一个数据域和两个指针域,分别用左指针和右指针来指向左孩子和右孩子。链式结构又分为二叉链和三叉链,当前学习中一般都是二叉链。
请添加图片描述

本篇文章主要介绍二叉树的顺序存储,在下篇文章中会详细介绍二叉树的链式存储。


4、顺序结构实现二叉树

4.1堆的结构和概念

堆(Heap)栈(Stack)
数据结构一种树形结构,可以做堆排序,效率很高一种线性结构,具有后进先出的特点,基本操作有压栈、出栈
C语言用于动态分配内存的区域由操作系统分配的固定大小的空间

一般堆使用顺序结构的数组来存储数据,堆是一种特殊的二叉树,具有二叉树性质的同时,还具备其他的特性。

堆具有以下性质:

  • 堆中某个节点的值总是不大于或不小于其父节点的值
  • 堆是一棵完全二叉树

其中堆又分为大堆和小堆:

  • 大堆 / 大根堆 / 大顶堆:任何一个父亲>=孩子,根最大
  • 小堆 / 小根堆 / 小顶堆:任何一个父亲<=孩子,根最小

在这里插入图片描述

从上图中可以看到,小堆不一定是升序,大堆也不一定是降序, 因为兄弟之间没有大小关系。


4.2堆的实现

堆的底层结构是数组,基本与顺序表一样。因此定义堆的结构为:

typedef int HeapDataType;

typedef struct Heap
{
	HeapDataType* arr;
	int size;
	int capacity;
}Heap;

void HeapInit(Heap* php);
void HeapDestroy(Heap* php);
HeapDataType HeapTop(Heap* php);
bool HeapEmpty(Heap* php);

其中初始化、销毁、取堆顶、判空函数也基本与我们之前写过的相差无几,这里就直接给出不做介绍。

void HeapInit(Heap* php)
{
	assert(php);
	php->arr = NULL;
	php->size = php->capacity = 0;
}

void HeapDestroy(Heap* php)
{
	assert(php);
	free(php->arr);
	php->arr = NULL;
	php->size = php->capacity = 0;
}

HeapDataType HeapTop(Heap* php)
{
	assert(php);
	assert(php->size > 0);
	return php->arr[0];
}

bool HeapEmpty(Heap* php)
{
	assert(php);
	return php->size == 0;
}

接下来就到了比较重要的内容.

4.2.1向上调整算法

| 堆的插入
将新数据插入到数组末尾,再通过向上调整算法,直到满足堆。

  • 先将元素插入到堆的末尾,即最后一个孩子之后
  • 插入后如果堆的性质被破坏,将新插入的节点顺着其双亲节点往上调整到合适的位置即可

下面是小堆插入:

在这里插入图片描述

void AdjustUp(HeapDataType* arr, int child)
{
	int parent = (child - 1) / 2;
	while (child > 0)
	{
		           //  > 是建大堆
		if (arr[child] > arr[parent])
		{
			Swap(&arr[child], &arr[parent]);
			child = parent;
			parent = (child - 1) / 2;
		}
		else
		{
			break;
		}
	}
}

void HeapPush(Heap* php, HeapDataType x)
{
	assert(php);
	if (php->size == php->capacity)
	{
		int newcapacity = php->capacity == 0 ? 4 : 2 * php->capacity;
		HeapDataType* tmp = (HeapDataType*)realloc(php->arr, newcapacity * sizeof(HeapDataType));
		if (tmp == NULL)
		{
			perror("realloc fail");
			return;
		}
		php->arr = tmp;
		tmp = NULL;
		php->capacity = newcapacity;
	}
	php->arr[php->size] = x;
	php->size++;
	
	//向上调整
	AdjustUp(php->arr, php->size - 1);
}

向上调整算法建堆的时间复杂度为:O(N*logN)


4.2.2向下调整算法

| 堆的删除

删除堆是删除堆顶的数据,前提是size > 0有数据可删。将堆顶的数据和最后一个数据交换,然后删除数组最后一个数据,为了继续满足堆需要再进行向下调整算法,结果是次小的(次大的)在堆顶。
堆顶数据和最后一个数据交换再删除的目的是保证根节点下左右子树都是堆,父子关系不会乱。

请添加图片描述

向下调整:

在这里插入图片描述

void AdjustDown(HeapDataType* arr, int parent, int n)
{
	//假设左孩子小
	int child = 2 * parent + 1;

	while (child < n)//child>=n时孩子不存在
	{
		                            // < 是建大堆
		if ((child + 1) < n && arr[child] < arr[child + 1])//防止右孩子越界
		{
			//建大堆,要大孩子,建小堆,要小孩子
			child++;
		}
		if (arr[child] > arr[parent])
		{
			Swap(&arr[child], &arr[parent]);
			parent = child;
			child = 2 * parent + 1;
		}
		else
		{
			break;
		}
	}
}

void HeapPop(Heap* php)
{
	assert(php);
	assert(php->size > 0);
	Swap(&php->arr[0], &php->arr[php->size - 1]);
	php->size--;
	
	AdjustDown(php->arr, 0, php->size);
}

向下调整算法建堆时间复杂度为:O(N)


4.3堆的应用

4.3.1堆排序

| 版本一:基于已有数组建堆,取堆顶元素完成排序

void HeapSort(HeapDataType* arr, int n)
{
	Heap hp;
	for (int i = 0; i < n; i++)
	{
		HeapPush(&hp, arr[i]);
	}

	int i = 0;
	while (!HeapEmpty(&hp))
	{
		arr[i++] = HeapTop(&hp);
		HeapPop(&hp);
	}

	HeapDestroy(&hp);
}

该版本有一个前提:必须提供有现成的数据结构堆。
所以这样排序不好,得先建一个堆放入数据(开辟额外空间),再从堆里面将数组拷贝到原数组中,空间复杂度O(N)
要是能有什么办法避免开辟额外的空间就好了,来看版本二:


| 版本二:原数组上建堆,首尾交换,交换后的堆尾数据从堆中删除,将堆顶数据向下(向上)调整选出次大(次小)的数据

思路是直接将原数组(看作)一个堆,从下标为1的孩子开始,向上(向下) 循环调整(实现大堆或者小堆),最终达到在原数组上建堆的效果,这个方法好在没有额外的空间消耗。

//向上调整建堆
for (int i = 1; i < n; i++)
{
	AdjustUp(arr, i);
}

//向下调整建堆
for (int i = (n-1-1) / 2; i >= 0; i--)
{
	AdjustDown(arr, i, n);
}

向上调整算法建堆时默认第一个元素已经排好,从下标为1的元素往后依次开始调整。
向下调整算法建堆,从最后一个孩子的父亲开始往前依次向下调整,到堆顶时结束。

因为向上调整算法建堆的时间复杂度是:O(N*logN),而向下调整算法建堆的时间复杂度是:O(N),所以我们优先使用向下调整算法建堆来实现堆排序

确定了建堆的算法,接下来就要考虑的是如果我们要排升序,该在原数组上建大堆还是小堆?
可能大多数人下意识地认为排升序的话应该建小堆,因为我们可以通过循环拿根节点(堆顶)再删除根节点的方法依次得到最小值,其实这样是不好的
因为小堆的堆顶是所有数里的最小值,此时堆顶已经排好了,要想排剩下的数就要重新建堆,这样一来父子关系全乱了,实现起来代价太大。

如果建大堆,此时堆顶是最大的数,可以删除堆顶,结果就是最大的数到数组末端,n- -后这个最大的数就不被当做堆内的数,循环向下调整重复上面的操作,就能得到按升序排列的数组了。

请添加图片描述

所以,排升序,建大堆;排降序,建小堆。

void HeapSort(int* arr, int n)
{
	//升序,建大堆
	//降序,建小堆
	
	//向下调整建堆
	//O(N)
	for (int i = (n-1-1) / 2; i >= 0; i--)
	{
		AdjustDown(arr, i, n);
	}
	
	//O(N*logN)
	int end = n - 1;
	while (end > 0)
	{
		Swap(&arr[0], &arr[end]);
		AdjustDown(arr, 0, end);
		end--;
	}
}

向下调整算法建堆时间复杂度O(N),再加上最后的排序操作的时间复杂度O(N*logN),整个堆排序的时间复杂度是O(N*logN),比起冒泡排序时间复杂度O(N^2),堆排序是非常非常理想的。


4.3.2 TOP-K问题

TOP-K问题:求数据量比较大的数据中前K个最大或最小的元素。比如:富豪榜TOP10、世界企业TOP500、中国名校TOP100等。

对于TOP-K问题,最简单最直接的办法就是排序,但是当数据量比较大时排序就不可取了,最佳的方式就是利用堆来解决。

我们可以将大量的数据建大堆(向下调整算法优先),此时堆顶就是最大的数据,然后Topk次就能解决问题了。

void TOP()
{
	Heap hp;
	HeapInit(&hp);

	int arr[] = { 34,453,3,4,56,36,6,3,7,34,6,36,3,7,2,4,46,534,7,3,7673,56 };
	for (int i = 0; i < sizeof(arr) / sizeof(int); i++)
	{
		HeapPush(&hp, arr[i]);
	}

	int k = 0;
	scanf("%d", &k);
	while (k--)
	{
		printf("%d ", HeapTop(&hp));
		HeapPop(&hp);
	}

	HeapDestroy(&hp);
}

请添加图片描述


5、完整代码

heap.h:

#pragma once

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

typedef int HeapDataType;

typedef struct Heap
{
	HeapDataType* arr;
	int size;
	int capacity;
}Heap;

void AdjustUp(HeapDataType* arr, int child);
void AdjustDown(HeapDataType* arr, int parent, int n);
void Swap(HeapDataType* child, HeapDataType* parent);
void HeapInit(Heap* php);
void HeapDestroy(Heap* php);
void HeapPush(Heap* php, HeapDataType x);
void HeapPop(Heap* php);
HeapDataType HeapTop(Heap* php);
bool HeapEmpty(Heap* php);

heap.c:

#define  _CRT_SECURE_NO_WARNINGS

#include "heap.h"

void HeapInit(Heap* php)
{
	assert(php);
	php->arr = NULL;
	php->size = php->capacity = 0;
}

void HeapDestroy(Heap* php)
{
	assert(php);
	free(php->arr);
	php->arr = NULL;
	php->size = php->capacity = 0;
}

void Swap(HeapDataType* child, HeapDataType* parent)
{
	HeapDataType tmp = *child;
	*child = *parent;
	*parent = tmp;
}

void AdjustUp(HeapDataType* arr, int child)
{
	int parent = (child - 1) / 2;
	while (child > 0)
	{
		//  > 是建大堆
		if (arr[child] > arr[parent])
		{
			Swap(&arr[child], &arr[parent]);
			child = parent;
			parent = (child - 1) / 2;
		}
		else
		{
			break;
		}
	}
}

void HeapPush(Heap* php, HeapDataType x)
{
	assert(php);
	if (php->size == php->capacity)
	{
		int newcapacity = php->capacity == 0 ? 4 : 2 * php->capacity;
		HeapDataType* tmp = (HeapDataType*)realloc(php->arr, newcapacity * sizeof(HeapDataType));
		if (tmp == NULL)
		{
			perror("realloc fail");
			return;
		}
		php->arr = tmp;
		tmp = NULL;
		php->capacity = newcapacity;
	}
	php->arr[php->size] = x;
	php->size++;

	//向上调整
	AdjustUp(php->arr, php->size - 1);
}

void AdjustDown(HeapDataType* arr, int parent, int n)
{
	//假设左孩子小
	int child = 2 * parent + 1;

	while (child < n)//child>=n时孩子不存在
	{
		// < 是建大堆
		if ((child + 1) < n && arr[child] < arr[child + 1])//防止右孩子越界
		{
			//建大堆,要大孩子,建小堆,要小孩子
			child++;
		}
		if (arr[child] > arr[parent])
		{
			Swap(&arr[child], &arr[parent]);
			parent = child;
			child = 2 * parent + 1;
		}
		else
		{
			break;
		}
	}
}

void HeapPop(Heap* php)
{
	assert(php);
	assert(php->size > 0);
	Swap(&php->arr[0], &php->arr[php->size - 1]);
	php->size--;

	AdjustDown(php->arr, 0, php->size);
}

HeapDataType HeapTop(Heap* php)
{
	assert(php);
	assert(php->size > 0);
	return php->arr[0];
}

bool HeapEmpty(Heap* php)
{
	assert(php);
	return php->size == 0;
}

test.c:

#define  _CRT_SECURE_NO_WARNINGS

#include "heap.h"

void test1()
{
	int arr[] = { 5,3,2,8,5,3,6,9,0 };
	Heap hp;
	HeapInit(&hp);

	for (int i = 0; i < sizeof(arr) / sizeof(int); i++)
	{
		HeapPush(&hp, arr[i]);
	}

	HeapDestroy(&hp);
}

void test2()
{
	//排升序
	int arr[] = { 5,3,2,8,5,3,6,9,0 };
	for (int i = 1; i < sizeof(arr) / sizeof(int); i++)
	{
		//建大堆
		AdjustUp(arr, i);
	}

}

//void HeapSort(int* arr, int n)
//{
//	//升序,建大堆
//	//降序,建小堆
//
//	for (int i = 1; i < n; i++)
//	{
//		AdjustUp(arr, i);
//	}
//
//	int end = n - 1;
//	while (end > 0)
//	{
//		Swap(&arr[0], &arr[end]);
//		AdjustDown(arr, 0, end);
//		end--;
//	}
//}

void TOP()
{
	Heap hp;
	HeapInit(&hp);

	int arr[] = { 34,453,3,4,56,36,6,3,7,34,6,36,3,7,2,4,46,534,7,3,7673,56 };
	for (int i = 0; i < sizeof(arr) / sizeof(int); i++)
	{
		HeapPush(&hp, arr[i]);
	}

	int k = 0;
	scanf("%d", &k);
	while (k--)
	{
		printf("%d ", HeapTop(&hp));
		HeapPop(&hp);
	}

	HeapDestroy(&hp);
}

int main()
{
	//test1();
	//test2();
	TOP();

	return 0;
}

总结

  • 二叉树在各种领域和问题中都有广泛的应用,文件系统、数据库、表达式求值、代码编译、网络路由、Huffman 编码等场景。
  • 堆排序利用了二叉堆的性质,通过构建最大堆(或最小堆)来实现排序。整个排序过程分为两个阶段:首先通过数组构建一个最大堆,然后不断将堆顶元素与堆的最后一个元素交换并调整堆,最终得到一个有序数组。

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

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

相关文章

一个小问题导致,AI大模型集体翻车?

9.11大还是9.9大&#xff1f; 这两天大家都在说ChatGPT大模型翻车了 &#xff01; 这到底是怎么个事儿呢&#xff1f; 原来是最近有人想ChatGPT等大模型提了一个简单的问题&#xff1a; 9.11 大还是 9.9 大&#xff1f; 答案显而易见&#xff0c;然而众多大模型却给出了错误…

基于JAVA+SpringBoot+Vue的oa系统

✌全网粉丝20W,csdn特邀作者、博客专家、CSDN新星计划导师、java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ 技术范围&#xff1a;SpringBoot、Vue、SSM、HLMT、Jsp、SpringCloud、Layui、Echarts图表、Nodejs、爬…

【高性能服务器】poll模型

&#x1f525;博客主页&#xff1a; 我要成为C领域大神&#x1f3a5;系列专栏&#xff1a;【C核心编程】 【计算机网络】 【Linux编程】 【操作系统】 ❤️感谢大家点赞&#x1f44d;收藏⭐评论✍️ 本博客致力于知识分享&#xff0c;与更多的人进行学习交流 poll模型 关于sel…

算法-计数质数

题目&#xff1a; 给定整数 n &#xff0c;返回 所有小于非负整数 n 的质数的数量 。 思路&#xff1a; 使用埃式筛法 当n大于等于2时&#xff0c;如果当前遍历的数 i 是质数&#xff0c;那么从 i*i 开始&#xff0c;直到 n 为止&#xff0c;把 i 的倍数都标记为合数 代码&a…

一个关于STM32的DAC输出的遗忘点

众所周知熟练使用HAL库可以帮你解决不少stm32的开发难题&#xff0c;但是是谁让你陷入了这些难题&#xff0c;别问。 如上图所示&#xff0c;正常初始化这个模块后生成代码如下图所示&#xff1b; * DAC init function */ void MX_DAC_Init(void) {/* USER CODE BEGIN DAC_Ini…

【LabVIEW作业篇 - 3】:数组相加、for循环创建二位数组、数组练习(求最大最小值、平均值、中位数、提取范围内的数据、排序)

文章目录 数组相加for循环实现直接使用加函数 for循环创建二位数组数组练习 数组相加 要求&#xff1a;用两种方法实现两个数组相加 for循环实现 在前面板中分别创建两个数值类型的一维数组&#xff0c;并设置相应的值&#xff0c;然后在程序框图中创建一个for循环&#xff…

数据结构(Java):力扣牛客 二叉树面试OJ题(一)

&#x1f449; ​​​​​​目录 &#x1f448; 1、题一&#xff1a;检查两棵树是否相同 1.1 思路分析 1.2 代码 2、题二&#xff1a;另一棵树的子树 2.1 思路分析 2.2 代码 3、题三&#xff1a;翻转二叉树 3.1 思路分析 3.2 代码 4、题四&#xff1a;判断树是否对称 …

小模型大突破!神经网络透视空间异质性,准确描述复杂地理现象

为推进 AI4S 的普适化&#xff0c;降低学术机构科研成果的传播壁垒&#xff0c;为更多行业学者、科技爱好者及产业单位提供交流平台&#xff0c;HyperAI超神经策划了「Meet AI4S」系列直播栏目&#xff0c; 邀请深耕 AI for Science 领域的科研人员或相关单位&#xff0c;以视频…

新时代多目标优化【数学建模】领域的极致探索——数学规划模型

目录 例1 1.问题重述 2.基本模型 变量定义&#xff1a; 目标函数&#xff1a; 约束条件&#xff1a; 3.模型分析与假设 4.模型求解 5.LINGO代码实现 6.结果解释 ​编辑 7.敏感性分析 8.结果解释 例2 奶制品的销售计划 1.问题重述 ​编辑 2.基本模型 3.模…

北京邮电大学,中央空调的分户计费系统

北京邮电大学 中央空调如何公平、公正、合理的收取费用&#xff0c;一直都是各建筑管理者的首要问题。北京邮电大学也面临着能源分配不公&#xff0c;学校管理者空调收费管理困难等问题。根据学校的具体情况&#xff0c;拓森为其制定了一套中央空调管理运营方案—无线中央空调…

jupyter学习笔记

简介 Jupyter Notebook是一个Web应用程序&#xff0c;它可以在网页页面中直接编写代码和运行代码&#xff0c;代码的运行结果也会直接在代码块下显示。 安装使用 前提&#xff1a;必须安装python 先升级pip至最新版本 pip3 install --upgrade pip安装jupyter notebook pi…

springboot的简单应用

Mvc与三层架构 创建Spring项目 勾选web和mabais框架 配置yml文件&#xff0c;这里创建spring项目默认生成的是propertise文件&#xff0c;但是properties文件的格式看起来没有yml文件一目了然。yml文件配置数据库还有映射mapper层的xml文件以及设置日志级别&#xff0c;比如map…

刚起步的家庭海外仓:涉及到的全部业务优化流程

对于家庭海外仓来说&#xff0c;最难的阶段应该就是刚起步的时候。对业务流程不熟悉&#xff0c;也没有客户积累&#xff0c;本身的预算又十分有限。 在这个情况下应该注意什么&#xff0c;怎样才能顺利的开展业务&#xff1f;今天我们就针对这个问题详细的梳理了一下家庭海外…

尚品汇-(二十一)

目录&#xff1a; &#xff08;1&#xff09;使用redis实现分布式锁 &#xff08;2&#xff09;优化之设置锁的过期时间 &#xff08;3.&#xff09;优化之UUID防误删 &#xff08;4&#xff09;优化之LUA脚本保证删除的原子性 &#xff08;1&#xff09;使用redis实现分布…

go语言编程 小试牛刀 goroutine和reflect知识点

&#xff08;一&#xff09;goroutine package _caseimport "fmt"// sum 函数计算整数切片 values 的总和&#xff0c;并将结果发送到 resultChan 通道中 func sum(values []int, resultChan chan int) {sum : 0for _, value : range values {sum value}resultChan…

HarmonyOS NEXT学习——@Styles、@Extend、stateStyles

Styles装饰器 定义组件重用样式 仅支持通用属性和通用事件不支持参数可以定义全局和组件内使用&#xff0c;全局使用需要加function // 全局 Styles function functionName() { ... }// 在组件内 Component struct FancyUse {Styles fancy() {.height(100)} }组件内Styles的优…

智能一体式闸门在灌区中的应用

在现代化的农业灌溉领域&#xff0c;智能一体式闸门作为一种集自动化、智能化、高效能于一体的先进设备&#xff0c;正逐渐在灌区管理中发挥着重要作用。 灌区是农业生产的重要基地&#xff0c;其水资源的管理和利用直接关系到农作物的生长和产量。然而&#xff0c;传统的闸门管…

旋转中的图片视觉差效果

Hello&#xff0c;亲爱的宝子们&#xff1f;最近我一个前端架构师却临时顶替产品经理的工作&#xff0c;导致最近一周实在太忙了&#xff0c;都没有来得及更新文章。在这里想大家道歉了&#xff01;也想厚颜无耻的问问大家想我了吗&#xff1f;(●◡●) 今天给大家带来一个非常…

Vue 使用 Element UI 组件库

https://andi.cn/page/621589.html

RAG介绍

一&#xff0c;RAG概述 RAG&#xff08;Retrieval-Augmented Generation&#xff0c;检索增强生成&#xff09;是一种结合了信息检索与生成任务的技术&#xff0c;它通过将外部知识库与大模型的生成能力相结合&#xff0c;提高了生成内容的准确性和丰富性。以下是关于RAG应用的…