数据结构基础6:二叉树的实现和堆。

news2024/12/23 23:02:10

二叉树的概念和应用:

  • 一.树的概念和结构:
    • 一.树的概念和结构:
      • 1.树的概念:
      • 2.树的相关概念:
      • 3.树的表示:
  • 二.二叉树的概念和结构:
    • 1.概念:
    • 2.两种特殊的二叉树:
      • 1.完全二叉树:
      • 2.满二叉树:
      • 3.二叉树的性质:
      • 题目一:
      • 题目二:
      • 题目三:
      • 题目四:
      • 题目五:
      • 4.二叉树的存储结构:
  • 三.二叉树的顺序存储结构和实现:
    • 1.二叉树的顺序结构:
    • 2.堆的概念和结构:
      • 1.插入数据
      • 2获取堆顶数据(数据交换和数据减少)
    • 3.堆的代码实现:
  • 四.堆的应用:
    • 1.堆排序:
      • 1.建堆:
      • 2.利用堆的删除思想去进行排序(这是一种原地排序)
      • 3.整体代码:
    • 2.TOPK问题:

一.树的概念和结构:

一.树的概念和结构:

1.树的概念:

我们之前学习过了顺序表和链表这样比较简单的数据结构这些结构是一种线性结构,关于树他是一个树形结构,一个数有n个节点(n>=0),这些节点按层去排列,构成了一个树的结构。但是呢关于一个树他是根在上叶子在下的。

对于一颗树:
1.根节点:一个树只有一个根节点,他本身是没有前驱节点。
2.子树:除了根节点之外的其他的节点在数形结构中构成的集合,每一个子树的根节点有且只有一个前驱,和多个后继
3.树是由递归==(把一个比较复杂的问题经过一次一次的递归去简化问题的复杂度)==定义的:

eg:
请添加图片描述

补充:在树形结构中,树形结构不能有子树相交。
请添加图片描述
必须满足一个根有一个前驱和多个后继当然也可以没有后继:

2.树的相关概念:

补充:层数的概念提供了两个记录的方法:
1.层数从1开始。
2.层数从0开始。
在这里插入图片描述
请添加图片描述
1.使用0和1分别作为起始的层数。
2.分别对上面的情况进行观察对比:
请添加图片描述

节点的度:一个节点含有的子树的个i树就是度。(A度是6)。
叶节点或终端节点:度为0的节点(只有一个前驱和一个后继)。
非终端节点或分支节点:度不为0的节点。
双亲节点或父节点:一个节点有自己的子节点,这个节点就是他子节点的父节点。
孩子节点或子节点:一个节点的子树的根节点,就是他的孩子节点。
兄弟节点:有相同父节点的子节点,这些子节点之间的关系就是兄弟关系。
树的度:对于一个树,找到一个节点有这这颗树最大的度(代表这个树的度)。
节点的层次:前面补充了:从1开始。
树的高度或深度:树的最大层次。
堂兄弟节点:双亲节点在同一层的节点之间被称为堂兄弟。
节点的祖先:从这个节点到我们1层的根节点中路径上的所有节点。
子孙:从这个节点下面的所有节点都是子孙。
森林:由m个不相交的树称为集合。

3.树的表示:

请添加图片描述

1.孩子兄弟表示法在这里是最常用的一个:
在这里插入图片描述
相当于把一个一个链表的头使有第一个孩子节点的方法连接在一起多个链表,构成了这样的逻辑结构。

二.二叉树的概念和结构:

1.概念:

一颗二叉树是一个节点的有限集合(对于集合来说)。
1.集合为空(根节点没有子树):
2.由一个根节点加上两颗(二叉树)子树构成的集合:

在这里插入图片描述

1.二叉树不存在度大于二的节点。
2.二插树的左右子树有次序之分,因此二叉树是一个有序树。
3.二叉树的复合(由下面几种复合而成:)。
请添加图片描述

2.两种特殊的二叉树:

1.完全二叉树:

一个二叉树每一层的节点都达到了最大,这个二叉树就是满二叉树。
计数节点个数,观察发现一个二叉树(层数为k)的节点个数为2^k-1.
通过等比数列的求和公式计算。

2.满二叉树:

完全二叉树是一种特殊的满二叉树(假设二叉树有K层)
1.要求二叉树的前面的K-1层必须是满的。
2.第K层必须要有一个节点到满层的一个范围。
3.总结:[2 ^ k-1(-1+1) 2^k-1 ]

3.二叉树的性质:

  1. 若规定根节点的层数为1,则一棵非空二叉树的第i层上最多有2^(h-1) 个结点.
  2. 若规定根节点的层数为1,则深度为h的二叉树的最大结点数是 2^h - 1.
  3. 对任何一棵二叉树, 如果度为0其叶结点个数为n0 , 度为2的分支结点个数为n2 ,则有n0 = n2+1
  4. 若规定根节点的层数为1,具有n个结点的满二叉树的深度,h=log(n+1) . (ps:log(n+1) 是log以2为底,n+1为对数)
  5. 对于具有n个结点的完全二叉树,如果按照从上至下从左至右的数组顺序对所有节点从0开始编号,则对于序号为i的结点有:
  6. 若i>0,i位置节点的双亲序号:(i-1)/2;i=0,i为根节点编号,无双亲节点
  7. 若2i+1<n,左孩子序号:2i+1,2i+1>=n否则无左孩子
  8. 若2i+2<n,右孩子序号:2i+2,2i+2>=n否则无右孩子

题目一:

1 某二叉树共有 399 个结点,其中有 199 个度为 2 的结点,则该二叉树中的叶子结点数为( B)
A 不存在这样的二叉树
B 200
C 198
D 199
在这里插入图片描述

题目二:

2.下列数据结构中,不适合采用顺序存储结构的是( A)
A 非完全二叉树
B 堆
C 队列
D 栈

题目三:

3.在具有 2n 个结点的完全二叉树中,叶子结点个数为( )
A n
B n+1
C n-1
D n/2

请添加图片描述

题目四:

4.一棵完全二叉树的节点数位为531个,那么这棵树的高度为( B)
A 11
B 10
C 8
D 12

请添加图片描述

题目五:

5.一个具有767个节点的完全二叉树,其叶子节点个数为(B)
A 383
B 384
C 385
D 386

4.二叉树的存储结构:

二叉树可以通过两种形式去存储数据(顺序结构:链式结构)

1.顺序存储:
顺序结构就是拿数组去存储数据,这样的结构只适合用来存储完全二叉树。
如果二叉树种间存在一个节点只连接一个节点的情况会导致数组结构的问题:
1:数组下标为0的去存储我们的根节点:
2.从左到右依次存储:
3.子和父节点的下标计算:

leftchild=parent2+1
rightchild=parent
2+2
parent=(child-1)/2


如图:
请添加图片描述

三.二叉树的顺序存储结构和实现:

1.二叉树的顺序结构:

普通的二叉树是不适合用数组来存储的,因为可能会存在大量的空间浪费。而完全二叉树更适合使用顺序结构存储。现实中我们通常把堆(一种二叉树)使用顺序结构的数组来存储,需要注意的是这里的堆和操作系统虚拟进程地址空间中的堆是两回事,一个是数据结构,一个是操作系统中管理内存的一块区域分段。

2.堆的概念和结构:

如果有一个数据的一维数组K={k1,k2,k3,k4,k5……kn};我们把这个数组按照完全二叉树去构建一个逻辑结构,如果一维数组中满足(堆适合使用堆去存储):

ki<=k2i+1ork2i+2 —>小堆
ki>=k2i+1ork2i+2---->大堆

补充:
1.小堆的根是这个集合中最小的值:
2.堆的应用:
–1.topk问题(取排行榜的前面数据)
–2.堆排序O(n*logn)

1.插入数据

1-1.一个一个数据的插入保证每一个插入之后变成堆的结构都是一个大堆或者小堆。所以我们需要一个向上调整算法,新插入的数据需要和前面的比较(以下的举例都是小堆)
在这里插入图片描述
1-2:时间复杂度:
请添加图片描述

//3-1:进行向上调整:
void AdjustHeapUp(struct Heap* hp)
{
	assert(hp);
	//排一个升序(空复是N)(建立一个小堆)
	//找父节点:parent=child-1/2;
	int child = (hp->size) - 1;
	int parent = (child - 1) / 2;

	//向上调整如何结束:
	while (child>0)
	{
		//进行单次的调整:
		if (hp->str[child] < hp->str[parent])
		{
			swap(&hp->str[child], &hp->str[parent]);
		}
		else
		{
			break;
		}
		//向上调整数据的更新:
		child = parent;
		parent = (child - 1) / 2;
	}
}
//3.插入数据
void HeapPush(struct Heap* hp, HeapData x)
{
	assert(hp);
	//边插入数据边调整:
	
	//1.开始的时候没有开辟空间://2.后续的增容:
	if (hp->size == hp->capacity)
	{
		hp->capacity = (hp->str == NULL ? 4 : hp->capacity * 2);
		HeapData* tmp = (HeapData*)realloc(hp->str, sizeof(HeapData) * hp->capacity);
		if (tmp == NULL)
		{
			perror("realloc filad");
			exit(-1);
		}

		hp->str = tmp;
	}
	//2.插入数据:
	hp->str[hp->size] = x;
	hp->size++;

	//3进行向上调整:
	AdjustHeapUp(hp);
}

2获取堆顶数据(数据交换和数据减少)

1.获取堆顶数据:
2.交换堆顶数据和最后一个数据:
3.再减少堆中的一个数据:
4.向下调整(数据交换之后需要保持小堆)

时间复杂度的计算:
请添加图片描述

//4.获取(堆顶)数据
HeapData heapGetTop(struct Heap* hp)
{
	//不可以指针为空,或者没有数据:
	assert(hp);
	assert(hp->size != 0);
	//保存一下数据:
	HeapData n= hp->str[0];

	//交换:
	int tmp = (hp->size)-1;
	swap(&hp->str[0], &hp->str[tmp]);
	return n;
}

//5-1:向下调整:
void AdjustHeapDown(struct Heap* hp)
{
	assert(hp);

	int parent = 0;
	int child = (parent * 2) + 1;

	while (child <= hp->size-1)
	{
		//不知道左右节点哪一个小假设:
		//child+1 有可能会越界
		if ((child + 1) < hp->size)
		{
			hp->str[child] < hp->str[child + 1] ? child : child++;

			if (hp->str[child] < hp->str[parent])
			{
				swap(&hp->str[child], &hp->str[parent]);
			}

			parent = child;
			child = (parent * 2) + 1;
		}
		else
		{
			break;
		}
	}
}

//5.删除数据:
void Heappop(struct Heap* hp)
{
	assert(hp);
	assert(hp->size != 0);

	//1.减去最后一个:
	hp->size--;

	//2.向下调整,变回小堆:
	AdjustHeapDown(hp);
}

3.堆的代码实现:

#pragma once

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

typedef int HeapData;

//堆的结构
struct Heap {
	HeapData* str;
	int size;
	int capacity;
}Hp;

//初始化:
void HeapInit(struct Heap* hp);
//销毁:
void HeapDestory(struct Heap* hp);
//插入数据
void HeapPush(struct Heap* hp, HeapData x);
//获取(堆顶)数据
HeapData heapGetTop(struct Heap* hp);
//删除数据:
void Heappop(struct Heap* hp);
//打印一下堆:
void Heapprint(struct Heap* hp);
//判断堆是否为空:
bool ispowe(struct Heap* hp);


#define _CRT_SECURE_NO_WARNINGS 1

#include"heap.h"

//1.初始化:
void HeapInit(struct Heap* hp)
{
	//防止为空指针:
	assert(hp);
	//不想在初始化的时候开辟空间数据:
	hp->str = NULL;
	hp->capacity = 0;
	hp->size = 0;
}

//2.销毁:
void HeapDestory(struct Heap* hp)
{
	//防止为空指针:
	assert(hp);

	free(hp->str);
	hp->str = NULL;
	hp->capacity = 0;
	hp->size = 0;
}
//3-1-1:交换函数:
void swap(HeapData* a, HeapData* b)
{
	HeapData tmp = 0;

	tmp = *a;
	*a = *b;
	*b = tmp;
}

//3-1:进行向上调整:
void AdjustHeapUp(struct Heap* hp)
{
	assert(hp);
	//排一个升序(空复是N)(建立一个小堆)
	//找父节点:parent=child-1/2;
	int child = (hp->size) - 1;
	int parent = (child - 1) / 2;

	//向上调整如何结束:
	while (child>0)
	{
		//进行单次的调整:
		if (hp->str[child] < hp->str[parent])
		{
			swap(&hp->str[child], &hp->str[parent]);
		}
		else
		{
			break;
		}
		//向上调整数据的更新:
		child = parent;
		parent = (child - 1) / 2;
	}
}
//3.插入数据
void HeapPush(struct Heap* hp, HeapData x)
{
	assert(hp);
	//边插入数据边调整:
	
	//1.开始的时候没有开辟空间://2.后续的增容:
	if (hp->size == hp->capacity)
	{
		hp->capacity = (hp->str == NULL ? 4 : hp->capacity * 2);
		HeapData* tmp = (HeapData*)realloc(hp->str, sizeof(HeapData) * hp->capacity);
		if (tmp == NULL)
		{
			perror("realloc filad");
			exit(-1);
		}

		hp->str = tmp;
	}
	//2.插入数据:
	hp->str[hp->size] = x;
	hp->size++;

	//3进行向上调整:
	AdjustHeapUp(hp);
}

//4.获取(堆顶)数据
HeapData heapGetTop(struct Heap* hp)
{
	//不可以指针为空,或者没有数据:
	assert(hp);
	assert(hp->size != 0);
	//保存一下数据:
	HeapData n= hp->str[0];

	//交换:
	int tmp = (hp->size)-1;
	swap(&hp->str[0], &hp->str[tmp]);
	return n;
}

//5-1:向下调整:
void AdjustHeapDown(struct Heap* hp)
{
	assert(hp);

	int parent = 0;
	int child = (parent * 2) + 1;

	while (child <= hp->size-1)
	{
		//不知道左右节点哪一个小假设:
		//child+1 有可能会越界
		if ((child + 1) < hp->size)
		{
			hp->str[child] < hp->str[child + 1] ? child : child++;

			if (hp->str[child] < hp->str[parent])
			{
				swap(&hp->str[child], &hp->str[parent]);
			}

			parent = child;
			child = (parent * 2) + 1;
		}
		else
		{
			break;
		}
	}
}

//5.删除数据:
void Heappop(struct Heap* hp)
{
	assert(hp);
	assert(hp->size != 0);

	//1.减去最后一个:
	hp->size--;

	//2.向下调整,变回小堆:
	AdjustHeapDown(hp);
}


//打印一下堆:
void Heapprint(struct Heap* hp)
{
	assert(hp);
	for (int i = 0; i < hp->size; i++)
	{
		printf("%d ", hp->str[i]);
	}
	printf("\n");
}

//判断堆是否为空:
bool ispowe(struct Heap* hp)
{
	assert(hp);

	if (hp->size == 0)
	{
		return false;
	}
	return true;
}


#include"heap.h"

int main()
{
	HeapData arr[] = { 2,3,1,8,10,5,12,19,8 };
	int n = sizeof(arr) / sizeof(arr[0]);
	//初始化:
	struct Heap hp;
	HeapInit(&hp);
	for (int i = 0; i < n; i++)
	{
		HeapPush(&hp, arr[i]);
	}
	//打印看一下小堆:
	Heapprint(&hp);
	//进行升序打印

	for (int j = 0; j < n; j++)
	{
		printf("%d ", heapGetTop(&hp));
		//删除数据:
		Heappop(&hp);
	}
	//Heapprint(&hp);
	HeapDestory(&hp);
	return 0;
}

四.堆的应用:

1.堆排序:

1.建堆:

*升序:建立大堆
*降序:建立小堆

2.利用堆的删除思想去进行排序(这是一种原地排序)

1.建堆和堆的删除都使用了向下调整的算法只要会向下调整就可以拿捏堆排序:

2.排序:
1.给函数传一个数组。
2.函数原地的去排序。
3.把数组的内容排成一个需要的序:
4.(这是一种原地排序)

问题一(建堆):
1.开始顺序的调整:
从后往前第一个非叶子节点开始向下调整:请添加图片描述

#include"heap.h"

//3-1-1:交换函数:
void swapQ(HeapData* a, HeapData* b)
{
	HeapData tmp = 0;

	tmp = *a;
	*a = *b;
	*b = tmp;
}

//5-1:向下调整:
void AdjustQsortHeapDown(HeapData* str,int n)
{
	assert(str);

	while (n>=1)
	{
		//arr是数组,n是元素个数:
		int parent = (n - 1 -1)/2;
		int child = parent * 2 + 1;

		//孩子作为根的时候说明建堆完成:
		//child的范围:
		while (child <= n-1)
		{
			//不知道左右节点哪一个大:假设:
			//child+1 有可能会越界
			if (((child) <= n - 1) )
			{
				//产生数组越界问题:
				if (child + 1 < n)
				{
					(str[child] > str[child + 1] ? child : child++);
				}


				if (str[child] > str[parent])
				{
					swapQ(&str[child], &str[parent]);
				}

				parent = child;
				child = (parent * 2) + 1;
			}
			else
			{
				break;
			}
		}

		n--;
	}

	
}

问题二(位置的调整)
1.把堆顶和堆尾进行交换:
2.减少堆的数据个数减少范围:
3.再一次调整重复之前的操作:

void HeapQsort(HeapData* arr,int n)
{
	while (n)
	{
		//向下调整
		AdjustQsortHeapDown(arr, n);
		//进行首尾的交换,把大的放到应该的位置。
		swapQ(&arr[0], &arr[n - 1]);
		n--;
	}
}

3.整体代码:

#include"heap.h"

//3-1-1:交换函数:
void swapQ(HeapData* a, HeapData* b)
{
	HeapData tmp = 0;

	tmp = *a;
	*a = *b;
	*b = tmp;
}

//5-1:向下调整:
void AdjustQsortHeapDown(HeapData* str,int n)
{
	assert(str);

	while (n>=1)
	{
		//arr是数组,n是元素个数:
		int parent = (n - 1 -1)/2;
		int child = parent * 2 + 1;

		//孩子作为根的时候说明建堆完成:
		//child的范围:
		while (child <= n-1)
		{
			//不知道左右节点哪一个大:假设:
			//child+1 有可能会越界
			if (((child) <= n - 1) )
			{
				//产生数组越界问题:
				if (child + 1 < n)
				{
					(str[child] > str[child + 1] ? child : child++);
				}


				if (str[child] > str[parent])
				{
					swapQ(&str[child], &str[parent]);
				}

				parent = child;
				child = (parent * 2) + 1;
			}
			else
			{
				break;
			}
		}

		n--;
	}
}

//2.堆排序的功能函数:
void HeapQsort(HeapData* arr,int n)
{
	while (n)
	{
		//向下调整
		AdjustQsortHeapDown(arr, n);
		//进行首尾的交换,把大的放到应该的位置。
		swapQ(&arr[0], &arr[n - 1]);
		n--;
	}
}


2.TOPK问题:

TOP-K问题:即求数据结合中前K个最大的元素或者最小的元素,一般情况下数据量都比较大。
比如:专业前10名、世界500强、富豪榜、游戏中前100的活跃玩家等。
对于Top-K问题,能想到的最简单直接的方式就是排序,但是:如果数据量非常大,排序就不太可取了(可能数据都不能一下子全部加载到内存中)。最佳的方式就是用堆来解决,基本思路如下:

  1. 用数据集合中前K个元素来建堆
    2.前k个最大的元素,则建小堆
    3.前k个最小的元素,则建大堆
  2. 用剩余的N-K个元素依次与堆顶元素来比较,不满足则替换堆顶元素
    将剩余N-K个元素依次与堆顶元素比完之后,堆中剩余的K个元素就是所求的前K个最小或者最大的元素。
int main()
{
	/*srand((unsigned int)time(NULL));

	1.打开文件用来写数据:
	FILE* pf = fopen("data.txt", "w");
	if (pf == NULL)
	{
		perror("fopen filed");
		exit(-1);
	}
	int num = 100000;
	while (num--)
	{
		2.写数据:
		int n = rand() % 1000000;
		fprintf(pf, "%d\n", n);
	}
	关闭数据:
	fclose(pf);*/



	//1.打开文件用来写数据:
	FILE* pf = fopen("data.txt", "r");
	if (pf == NULL)
	{
		perror("fopen filed");
		exit(-1);
	}

	//2.数据写到堆中:
	int num = 100000;
	//3.前面k个建堆:
	int k = 10;
	int* arr = (int*)malloc(sizeof(int) * k);
	if (arr == NULL)
	{
		perror("malloc file");
		exit(-1);
	}
	for(int i=0;i<k;i++)
	{
		int tmp = 0;
		fscanf(pf,"%d", &tmp);
		//插入法建堆:
		arr[i] = tmp;
		creatHeap(arr,i);
	}
	int number = num - k;
	
	//4.后面N-k个比较:
	for (int j = 0; j< number; j++)
	{
		int tp = 0;
		fscanf(pf, "%d", &tp);
		AdjustTOPtHeapDown(arr, k ,tp);
	}

	for (int a = 0; a < k; a++)
	{
		printf("%d ", arr[a]);
	}

	//关闭数据:
	fclose(pf);
	return 0;
}

1.插入建堆:

//1.插入法建堆:
void creatHeap(HeapData* arr, int k)
{
	assert(arr);
	//排一个升序(空复是N)(建立一个小堆)
	//找父节点:parent=child-1/2;
	int child = k - 1;
	int parent = (child - 1) / 2;
	//向上调整如何结束:
	while (child > 0)
	{
		//进行单次的调整:
		if (arr[child] < arr[parent])
		{
			swapQ(&arr[child], &arr[parent]);
		}
		else
		{
			break;
		}
		//向上调整数据的更新:
		child = parent;
		parent = (child - 1) / 2;
	}
}

2.比较插入第一给个(进行向下调整)

//2.向下调整:
void AdjustTOPtHeapDown(HeapData* arr, int n, HeapData tmp)
{
	assert(arr);
	if (tmp > arr[0])
	{
		arr[0] = tmp;
		//arr是数组,n是元素个数:
		int parent = 0;
		int child = parent * 2 + 1;

		//孩子作为根的时候说明建堆完成:
		//child的范围:
		while (child <= n - 1)
		{
			if (child <= n - 1)
			{
				if (child + 1 < n)
				{
					(arr[child] < arr[child + 1] ? child : child++);
				}

				if (arr[child] < arr[parent])
				{
					swapQ(&arr[child], &arr[parent]);
				}

				parent = child;
				child = (parent * 2) + 1;
			}

			else
			{
				break;
			}
		}
	}
}

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

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

相关文章

一个CVE漏洞预警知识库

CVE 0x01 免责声明 本仓库所涉及的技术、思路和工具仅供安全技术研究&#xff0c;任何人不得将其用于非授权渗透测试&#xff0c;不得将其用于非法用途和盈利&#xff0c;否则后果自行承担。 无exp/poc&#xff0c;部分包含修复方案 0x02 项目导航 2022.12 CVE-2022-3328&a…

管理类联考——数学——汇总篇——知识点突破——应用题——工程

⛲️ 工程问题为常考题型&#xff0c;命题频率相对较高&#xff0c;题型难度属于中等&#xff0c;核心在于效率的有关计算。 1.工作量s、工作效率v、工作时间t三者的关系&#xff1a; 工作量 工作效率 工作时间&#xff08; s v t &#xff09; 工作量工作效率工作时间&am…

第一章 数据库SQL-Server(及安装管理详细)

❄️作者介绍&#xff1a;奇妙的大歪❄️ &#x1f380;个人名言&#xff1a;但行前路&#xff0c;不负韶华&#xff01;&#x1f380; &#x1f43d;个人简介&#xff1a;云计算网络运维专业人员&#x1f43d; 前言 21 世纪&#xff0c;人类迈入了“信息爆炸时代”&#xff0c…

Java计算机毕业设计基于SpringBoot音乐网项目(附源码讲解)

目录 用户端 第一步&#xff1a;用户注册 第二步&#xff1a;用户登录 第三步&#xff1a;平台首页&#xff08;可查看平台歌单、歌手详细信息操作等等&#xff09; 第四步&#xff1a;查看歌单 第五步&#xff1a;歌单详情操作&#xff08;歌单评价、歌单歌曲下载、歌单…

2021-2023顶会190+篇ViT高分论文总结(通用ViT、高效ViT、训练transformer、卷积transformer等)

今天分享近三年&#xff08;2021-2023&#xff09;各大顶会中的视觉Transformer论文&#xff0c;有190篇&#xff0c;涵盖通用ViT、高效ViT、训练transformer、卷积transformer等细分领域。 全部论文原文及开源代码文末直接领取 General Vision Transformer&#xff08;通用V…

Asp.Net 6.0集成 Log4Net

环境 需要安装NuGet包&#xff0c;明细如下&#xff1a; log4netMicrosoft.Extensions.Logging.Log4Net.AspNetCore 配置文件 文件名称 log4net.config&#xff0c;默认可以放在与启动类Program.cs同级目录下 <?xml version"1.0" encoding"utf-8"…

腾讯云服务器无法使用 xftp 上传文件

现象&#xff1a;xftp 连接腾讯云服务器后不能在可视化界面创建文件&#xff0c;也不能上传文件 解决办法&#xff1a; 一、防火墙开放 21 端口 二、使用 xshell 登陆云服务器&#xff0c;默认登陆为 ubuntu 用户&#xff0c;需要切到 root&#xff0c;只有 root 用户才有 FTP…

kubernetes-operator开发教程(基于kubebuilder脚手架)

1、Operator介绍 Operator是什么&#xff1f; Kubernetes Operator是一个自定义控制器&#xff0c;用于通过自动化操作来管理复杂应用或服务。 实现原理是什么&#xff1f; Kubernetes Operator的实现原理基于自定义控制器&#xff08;Controller&#xff09;和自定义资源定义…

conda常用命令及问题解决-创建虚拟环境

好久没写博文了&#xff0c;感觉在学习的过程中还是要注意积累与分享&#xff0c;这样利人利己。 conda包清理&#xff0c;许多无用的包是很占用空间的 conda clean -p //删除没有用的包 conda clean -y -all //删除pkgs目录下所有的无用安装包及cacheconda创建虚拟环境…

机器学习入门教学——标签编码、序号编码、独热编码

1、前言 在机器学习过程中&#xff0c;我们经常需要对特征进行分类&#xff0c;例如&#xff1a;性别有男、女&#xff0c;国籍有中国、英国、美国等&#xff0c;种族有黄、白、黑。 但是分类器并不能直接对字符型数据进行分类&#xff0c;所以我们需要先对数据进行处理。如果…

索引失效有哪些?

在工作中&#xff0c;如果我们想要提高一条语句的查询速度&#xff0c;通常都会想对字段建立索引。 但是索引不是万能的。建立了索引&#xff0c;并不意味着任何查询语句都能走索引扫描。 稍不注意&#xff0c;可能查询语句就会导致索引失效&#xff0c;从而走了全表扫描&…

美业创新之路:广告电商模式让你的品牌脱颖而出

美业是一个巨大的市场&#xff0c;但也面临着激烈的竞争和消费者的多样化需求。如何在这个市场中脱颖而出&#xff0c;实现品牌的增长和盈利呢&#xff1f;答案就是广告电商模式。 广告电商模式是一种结合了社交电商和广告分佣的新型电商模式&#xff0c;它可以让消费者在购物的…

几种研发管理流程

一、CMMI 1.初始阶段 软件过程混乱&#xff0c;有时甚至混乱。几乎没有流程的定义。成功取决于个人的努力。管理是被动的。 2.可重复/可管理 建立了基本的项目管理流程来跟踪成本&#xff0c;进度和功能特征。已经建立了必要的过程规程&#xff0c;以便能够重复先前类似应用…

RPC框架核心技术

一、RPC框架整体架构 RPC Client && RPC Server RPC Client 1、动态代理&#xff0c;根据lookUp信息&#xff08;接口-实现-方法&#xff09;动态创建出代理类&#xff0c;&#xff08;创建代理类RPC服务端的目标接口&#xff09;。即Lookup为远端目标接口地址&#…

localStorage是什么?有哪些特点?

localStorage的主要作用是本地存储&#xff0c;它可以将数据按照键值对的方式保存在浏览器中&#xff0c;直到用户或者脚本主动清除数据&#xff0c;否则该数据会一直存在。也就是说&#xff0c;使用了本地存储的数据将被持久化保存。 localStorage与sessionStorage的区别是存…

Cpolar+Tipas:在Ubuntu上搭建私人问答网站,为您提供专业的问题解答

文章目录 前言2.Tipask网站搭建2.1 Tipask网站下载和安装2.2 Tipask网页测试2.3 cpolar的安装和注册 3. 本地网页发布3.1 Cpolar临时数据隧道3.2 Cpolar稳定隧道&#xff08;云端设置&#xff09;3.3 Cpolar稳定隧道&#xff08;本地设置&#xff09; 4. 公网访问测试5. 结语 前…

什么是JavaScript中的严格模式(strict mode)?应用场景是什么?

聚沙成塔每天进步一点点 ⭐ 专栏简介⭐ 严格模式&#xff08;Strict Mode&#xff09;&#xff1a;⭐ 使用场景⭐ 写在最后 ⭐ 专栏简介 前端入门之旅&#xff1a;探索Web开发的奇妙世界 记得点击上方或者右侧链接订阅本专栏哦 几何带你启航前端之旅 欢迎来到前端入门之旅&…

shell脚本指令:for循环、函数、数组、grep等指令的使用

1、实现一个对数组求和的函数&#xff0c;数组通过实参传递给函数 2、写一个函数&#xff0c;输出当前用户的uid和gid 并使用变量接收结果 #!/bin/bash echo "请输入一个数组" read -a arr function add_arr() {var1${#arr[*]}for i in ${arr[*]} do((sumi))doner…

技术解码 | GB28181/SIP/SDP 协议--EasyGBS国标GB28181平台国标视频技术SIP解析

EasyGBS国标视频云服务是基于国标GB/T28181协议的视频能力平台&#xff0c;可实现的视频功能包括&#xff1a;实时监控直播、录像、检索与回看、语音对讲、云存储、告警、平台级联等功能。平台部署简单、可拓展性强&#xff0c;支持将接入的视频流进行全终端、全平台分发&#…

中国人民大学与加拿大女王大学金融硕士——人生总要逼自己一把

我们每个人都是一个独特而丰富的个体&#xff0c;身上蕴藏着各种潜力和可能性。要不断去开发自己的潜能&#xff0c;不断学习和提升自己的知识和技能&#xff0c;保持对新知识和趋势的敏感。想要在职场上走得更远&#xff0c;就要逼自己一把&#xff0c;在职继续攻读硕士学位是…