数据结构与算法(持续更新)

news2024/10/6 10:29:51

线性表

单链表

单链表的定义
由于顺序表的插入删除操作需要移动大量的元素,影响了运行效率,因此引入了线性表的链式存储——单链表。单链表通过一组任意的存储单元来存储线性表中的数据元素,不需要使用地址连续的存储单元,因此它不要求在逻辑上相邻的两个元素在物理位置上也相邻。

单链表的特点
1.单链表不要求逻辑上相邻的两个元素在物理位置上也相邻,因此不需要连续的存储空间。
2.单链表是非随机的存储结构,即不能直接找到表中某个特定的结点。查找某个特定的结点时,需要从表头开始遍历,依次查找。

**单链表操作**

#include<iostream>
using namespace std;

typedef struct LNode{
	int data;
	struct LNode *next;
}LNode,*LinkList;

//初始化 
void InitList(LinkList &L){
	L=(LNode *)malloc(sizeof(LinkList));
	L->next=NULL;
}

//头插法建表
LinkList HeadInsert(LinkList &L){
	InitList(L);
	int x;
	while(cin>>x){
		LNode *s=(LNode *)malloc(sizeof(LNode));
		s->data=x;
		s->next=L->next;
		L->next=s;
	}
	return L;
}

//尾插法建表
LinkList TailInsert(LinkList &L){
	InitList(L);
	LNode *s,*r=L;
	int x;
	while(cin>>x){
		s=(LNode *)malloc(sizeof(LNode));
		s->data=x;
		r->next=s;
		r=s;
	}
	r->next=NULL;
	return L;
} 

//输出表中元素
void PrintList(LinkList L){
	LNode *p=L->next;
	while(p!=NULL){
		cout<<p->data<<" ";
		p=p->next;
	}
} 

//求单链表的长度
int Length(LinkList L){
    LNode *p = L->next;
    int len = 0;
    while(p!=NULL){
        len++;
        p = p->next;
    }
    return len;
}

//按值查找:查找x在L中的位置
LNode *LocateElem(LinkList L, int x){
    LNode *p = L->next;
    while(p!=NULL&&p->data!=x){
        p = p->next;
    }
    return p;
}

//按位查找:查找在单链表L中第i个位置的结点
LNode *GetElem(LinkList L, int i){
    int j=1;
    LNode *p = L->next;
    if(i==0){
		return L;
	}
    if(i<1){
		return NULL;
	}
    while(p!=NULL&&j<i){
        p = p->next;
        j++;
    }
    return p;
}

//判空操作
void Empty(LinkList L){
    if(L->next == NULL){
        cout<<"L is null"<<endl;
    }else{
        cout<<"L is not null"<<endl;
    }
}

//将x插入到单链表L的第i个位置上
void Insert(LinkList &L, int i, int x){
    LNode *p = GetElem(L,i-1);
    LNode *s = (LNode *)malloc(sizeof(LNode));
    s->data = x;
    s->next = p->next;
    p->next = s;
}

//删除操作:将单链表中的第i个结点删除
void Delete(LinkList &L, int i){
	if(i<0||i>Length(L)){
		cout<<"数据有误"; 
		return ;
	}
    LNode *p = GetElem(L,i-1);
    LNode *q = p->next;
    p->next = q->next;
    free(q);
}

int main(){
	**自定义补充**
	return 0;
}

双链表

循环链表

栈、队列、数组

查找

排序

排序算法可以分为内部排序和外部排序,其中内部排序有:插入排序(直接插入排序、折半插入排序、希尔排序)、交换排序(冒泡排序、快速排序)、选择排序(简单选择排序、堆排序)、归并排序、基数排序;外部排序有:多路归并排序。

插入排序

插入排序是一种简单直观的排序方法,其基本思想是每次将一个待排序的记录按其关键字大小插入前面已排好序的子序列,直到全部记录插入完成。由插入排序的思想可以引申出三个重要的排序算法:直接插入排序、折半插入排序和希尔排序。

直接插入排序

要将元素 L(i)插入已有序的子序列 L[1…i-1],需要执行以下操作(为避免混,下面用L[ ]表示一个表,而用 L( )表示一个元素):
1)查找出L(i)在L[l…i-1]中的插入位置k。
2)将L[k…i-1]中的所有元素依次后移一个位置。
3)将L(i)复制到L(k)。

#include<iostream>
using namespace std;

void InsertSort(int a[],int len){
	int temp,i,j;
	for(i=1;i<len;i++){
		if(a[i]<a[i-1]){
			temp=a[i];
			for(j=i-1;temp<a[j];j--){
				a[j+1]=a[j];	
			}
			a[j+1]=temp;
		}
	}
} 

int main(){
	int a[]={1,3,4,2,6,5,9,8,7};
	int l=sizeof(a)/sizeof(int);
	InsertSort(a,l);
	for(int i=0;i<l;i++){
		cout<<a[i]<<" ";
	} 
	return 0;
}

时间复杂度:O(n^2) 最好情况下:O(n)
空间复杂度:O(1)
稳定性:由于每次插入元素时总是从后向前先比较再移动,所以不会出现相同元素相对位置发生变化的情况,即直接插入排序是一个稳定的排序方法。
适用性:直接插入排序算法适用于顺序存储和链式存储的线性表。为链式存储时,可以从前往后查找指定元素的位置。

折半插入排序

从直接插入排序算法中,不难看出每趟插入的过程中都进行了两项工作:1.从前面的有序子表中查找出待插入元素应该被插入的位置;2.给插入位置腾出空间,将待插入元素复制到表中的插入位置。注意到在该算法中,总是边比较边移动元素。下面将比较和移动操作分离,即先折半查找出元素的待插入位置,然后统一地移动待插入位置之后的所有元素。当排序表为顺序表时,可以对直接插入排序算法做如下改进:由于是顺序存储的线性表,所以查找有序子表时可以用折半查找来实现。确定待插入位置后,就可统一地向后移动元素。

#include<iostream>
using namespace std;

void InsertSort(int a[],int len){
	int temp,low,high,mid;
	for(int i=1;i<len;i++){
		temp=a[i];
		low=0,high=i-1;
		while(low<=high){
			mid=(low+high)/2;
			if(a[mid]>temp){
				high=mid-1;
			}else{
				low=mid+1;
			}
		}
		for(int j=i-1;j>=high+1;j--){
			a[j+1]=a[j];
		}
		a[high+1]=temp;
	}
}

int main(){
	int a[]={1,3,4,2,6,5,9,8,7};
	int l=sizeof(a)/sizeof(int);
	InsertSort(a,l);
	for(int i=0;i<l;i++){
		cout<<a[i]<<" ";
	}
	return 0;
}

从上述算法中,不难看出折半插入排序仅减少了比较元素的次数,约为 O(nlogn),该比较次数与待排序表的初始状态无关,仅取决于表中的元素个数n;而元素的移动次数并未改变,它依赖于待排序表的初始状态。因此,折半插入排序的时间复杂度仍为 O(n^2),但对于数据量不很大的排序表,折半插入排序往往能表现出很好的性能。折半插入排序是一种稳定的排序方法。

希尔排序

希尔排序的基本思想是:先将待排序表分割成若干形如L[i,i+d,i+2d,i+3d,…,i+kd]的“特殊”子表,即把相隔某个“增量”的记录组成一个子表,对各个子表分别进行直接插入排序,当整个表中的元素已呈“基本有序”时,再对全体记录进行一次直接插入排序。
希尔排序的过程如下:先取一个小于n 的步长 d1,把表中的全部记录分成d1组,所有距离为d1的倍数的记录放在同一组,在各组内进行直接插入排序;然后取第二个步长 d2<d1,重复上述过程,直到所取到的di=1,即所有记录已放在同一组中,再进行直接插入排序,由于此时已经具有较好的局部有序性,故可以很快得到最终结果。

#include<iostream>
using namespace std;

void InsertSort(int a[],int len){
	for(int d=len/2;d>=1;d=d/2){
		int temp,i,j;
		for(i=d+1;i<len;i++){
			if(a[i]<a[i-d]){
				temp=a[i];
				for(j=i-d;j>0&&temp<a[j];j-=d){
					a[j+d]=a[j];	
				}
				a[j+d]=temp;
			}
		}
	}
} 

int main(){
	int a[]={1,3,4,2,6,5,9,8,7};
	int l=sizeof(a)/sizeof(int);		
	InsertSort(a,l);
	for(int i=0;i<l;i++){
		cout<<a[i]<<" ";
	}
	return 0;
}

空间效率:仅使用了常数个辅助单元,因而空间复杂度为 O(1)。
时间效率:由于希尔排序的时间复杂度依赖于增量序列的函数,这涉及数学上尚未解决的难题,所以其时间复杂度分析比较困难。当n在某个特定范围时,希尔排序的时间复杂度约为O(n^1.3)。在最坏情况下希尔排序的时间复杂度为 O(n^2)。
稳定性:当相同关键字的记录被划分到不同的子表时,可能会改变它之间的相对次序,因此希尔排序是一种不稳定的排序方法。
适用性:希尔排序算法仅适用于线性表为顺序存储的情况。

交换排序

所谓交换,是指根据序列中两个元素关键字的比较结果来对换这两个记录在序列中的位置。基于交换的排序算法很多,主要有冒泡排序和快速排序。

冒泡排序

冒泡排序的基本思想是:从后往前(或从前往后)两两比较相邻元素的值,若为逆序(即A[i-1]>A[i]),则交换它们,直到序列比较完。我们称它为第一趟冒泡,结果是将最小的元素交换到待排序列的第一个位置(或将最大的元素交换到待排序列的最后一个位置),关键字最小的元素如气泡一般逐渐往上“漂浮”直至“水面”(或关键字最大的元素如石头一般下沉至水底)。下一趟冒泡时,前一趟确定的最小元素不再参与比较,每趟冒泡的结果是把序列中的最小元素(或最大元素)放到了序列的最终位置…这样最多做n-1趟冒泡就能把所有元素排好序。

#include<iostream>
using namespace std;

void BubbleSort(int a[],int len){
	for(int i=0;i<len-1;i++){
		for(int j=0;j<len-i;j++){
			if(a[j+1]<a[j]){
				swap(a[j+1],a[j]);
			}
		}
	}
} 

int main(){
	int a[]={1,3,4,2,6,5,9,8,7};
	int l=sizeof(a)/sizeof(int);		
	BubbleSort(a,l);
	for(int i=0;i<l;i++){
		cout<<a[i]<<" ";
	}
	return 0;
}

算法改进:由上述的示例(数组元素为:1,3,4,2,6,5,9,8,7)可知,其第二趟的结果(1,2,3,4,5,6,7,8,9)已经有序,后面再进行排序其实是重复动作。因此,当某一趟的结果已经有序时,表示所给序列已经有序,不必要再进行下一趟排序。

void BubbleSort(int a[],int len){
	for(int i=0;i<len-1;i++){
		bool flag=false; 
		for(int j=0;j<len-i;j++){
			if(a[j+1]<a[j]){
				swap(a[j+1],a[j]);
				flag=true;
			}
		}
		if(flag==false){
			return ;
		}
	}
} 

空间效率:仅使用了常数个辅助单元,因而空间复杂度为 O(1)。
时间效率:当初始序列有序时,显然第一趟冒泡后flag依然为false(本趟冒泡没有元素交换),从而直接跳出循环,比较次数为n-1,移动次数为0,从而最好情况下的时间复杂度为O(n);当初始序列为逆序时,需要进行n-1趟排序,第i趟排序要进行n-i次关键字的比较,而且每次比较后都必须移动元素3次来交换元素位置。这种情况下的时间复杂度为 O(n^2),其平均时间复杂度也为 O(n^2)。
稳定性:由于i>j且a[i]=a[j]时,不会发生交换,因此冒泡排序是一种稳定的排序方法。

快速排序

快速排序的基本思想是基于分治法的:在待排序表 L[l…n]中任取一个元素pivot作为枢轴(或基准,通常取首元素),通过一趟排序将待排序表划分为独立的两部分L[1…k-1]和L[k+l…n],使得L[l…k-1]中的所有元素小于pivot,L[k+l…n]中的所有元素大于等于pivot,则pivot放在了其最终位置 L(k)上,这个过程称为一趟快速排序(或一次划分)。然后分别递归地对两个子表重复上述过程,直至每部分内只有一个元素或空为止,即所有元素放在了其最终位置上。

#include<iostream>
using namespace std;

void QuickSort(int a[],int low,int high){
	int i=low,j=high,pivot=a[low];
	if(low>=high){
		return ;
	}
	while(i<j){
		while(a[j]>=pivot&&i<j){
			j--;
		}
		a[i]=a[j];
		while(a[i]<=pivot&&i<j){
			i++;
		}
		a[j]=a[i];
	}
	a[i]=pivot;
	QuickSort(a,low,i-1);
	QuickSort(a,i+1,high);
}

int main(){
	int a[]={1,3,4,2,6,5,9,8,7};
	int l=sizeof(a)/sizeof(int);		
	QuickSort(a,0,l-1);
	for(int i=0;i<l;i++){
		cout<<a[i]<<" ";
	}
	return 0;
}
**快速排序另一种写法:**

int Partition(int a[],int low,int high){
	int pivot=a[low];
	while(low<high){
		while(a[high]>pivot&&low<high){
			high--;
		}
		a[low]=a[high];
		while(a[low]<pivot&&low<high){
			low++;
		}
		a[high]=a[low];
	}
	a[low]=pivot;
	return low;
}

void QuickSort(int a[],int low,int high){
	if(low<high){
		int pivotpos = Partition(a,low,high);
		QuickSort(a,low,pivotpos-1);
		QuickSort(a,pivotpos+1,high);
	}
}

选择排序

选择排序的基本思想是:每一趟(如第i趟)在后面n-i+1(i=1,2,…,n-1)个待排序元素中选取关键字最小的元素,作为有序子序列的第i个元素,直到第n-1趟做完,待排序元素只剩下1个,就不用再选了。选择排序主要有简单选择排序和堆排序。

简单选择排序

简单选择排序算法的思想:假设排序表为L[1…n],第i趟排序即从L[i…n]中选择关键字最小的元素与L(i)交换,每一趟排序可以确定一个元素的最终位置,这样经过n-1趟排序就可使得整个排序表有序。

#include<iostream>
using namespace std;

void SelectSort(int a[],int len){
	for(int i=0;i<len-1;i++){
		int min=i;
		for(int j=i+1;j<len;j++){
			if(a[j]<a[min]){
				min=j;
			}
		}
		if(min!=i){
			swap(a[i],a[min]);
		}
	}
} 

int main(){
	int a[]={1,3,4,2,6,5,9,8,7};
	int l=sizeof(a)/sizeof(int);		
	SelectSort(a,l);
	for(int i=0;i<l;i++){
		cout<<a[i]<<" ";
	}
	return 0;
}

空间效率:仅使用常数个辅助单元,故空间效率为0(1)。
时间效率:从上述代码中不难看出,在简单选择排序过程中,元素移动的操作次数很少,不会超过3(n-1)次,最好的情况是移动0次,此时对应的表已经有序,但元素间比较的次数与序列的初始状态无关,始终是 n(n-1)/2 次,因此时间复杂度始终是 O(n^2)。
稳定性:在第i趟找到最小元素后,和第 i个元素交换,可能会导致第i个元素与其含有相同关键字元素的相对位置发生改变。例如,表L={2,2,1},经过一趟排序后L={1,2,2},最终排序序列也是L={1,2,2},显然,2与2的相对次序已发生变化。因此,简单选择排序是一种不稳定的排序方法。

堆排序

的定义如下,n个关键字序列L[1…n]称为堆,当且仅当该序列满足:
1.L(i)>=L(2i)且L(i)>=L(2i+1)或
2.L(i)<=L(2i)且L(i)<=(2i+1) (1 <= i <= n/2)
堆排序的思路很简单:首先将存放在L[1…n]中的n个元素建成初始堆,由于堆本身的特点(以大顶堆为例),堆顶元素就是最大值。输出堆顶元素后,通常将堆底元素送入堆顶,此时根结点已不满足大顶堆的性质,堆被破坏,将堆顶元素向下调整使其继续保持大顶堆的性质,再输出堆顶元素。如此重复,直到堆中仅剩一个元素为止。可见堆排序需要解决两个问题:1.如何将无序序列构造成初始堆?2.输出堆顶元素后,如何将剩余元素调整成新的堆?
堆排序的关键是构造初始堆。n个结点的完全二叉树,最后一个结点是第n/2个结点的孩子。对第n/2个结点为根的子树筛选(对于大根堆,若根结点的关键字小于左右孩子中关键字较大者,则交换),使该子树成为堆。之后向前依次对各结点(n/2-1,…,1)为根的子树进行筛选,看该结点值是否大于其左右子结点的值,若不大于,则将左右子结点中的较大值与之交换,交换后可能会破坏下一级的堆,于是继续采用上述方法构造下一级的堆,直到以该结点为根的子树构成堆为止。反复利用上述调整堆的方法建堆,直到根结点。

#include<iostream>
using namespace std;

void HeapAdjust(int a[],int k,int len){
	a[0]=a[k];
	for(int i=2*k;i<=len;i*=2){
		if(i<len&&a[i]<a[i+1]){
			i++;	
		}
		if(a[0]>=a[i]){
			break;
		}else{
			a[k]=a[i];
			k=i;
		}
	}
	a[k]=a[0];
}

void BuildMaxHeap(int a[],int len){
	for(int i=len/2;i>0;i--){
		HeapAdjust(a,i,len);
	}
}

void HeapSort(int a[],int len){
	BuildMaxHeap(a,len);
	for(int i=len;i>1;i--){
		swap(a[i],a[1]);
		HeapAdjust(a,1,i-1);
	}
} 

int main(){
	int b[]={1,3,4,2,6,5,9,8,7};
	int a[100],l=sizeof(b)/sizeof(int);
	for(int i=0;i<l;i++){
		a[i+1]=b[i];
	}
	HeapSort(a,l);
	for(int i=1;i<=l;i++){
		cout<<a[i]<<" ";
	}
	return 0;
} 

空间效率:仅使用了常数个辅助单元,所以空间复杂度为 O(1)。
时间效率:建堆时间为 O(n),之后有 n-1次向下调整操作,每次调整的时间复杂度为 O(h),故在最好、最坏和平均情况下,堆排序的时间复杂度为O(nlogn)。
稳定性:进行筛选时,有可能把后面相同关键字的元素调整到前面,所以堆排序算法是一种不稳定的排序方法。例如,表L={1,2,2},构造初始堆时可能将2交换到堆顶,此时L={2,1,2},最终排序序列为 L={1,2,2},显然,2与2的相对次序已发生变化。

归并排序

归并排序是比较稳定的排序方法。它的基本思想是把待排序的元素分解成两个规模大致相等的子序列。如果不易分解,将得到的子序列继续分解,直到子序列中包含的元素个数为1。因为单个元素的序列本身就是有序的,此时便可以进行合并,从而得到一个完整的有序序列。

分治算法
归并排序,其实就是一种分治算法,那么在了解归并排序之前,我们先来看看什么是分治算法。在算法设计中,我们引入分而治之的策略,称为分治算法,其本质就是将一个大规模的问题分解为若干个规模较小的相同子问题,分而治之。
分治算法解题
1.分解:将要解决的问题分解为若干个规模较小、相互独立、与原问题形式相同的子问题。
2.治理:求解各个子问题。由于各个子问题与原问题形式相同,只是规模较小而已,而当子问题划分得足够小时,就可以用简单的方法解决。
3.合并:按原问题的要求,将子问题的解逐层合并构成原问题的解。

归并排序解题步骤
步骤一:首先将待排序的元素分成大小大致相同的两个序列。
步骤二:再把子序列分成大小大致相同的两个子序列。
步骤三:如此下去,直到分解成一个元素停止,这时含有一个元素的子序列都是有序的。
步骤四:进行合并操作,将两个有序的子序列合并为一个有序序列,如此下去,直到所有的元素都合并为一个有序序列。

数据模拟,下面我将以序列(4,9,15,24,30,2,6,18,20)进行图解

1、初始化:i = low,j = mid+1,mid = (low+high)/2 ,申请一个辅助数组 b

在这里插入图片描述

int b[high-low+1];  
int i = low, j = mid + 1, k = 0;    

2、现在比较 a[i] 和 b[j],将较小的元素放在 b 数组中,相应的指针向后移动,直到 i > mid 或者 j>hight 时结束。

while (i <= mid && j <= high) {
	if (a[i] <= a[j]) {
		b[k++] = a[i++]; 
	} else {
		b[k++] = a[j++];
	}
}

进行第一次比较 a[i]=4 和 a[j]=2,将较小的元素 2 放入数组 b 中,j++,k++,如下图:

在这里插入图片描述

进行第二次比较 a[i]=4 和 a[j]=6,将较小的元素放 4 入数组 b 中,i++,k++,如下图:

在这里插入图片描述

进行第三次比较 a[i]=9 和 a[j]=6,将较小的元素放 6 入数组 b 中,j++,k++,如下图:

在这里插入图片描述

进行第四次比较 a[i]=9 和 a[j]=18,将较小的元素放 9 入数组 b 中,i++,k++,如下图:

在这里插入图片描述

进行第五次比较 a[i]=15 和 a[j]=18,将较小的元素放 15 入数组 b 中,i++,k++,如下图:

在这里插入图片描述

进行第六次比较 a[i]=24 和 a[j]=18,将较小的元素放 18 入数组 b 中,j++,k++,如下图:

在这里插入图片描述

进行第七次比较 a[i]=24 和 a[j]=20,将较小的元素放 20 入数组 b 中,j++,k++,如下图:

在这里插入图片描述

此时,j>hight 了,while循环结束,但 a 数组还剩下元素(i<mid)可直接放入 b 数组就可以了。如下图所示:

在这里插入图片描述

while (i <= mid){                         // j 序列结束,将剩余的 i 序列补充在 b 数组中 
	b[k++] = a[i++];
}
while (j <= high){                        // i 序列结束,将剩余的 j 序列补充在 b 数组中 
	b[k++] = a[j++];
}

现在比较 a[i] 和 b[j] ,将较小的元素放在 b 数组中,相应的指针向后移动,直到 i > mid 或者 j > hight 时结束。

while (i <= mid && j <= high) {
	if (a[i] <= a[j]) {
		b[k++] = a[i++]; 
	} else {
		b[k++] = a[j++];
	}
}

现在将 b 数组的元素赋值给 a 数组,再将 b 数组销毁,即可。

for (int i = low; i <= hight; i++)  {          //将 b 数组的值传递给数组 a
	a[i] = b[k++];
}
delete[]b;               // 辅助数组用完后,将其的空间进行释放(销毁)

3、递归的形式进行归并排序

void MergeSort(int a[ ],int low,int high){
	if(low<high){
		int mid=(low+high)/2;
		MergeSort(a,low,mid);
		MergeSort(a,mid+1,high);
		Merge(a,low,mid,high);
	}
}
**完整代码**
#include<iostream>
using namespace std;

void Merge(int a[],int low,int mid,int high){
	int *b=new int[high-low+1];               //用 new 申请一个辅助函数
	int i = low, j = mid + 1, k = 0;          // k为 b 数组的小标
	while (i <= mid && j <= high){
		if (a[i] <= a[j]){
			b[k++] = a[i++];                 //按从小到大存放在 b 数组里面
		}else{
			b[k++] = a[j++];
		}
	}
	while (i <= mid){                        // j 序列结束,将剩余的 i 序列补充在 b 数组中 
		b[k++] = a[i++];
	}
	while (j <= high){                       // i 序列结束,将剩余的 j 序列补充在 b 数组中 
		b[k++] = a[j++];
	}
	k = 0;                                   //从小标为 0 开始传送
	for (int i = low; i <= high; i++){       //将 b 数组的值传递给数组 a
		a[i] = b[k++];
	}
	delete []b;                              //销毁 
}

void MergeSort(int a[],int low,int high){
	if(low<high){
		int mid=(low+high)/2;
		MergeSort(a,low,mid);
		MergeSort(a,mid+1,high);
		Merge(a,low,mid,high);
	}
}

int main(){
	int a[]={1,3,4,2,6,5,9,8,7};
	int l=sizeof(a)/sizeof(int);
	MergeSort(a,0,l-1);
	for(int i=0;i<l;i++){
		cout<<a[i]<<" ";
	}
	return 0;
}

基数排序

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

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

相关文章

容易被忽视的CNN模型的感受野及其计算

感受野可能是卷积神经网络中最重要的概念之一&#xff0c;在学术中也被广泛关注。几乎所有的目标检测方法都围绕感受野来设计其模型结构。这篇文章通过可视化的方法来表达感受野的信息&#xff0c;并且提供一用于计算任何CNN网络每一层感受野的程序。 对于CNN相关的基础知识&a…

8 财政收入预测分析

第8章 财政收入预测分析 8.1 了解财政收入预测的背景与方法8.1.1 分析财政收入预测背景1、财政收入简介和需求2、财政收入预测数据基础情况3、财政收入预测分析目标 8.1.2 了解财政收入预测的方法8.1.3 熟悉财政收入预测的步骤与流程 8.2 分析财政收入数据特征的相关性8.2.1 了…

虚拟机模拟部署服务器

1、下载安装vmware 15 &#xff08;win7最高支持版&#xff09; 2、下载安装CentOS 配置2核2g&#xff08;最少&#xff09;磁盘100g&#xff08;不会实际占有&#xff09;选择时区配置分区 https://blog.csdn.net/qq_35363507/article/details/127390889 &#xff08;/boot …

MPLS VPN 配置

二 、知识点 MPLS VPN网络一般由运营商搭建&#xff0c;用于向不同的客户提供VPN服务&#xff0c;使得用户的路由和数据能够通过该网络进行传递&#xff0c;且不同的用户之间的路由和数据完全隔离&#xff0c;互不影响。MPLS VPN控制层面&#xff1a;通过VRF和RD隔离不同用户的…

matplotlib制图进阶版

需求&#xff1a;两个产品销量的可视化折线图 1、使用pandas读取数据 2、生成销售数量的折线图

深度图转化为点云

import numpy as np import cv2# 加载RGB图像和深度图像 rgb_image cv2.imread(rF:\Datasets\data\nyu2_test\00000_colors.png) # 假设你有一张RGB图像 depth_image cv2.imread(rF:\Datasets\data\nyu2_test\00000_depth.png, cv2.IMREAD_GRAYSCALE) # 假设你有一张灰度深…

计算机网络笔记 第三章数据链路层

3.1 数据链路层概述 数据链路层在网络体系结构中所处的地位 链路、数据链路和帧 链路 链路&#xff08;Link&#xff09;是指从一个节点到相邻节点的一段物理线路&#xff08;有线或无线&#xff09;&#xff0c;而中间没有任何其他的交换节点。 数据链路 (Data Link&#…

Python爬虫技术系列-03requests库案例-完善

Python爬虫技术系列-03requests库案例 参考1 Requests基本使用1.1 Requests库安装与使用1.1.1 Requests库安装1.1.2 Rrequests库介绍1.1.3 使用Requests一般分为三个步骤1.1.4 requests的公共方法 2 Requests库使用案例2.1 GET请求携带参数和headers2.2 POST请求&#xff0c;写…

no Go files in ...问题

golang项目&#xff0c;当我们微服务分模块开发时&#xff0c;习惯把main.go放在cmd目录下分模块放置&#xff0c;此时&#xff0c;我们在项目根目录下执行go test . 或go build . 时会报错“no Go files in ...”, 这是因为在.目录下找不到go程序&#xff0c;或者找不到程序入…

如何提升爬虫IP使用效率?精打细算的方法分享

在进行爬虫数据采集时&#xff0c;爬虫IP是不可或缺的工具。然而&#xff0c;爬虫IP的费用可能是一个爬虫项目的重要开支之一。为了帮助您节省爬虫IP经费&#xff0c;本文将分享一些经济高效的方法&#xff0c;让您在使用爬虫IP时更加节约成本&#xff0c;提高经济效益。 一、优…

Games104现代游戏引擎笔记 基础ai

游戏AI navigation(导航系统) 地图的表达形式&#xff0c; 寻路&#xff0c;路径优化 Map representation&#xff1a; 1.可行走区域&#xff08;物理碰撞&#xff0c;跳跃距离&#xff0c;攀爬高度&#xff09; 2.表达形式&#xff1a;waypoint networks(路点网络图)&#…

阿里云Alibaba Cloud Linux操作系统详细介绍_镜像常见问题解答

阿里云服务器操作系统Alibaba Cloud Linux镜像怎么样&#xff1f;可以代替CentOS吗&#xff1f;Alibaba Cloud Linux兼容性如何&#xff1f;有人维护吗&#xff1f;漏洞可以修复吗&#xff1f;Alibaba Cloud Linux完全兼容CentOS&#xff0c;并由阿里云官方免费提供长期维护。 …

JAVA-SpringBoot入门Demo用IDEA建立helloworld

使用编辑器IDEA做SpringBoot项目最近几年比较红红&#xff0c;作为JAVA语言翻身的技术&#xff0c;用户量激增。由于java平台原来的占有率&#xff0c;相比net core在某些方面更有优势。 我把本次我下载完成后Maven项目的过程记录下来了&#xff0c;仅供参考&#xff01; 安装J…

初识Java 13-1 异常

目录 概念 基本的异常 捕获异常 try块 异常处理程序&#xff08;catch&#xff09; 创建自己的异常 异常说明&#xff08;及检查型异常&#xff09; 捕获任何异常 多重捕捉 栈轨迹 重新抛出异常 异常链 本笔记参考自&#xff1a; 《On Java 中文版》 Java的基本哲学…

【Kotlin精简】第1章 基础类型

1 Kotlin基础类型 Kotlin中&#xff0c;我们可以调用任何变量的成员函数和属性&#xff0c;从这个角度来说&#xff0c;一切皆对象。某些类型可以有特殊的内部表现。例如&#xff1a;数字、字符和布尔型在运行时可以表现为基础类型&#xff08;primitivetypes&#xff09;。 …

九章云极DataCanvas公司完成D1轮融资!

近日&#xff0c;九章云极DataCanvas公司完成总融资额3亿元D1轮融资。中国电子集团旗下中电智慧基金、华民投、中国太平旗下太平创新、浙江东方旗下东方嘉富等央国企旗下投资机构&#xff0c;以及卓源资本等专注人工智能赛道的知名财务投资机构参与本轮融资。 九章云极DataCan…

dataframe保存excel格式比csv格式小很多很多

问题描述&#xff1a; 一个3万行的数据保存成csv大概10个G&#xff0c;但保存成excel格式只有100多M 原因分析&#xff1a; 因为xlsx 实际上就是 zip 压缩包&#xff0c;同时&#xff0c;如果有大量重复的数据&#xff0c;XLSX 会提取文本值&#xff0c;将其存储在查找表中&…

APP 备案公钥、签名 MD5获取方法。

一、IOS 系统获取 Bundle ID、平台公钥、签名 MD5 值的指引 获取 Bundle ID&#xff1a;使用 APP 对应的 IOS 开发者账号登录 Developer 控制台&#xff0c;找到下图标识符&#xff08;英文&#xff09;&#xff0c;单击进入 Certificates,Identifiers&Profiles 页面。 在…

【QT5-程序控制电源-[GPIB-USB-HS]-SCPI协议-上位机-基础样例【2】】

【QT5-程序控制电源-[GPIB-USB-HS]-SCPI协议-上位机-基础样例【2】】 1、前言2、实验环境3、自我总结1、基础了解仪器控制-熟悉仪器2、连接SCPI协议3、了解GPIB-USB-HS4、软件调试-代码编写 4、熟悉协议-SCPI协议5、实验过程-熟悉软件&#xff08;1&#xff09;去官网NI&#x…

电视盒子哪个牌子最好?经销商分享热门电视盒子排名

作为数码产品经销商&#xff0c;我对电视盒子这块非常了解&#xff0c;最近看到很多人因为不懂电视盒子哪个牌子最好而踩雷&#xff0c;我根据店内的销量情况整理了电视盒子排名&#xff0c;近期想买电视盒子不想花冤枉钱可以从下面五款电视盒子中入手。 TOP 1泰捷WEBOX 40S电视…