【数据结构】六种排序实现方法及区分比较

文章目录

  • 前言
  • 插入排序
  • 希尔排序
  • 选择排序
  • 堆排序
  • 快速排序
  • 冒泡排序
  • 总结


前言

众所周知,存在许多种排序方法,作为新手,最新接触到的就是冒泡排序,这种排序方法具有较好的教学意义,但是实用意义不高,原因就在于它的时间复杂度太高了,为 O(n^2) 即便后来我们使用 flag 去优化它,也不过也不过少了一点,如果序列完全倒序,就没什么用。

所以为了使代码运行效率更高,人们就设计了许多种排序方法,这里笔者将比较常用的六种进行介绍,并对其的一些使用情景及效率进行一下比较。

默认实现时都为升序

  • 插入排序
  • 希尔排序
  • 选择排序
  • 堆排序
  • 冒泡排序
  • 快速排序

为了等下便于比较我们可以建立多个存有相同大小的数组,利用 c l o c k ( ) clock() clock() 来记录排序十万或一百万数据所需的时间,这样就可以直观地比较了,代码如下

void TestOP()
{
	srand((unsigned)time(0));
	const int N = 100000;

	int* a1 = (int*)malloc(sizeof(int) * N);
	int* a2 = (int*)malloc(sizeof(int) * N);
	int* a3 = (int*)malloc(sizeof(int) * N);
	int* a4 = (int*)malloc(sizeof(int) * N);
	int* a5 = (int*)malloc(sizeof(int) * N);
	int* a6 = (int*)malloc(sizeof(int) * N);

	for (int i = 0; i < N; i++)
	{
		a1[i] = rand();
		a2[i] = a1[i];
		a3[i] = a1[i];
		a4[i] = a1[i];
		a5[i] = a1[i];
		a6[i] = a1[i];
	}

	int begin1 = clock();
	InsertSort(a1, N);
	int end1 = clock();

	int begin2 = clock();
	//ShellSort(a2, N);
	int end2 = clock();

	int begin3 = clock();
	//SelectSort(a3, N);
	int end3 = clock();

	int begin4 = clock();
	//HeapSort(a4, N);
	int end4 = clock();

	int begin5 = clock();
	//QuickSort(a5, N);
	int end5 = clock();

	int begin6 = clock();
	//BubbleSort(a6, N);
	int end6 = clock();


	printf("InsertSort:%d\n", end1 - begin1);
	printf("ShellSort:%d\n", end2 - begin2);
	printf("SelectSort:%d\n", end3 - begin3);
	printf("HeapSort:%d\n", end4 - begin4);
	printf("QuickSort:%d\n", end5 - begin5);
	printf("BubbleSort:%d\n", end6 - begin6);

	free(a1);
	free(a2);
	free(a3);
	free(a4);
	free(a5);
	free(a6);
}

插入排序

插入排序的平均时间复杂度为 O ( n 2 ) O(n^2) O(n2),最坏情况下的时间复杂度也为 O ( n 2 ) O(n^2) O(n2)

关于希尔排序的时间复杂度,是很难计算的。要准确计算希尔排序的时间复杂度,需要考虑具体的增量序列和数据分布情况。不同的增量序列可能会导致不同的时间复杂度。

需要注意的是,这些时间复杂度估计是基于理论分析和实验结果得出的,但实际情况可能会有所不同。在实际应用中,希尔排序的性能还会受到硬件、数据特点等因素的影响。

插入排序的思想就是把待排序的记录按其关键码值的大小逐个插入到一个已经排好序的有序序列中,直到所有的记录插入完为止,得到一个新的有序序列。

在这里插入图片描述

在插入排序的过程中,每次插入一个元素时,都需要在已经有序的序列中找到合适的位置插入该元素。这个过程需要进行比较和移动操作,因此插入排序的时间复杂度主要取决于比较和移动操作的次数。

具体思路:

  1. 从左往右插入排序
  2. 建立临时变量 e n d end end标志当前的有序末尾
  3. 不断将 e n d + 1 end+1 end+1的值插入到有序序列中
//插入排序,升序
// 时间复杂度:O(N^2)  什么情况最坏:逆序
// 最好:顺序有序,O(N)
void InsertSort(int* a, int n)
{
	for (int i = 0; i < n - 1; i++)
	{
		int end = i;
		int tmp = a[end + 1];
		while (end >= 0)
		{
			if (tmp < a[end])
			{
				a[end + 1] = a[end];
				end--;
			}
			else
				break;
		}
		a[end + 1] = tmp;
	}
}

我们尝试排序一下十万个数据,用时3点多秒,还算可以
在这里插入图片描述

但是当我们把数据改成一百万个时,笔者等了两分多种都没出结果,可见这个插入排序的漏洞还是很大的


希尔排序

希尔排序(Shell Sort)是插入排序的一种。也称缩小增量排序,是直接插入排序算法的一种更高效的改进版本。希尔排序是非稳定排序算法。

希尔排序是把记录按下标的一定增量分组,对每组使用直接插入排序算法排序;随着增量逐渐减少,每组包含的关键词越来越多,当增量减至 1 时,整个文件恰被分成一组,算法便终止。

希尔排序的基本思想是:先将整个待排序的记录序列分割成为若干子序列分别进行直接插入排序,待整个序列中的记录“基本有序”时,再对全体记录进行依次直接插入排序。

在这里插入图片描述

希尔排序的具体步骤如下:

  1. 选择一个增量序列 t1,t2,…,tk,其中 ti > tj, tk = 1;
  2. 按增量序列个数 k,对序列进行 k 趟排序;
  3. 每趟排序,根据对应的增量 ti,将待排序列分割成若干长度为 m 的子序列,分别对各子表进行直接插入排序。仅增量因子为 1 时,整个序列作为一个表来处理,表长度即为整个序列的长度。

希尔排序的时间复杂度为 O ( n l o g n ) O(nlogn) O(nlogn),空间复杂度为 O ( 1 ) O(1) O(1)。希尔排序是一种不稳定的排序算法。

//希尔排序
void ShellSort(int* a, int n)
{
	int gap = n;
	while (gap > 1)
	{
		gap = gap / 3 + 1;
		for (size_t i = 0; i < n - gap; i++)
		{
			int end = i;
			int tmp = a[end + gap];
			while (end >= 0)
			{
				if (a[end] > tmp)
				{
					a[end + gap] = a[end];
					end -= gap;
				}
				else
				{
					break;
				}
				a[end + gap] = tmp;
			}
		}
 	}
}

如果比较难理解可以看下图,假设我们当前是 g a p = 3 gap = 3 gap=3,就相当于每三个元素提取出来一个放进一个数组里,这样的数组有3个
在这里插入图片描述

之后在对这三个元素分别进行插入排序,这样的好处是分担了大量元素一次排序的性能,并且在多次这样预排序后会整个数组都趋近于有序,这样一来,越后面的排序基本就不需要交换了,性能也就更高。

可以直观感受一下对十万个数据两者的差距
在这里插入图片描述
即便改成了排序一百万个数据,也只消耗了0.2秒。
在这里插入图片描述


选择排序

选择排序(Selection Sort)是一种简单直观的排序算法。它首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,然后,再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。以此类推,直到所有元素均排序完毕。

选择排序的基本思想是:首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,然后,再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。以此类推,直到所有元素均排序完毕。

在这里插入图片描述

选择排序的具体步骤如下:

  1. 首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置;
  2. 然后,再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾;
  3. 以此类推,直到所有元素均排序完毕。

选择排序的时间复杂度为 O ( n 2 ) O(n^2) O(n2),空间复杂度为 O ( 1 ) O(1) O(1)。选择排序是一种不稳定的排序算法。

//选择排序
void SelectSort(int* a, int n)
{
	int begin = 0;
	int end = n - 1;
	while (begin < end)
	{
		int mini = begin;
		int maxi = begin;
		for (size_t i = begin + 1; i < end; i++)
		{
			if (a[i] < a[mini])
				mini = i;
			if (a[i] > a[maxi])
				maxi = i;
		}
		Swap(&a[mini], &a[begin]);
		if (begin == maxi)
			maxi = mini;
		Swap(&a[maxi], &a[end]);
		begin++;
		end--;
	}
}

但是这种算法的时间复杂度还是太高,要比较和交换的次数太多了,相比于冒泡排序,这种甚至连教学意义都没有,仅仅需要了解一下其中的思想就行了,一般代码中都不会用这种排序。
在这里插入图片描述


堆排序

堆排序(Heap Sort)是指利用堆这种数据结构所设计的一种排序算法。堆积是一个近似完全二叉树的结构,并同时满足堆积的性质:即子结点的键值或索引总是小于(或者大于)它的父节点。

堆排序的基本思想是:将待排序序列构造成一个大顶堆,此时,整个序列的最大值就是堆顶的根节点。将其与末尾元素进行交换,此时末尾就为最大值。然后将剩余 n-1 个元素重新构造成一个堆,这样会得到 n 个元素的次小值。如此反复执行,便能得到一个有序序列了。

在这里插入图片描述

堆排序的具体步骤如下:

  1. 构建初始堆:将待排序序列构造成一个大顶堆;
  2. 交换堆顶元素和末尾元素:将堆顶元素与末尾元素进行交换;
  3. 调整堆结构:对交换后的堆进行调整,使其重新成为一个大顶堆;
  4. 重复步骤 2 和 3,直到整个序列有序。

堆排序的时间复杂度为 O ( n l o g n ) O(nlogn) O(nlogn),空间复杂度为 O ( 1 ) O(1) O(1)。堆排序是一种不稳定的排序算法。

建堆的过程可以通过从最后一个非叶子节点开始,逐步向上调整堆的结构来实现。这个过程的时间复杂度为 O ( n ) O(n) O(n),其中 n n n是待排序元素的数量。

排序的过程是通过不断地将堆顶元素与末尾元素交换,并调整堆结构来实现的。每次交换和调整堆结构的时间复杂度为 O ( l o g n ) O(logn) O(logn),因为堆的高度为 l o g n logn logn

因此,堆排序的总时间复杂度为 O ( n l o g n ) O(nlogn) O(nlogn)

代码实现如下

//堆排序
void AdjustDown(int* a, int parent, int n)
{
	//建大堆
	int child = parent * 2 + 1;
	while (child < n)
	{
		if (child + 1 < n && a[child + 1] > a[child])
			child++;
		if (a[parent] < a[child])
		{
			Swap(&a[parent], &a[child]);
			parent = child;
			child = parent * 2 + 1;
		}
		else
		{
			break;
		}
	}
}

void HeapSort(int* a, int n)
{
	//建大堆 O(n^2)
	for (int i = (n - 1 - 1) / 2 ; i > 0; i--)
	{
		AdjustDown(a, i, n);
	}
	int end = n - 1;

	//O(logn)
	while (end > 0)
	{
		Swap(&a[end], &a[0]);
		AdjustDown(a, 0, end);
		end--;
	}
}

在十万个数据下,它进行的也是比较快的

在这里插入图片描述

更改为1000万个数据后,堆排序的性能还是可以的,仅次于希尔排序

在这里插入图片描述


快速排序

快速排序(Quick Sort)是一种常用的排序算法。它的平均时间复杂度为 O ( n l o g n ) O(nlogn) O(nlogn),空间复杂度为 O ( l o g n ) O(logn) O(logn)。快速排序的基本思想是通过选择一个基准元素,将数组分为两部分,使得左边的元素都小于等于基准元素,右边的元素都大于等于基准元素。然后,对左右两部分分别进行快速排序,直到整个数组有序。

快速排序的时间复杂度主要取决于划分的过程。

在快速排序中,每次选择一个基准元素,将数组分为两部分,使得左边的元素都小于等于基准元素,右边的元素都大于等于基准元素。这个过程的时间复杂度为 O ( n ) O(n) O(n),其中 n n n是数组的长度。

然后,对左右两部分分别进行快速排序,这个过程的时间复杂度也为 O ( n ) O(n) O(n)

因此,快速排序的总时间复杂度为 O ( n l o g n ) O(nlogn) O(nlogn)

需要注意的是,这是快速排序的平均时间复杂度。在最坏情况下,快速排序的时间复杂度可能会达到 O ( n 2 ) O(n^2) O(n2),例如当数组已经有序时。但是,在大多数情况下,快速排序的时间复杂度都非常接近 O ( n l o g n ) O(nlogn) O(nlogn)

在这里插入图片描述

快速排序的具体步骤如下:

  1. 选择一个基准元素,可以选择数组的第一个元素、最后一个元素或中间元素等。
  2. 将数组分为两部分,使得左边的元素都小于等于基准元素,右边的元素都大于等于基准元素。可以通过交换元素的位置来实现。
  3. 对左右两部分分别进行快速排序,直到整个数组有序。

快速排序的优点是平均时间复杂度较低,空间复杂度也较低,而且实现简单。但是,快速排序在最坏情况下的时间复杂度为 O ( n 2 ) O(n^2) O(n2),当数组已经有序或接近有序时,快速排序的性能会下降。为了避免这种情况,可以选择随机选择基准元素或使用其他改进的快速排序算法。

void QuickSort(int* a, int left, int right)
{
	if (left >= right)
	{
		return NULL;
	}
	int ret = left;
	int begin = left;
	int end = right;
	while (begin < end)
	{
		while (end > begin && a[end] >= a[ret])
			end--;
		while (end > begin && a[begin] <= a[ret])
			begin++;
		Swap(&a[end], &a[begin]);
	}
	Swap(&a[begin], &a[ret]);
	QuickSort(a, left, begin - 1);
	QuickSort(a, begin + 1, right);
}

在这里插入图片描述

这里利用递归的方法不断对左右两边进行排序,直至有序

但是我们可以发现上述过程还是可以优化的

  1. 当数组元素小于10个时,用插入排序(注意插入排序的起始位置)
  2. 每次都是那最左边的元素作为基准元素,在整个数组趋于有序时定然左少右多,找左右中元素中间的那个值作为基准元素更有效
//快速排序
int midi(int* a, int left, int right)
{
	int mid = (left + right) / 2;
	if (a[mid] > a[left])
	{
		if (a[mid] < a[right])
			return mid;
		else
		{
			if (a[left] > a[right])
				return left;
			else
				return right;
		}
	}
	else
	{
		if (a[mid] > a[right])
			return mid;
		else
		{
			if (a[left] < a[right])
				return left;
			else
				return right;
		}
	}
}
void QuickSort(int* a, int left, int right)
{
	if (left >= right)
	{
		return NULL;
	}

	if ((right - left + 1) < 10)
	{
		InsertSort(a+left, right - left + 1);//加上left,从第left个元素开始
	}
	else
	{
		int mid = midi(a, left, right);
		Swap(&a[mid], &a[left]);


		int ret = left;
		int begin = left;
		int end = right;
		while (begin < end)
		{
			while (end > begin && a[end] >= a[ret])
				end--;
			while (end > begin && a[begin] <= a[ret])
				begin++;
			Swap(&a[end], &a[begin]);
		}
		Swap(&a[begin], &a[ret]);
		QuickSort(a, left, begin - 1);
		QuickSort(a, begin + 1, right);
	}
}

冒泡排序

冒泡排序(Bubble Sort)是一种简单的排序算法。它重复地走访要排序的数列,一次比较两个数据元素,如果顺序不对则进行交换,并一直重复这样的走访操作,直到没有要交换的数据元素为止。

冒泡排序的基本思想是:通过相邻元素之间的比较和交换,将最大的元素逐步“冒泡”到数列的末尾。具体来说,冒泡排序的每一轮都会比较相邻的两个元素,如果它们的顺序错误,就将它们交换位置。这样,每一轮都会将一个最大的元素“冒泡”到数列的末尾。经过若干轮比较和交换后,整个数列就会变得有序。

在这里插入图片描述

冒泡排序的时间复杂度为 O ( n 2 ) O(n^2) O(n2),空间复杂度为 O ( 1 ) O(1) O(1)。它是一种稳定的排序算法,即相同元素的相对顺序在排序前后不会改变。

冒泡排序的优点是实现简单,容易理解。缺点是效率较低,对于大规模数据的排序不太适用。在实际应用中,冒泡排序通常用于对小规模数据进行排序,或者作为其他排序算法的辅助步骤。

void BubbleSort(int* a, int n)
{
	for (size_t i = 0; i < n - 1; i++)
	{
		int flag = 0;
		for (size_t j = 0; j < n - 1 - i; j++)
		{
			if (a[j] > a[j + 1])
				Swap(&a[j], &a[j + 1]);
			flag = 1;
		}
		if (flag == 0)
			break;
	}
}

排序一万个数据就可以看到冒泡与别的排序方法的差距

在这里插入图片描述
笔者尝试排序十万个,可是冒泡排序等了2分钟都没出结果就不管它了,别的排序算法比较如下
在这里插入图片描述


总结

以下是对插入排序、希尔排序、选择排序、堆排序、快速排序和冒泡排序的比较分析总结:

  1. 插入排序

    • 基本思想:将未排序元素逐个插入已排序序列的合适位置。
    • 时间复杂度:平均情况和最坏情况均为 O ( n 2 ) O(n^2) O(n2)
    • 空间复杂度: O ( 1 ) O(1) O(1)
    • 稳定性:稳定。
    • 优点:简单直观,适用于小规模数据。
    • 缺点:效率较低。
  2. 希尔排序

    • 基本思想:通过将数组分成较小的子数组,并对每个子数组进行插入排序来改进插入排序。
    • 时间复杂度:取决于增量序列的选择,平均情况和最坏情况的时间复杂度较为复杂。
    • 空间复杂度: O ( 1 ) O(1) O(1)
    • 稳定性:不稳定。
    • 优点:在某些情况下比插入排序更快。
    • 缺点:增量序列的选择对性能影响较大。
  3. 选择排序

    • 基本思想:在未排序序列中找到最小元素,存放到排序序列的起始位置,然后,再从剩余未排序元素中继续寻找最小元素,然后放到已排序序列的末尾。以此类推,直到所有元素均排序完毕。
    • 时间复杂度:平均情况和最坏情况均为 O ( n 2 ) O(n^2) O(n2)
    • 空间复杂度: O ( 1 ) O(1) O(1)
    • 稳定性:不稳定。
    • 优点:简单直观,交换次数较少。
    • 缺点:效率较低。
  4. 堆排序

    • 基本思想:利用堆这种数据结构来进行排序。堆是一种完全二叉树,其每个节点的值都大于等于(或小于等于)其左右子节点的值。
    • 时间复杂度:平均情况和最坏情况均为 O ( n l o g n ) O(nlogn) O(nlogn)
    • 空间复杂度: O ( 1 ) O(1) O(1)
    • 稳定性:不稳定。
    • 优点:效率较高。
    • 缺点:实现相对复杂。
  5. 快速排序

    • 基本思想:通过选择一个基准元素,将数组分为两部分,使得左边的元素都小于等于基准元素,右边的元素都大于等于基准元素。然后,对左右两部分分别进行快速排序,直到整个数组有序。
    • 时间复杂度:平均情况为 O ( n l o g n ) O(nlogn) O(nlogn),最坏情况为 O ( n 2 ) O(n^2) O(n2)
    • 空间复杂度:平均情况为 O ( l o g n ) O(logn) O(logn),最坏情况为 O ( n ) O(n) O(n)
    • 稳定性:不稳定。
    • 优点:效率高,平均情况下性能较好。
    • 缺点:最坏情况下时间复杂度较高。
  6. 冒泡排序

    • 基本思想:通过反复比较相邻的元素并交换它们的位置,将最大的元素逐步“冒泡”到数组的末尾。
    • 时间复杂度:平均情况和最坏情况均为 O ( n 2 ) O(n^2) O(n2)
    • 空间复杂度: O ( 1 ) O(1) O(1)
    • 稳定性:稳定。
    • 优点:简单易懂,容易实现。
    • 缺点:效率较低。

综上所述,不同的排序算法在时间复杂度、空间复杂度、稳定性和实现难度等方面存在差异。在实际应用中,应根据具体情况选择合适的排序算法。对于小规模数据,插入排序和冒泡排序可能是简单有效的选择;对于大规模数据,快速排序和堆排序通常具有较好的性能。希尔排序和选择排序在某些情况下也可能表现良好

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【文件fd】回顾C语言文件操作 | 详细解析C语言文件操作写w追加a | 重定向和“w““a“

目录 前言 回顾C语言的操作 Q1 Q2 Q3 C语言文件操作 w方式 a方式 重定向和"w""a"方式 前言 前面进程虚拟地址空间让我们对进程的理解更加深入。在基础IO我们会详细介绍文件和文件系统。本专题的核心内容是文件。 深刻理解文件&#xff08;站在…

知识库管理系统:是什么、作用、如何搭建

你有没有遇到过这种情况&#xff1a;在工作中想要查找某个信息&#xff0c;查找了很多个文档还是没找到准确的信息&#xff1b;或者在团队中&#xff0c;总是在重复做着相同的资料搜集工作&#xff0c;浪费了大量时间和精力&#xff1f;如果你在烦恼这个问题&#xff0c;那么跟…

【Vue3】自定义组件directiveapp.use()

历史小剧场 崇祯很勤政&#xff0c;崇祯并非王国之君&#xff0c;弘光很昏庸&#xff0c;弘光活该倒霉&#xff0c;几百年来&#xff0c;我们都这样认为。 但我们之所以一直这样认为&#xff0c;只是因为有人这样告诉我们。 之所以有人这样告诉我们&#xff0c;是因为他们希望我…

Java | Leetcode Java题解之第121题买卖股票的最佳时机

题目&#xff1a; 题解&#xff1a; public class Solution {public int maxProfit(int prices[]) {int minprice Integer.MAX_VALUE;int maxprofit 0;for (int i 0; i < prices.length; i) {if (prices[i] < minprice) {minprice prices[i];} else if (prices[i] -…

PieCloudDB Database Flink Connector:让数据流动起来

面对客户环境中长期运行的各种类型的传统数据库&#xff0c;如何优雅地设计数据迁移的方案&#xff0c;既能灵活地应对各种数据导入场景和多源异构数据库&#xff0c;又能满足客户对数据导入结果的准确性、一致性、实时性的要求&#xff0c;让客户平滑地迁移到 PieCloudDB 数据…

快递100使用

1.快递100 接口文档 链接: 接口文档 2.授权参数 授权Key: qZgsNFSo5391 customer&#xff1a;8EEA8C4FB90B275E228CA322EF0E61E5 3.技术文档 链接: 技术文档 4.使用 <dependency><groupId>com.github.kuaidi100-api</groupId><artifactId>sdk&l…

AI大模型探索之路-实战篇12: 构建互动式Agent智能数据分析平台:实现多轮对话控制

系列篇章&#x1f4a5; AI大模型探索之路-实战篇4&#xff1a;深入DB-GPT数据应用开发框架调研 AI大模型探索之路-实战篇5&#xff1a;探索Open Interpreter开放代码解释器调研 AI大模型探索之路-实战篇6&#xff1a;掌握Function Calling的详细流程 AI大模型探索之路-实战篇7…

【CPP】双端队列简介(deque)

简介&#xff1a;双端队列(deque) 目录 1.概述2.特点3.底层原理 1.概述 双端队列&#xff1a;是一种顺序表和顺序表的结合数据结构&#xff0c;不是队列。 它提供顺序表的[]下标访问和链表的中间头部的较高效率插入删除操作。 2.特点 顺序表的优缺点&#xff1a; 优点&…

网络安全基础技术扫盲篇 — 名词解释之“数据包“

用通俗易懂的话说&#xff1a; 数据包就像是一个信封。当你写信给某个人时&#xff0c;你将内容写在一张纸上&#xff0c;然后将纸叠起来并放入信封中&#xff0c;就形成了一个完整要发送的数据内容。信封上有发件人和收件人的详细地址&#xff0c;还有一些其他必要的信息&…

动态规划(Dynamic-Programming)问题讲解

动态规划类问题 从已知子问题的解&#xff0c;推导出当前问题的解 推导过程可以表达为一个数学公式用一维或二维数组来保存之前的计算结果&#xff08;可以进一步降维优化&#xff09; 将当前问题 分解成子问题 &#xff0c;找出递归公式&#xff0c;分阶段进行求解 求解过程中…

【scau大数据技术与原理2】综合性实验Spark集群的安装和使用——安装启动spark shell篇

实验内容简介&#xff1a; Spark是一个分布式计算框架&#xff0c;常用于大数据处理。本次实验中&#xff0c;首先设计一个包含主节点和从节点的Spark集群架构&#xff0c;并在CentOS的Linux环境下进行搭建。通过下载并解压Spark安装包&#xff0c;配置环境变量和集群参数&…

python分别保存聚类分析结果+KeyError: ‘CustomerID‘报错

如何在完成聚类分析后按聚类编号保存数据并且带上原数据所属ID # 将每个聚类的数据保存到不同的文件中 for cluster_id in range(6): # 假设共有6个聚类cluster_data data[data[cluster] cluster_id]cluster_data_with_customer_id cluster_data.copy()cluster_data_with_…

量化研究---强大的可转债分析系统上线,提供api,实时数据支持

今天把可转债实盘的分析模型拿出来&#xff0c;放在服务器方便选股分析&#xff0c;方便后面对接大qmt直接选股交易 强大的禄得可转债自定义因子轮动系统完成&#xff0c;可转债三低为例子 自定义因子实盘的框架 自定义因子轮动框架非常强大 网页 http://120.78.132.143:8023/…

MongoDB~俩大特点管道聚合和数据压缩(snappy)

场景 在MySQL中&#xff0c;通常会涉及多个表的一些操作&#xff0c;MongoDB也类似&#xff0c;有时需要将多个文档甚至是多个集合汇总到一起计算分析&#xff08;比如求和、取最大值&#xff09;并返回计算后的结果&#xff0c;这个过程被称为 聚合操作 。 根据官方文档介绍&…

day1、2-数1

数学一主要考查高数、线性代数、概率统计这三个方面&#xff0c;其中高数占比56%、线性代数占比22%、概率统计占比22% 题做完 要产生1套理论 24年真题 1. 选C sinx的话不影响奇偶 奇偶函数的积分 0到a的积分为一个常数 求导的话 奇函数导出来一定是偶函数&#xff0c;偶函…

【机器学习系列】掌握随机森林:从基础原理到参数优化的全面指南

目录 目录 一、随机森林简介 (一)随机森林模型的基本原理如下&#xff1a; (二)随机森林模型的优点包括&#xff1a; (三)森林中的树的生成规则如下&#xff1a; (四)在随机森林中&#xff0c;每棵树都使用不同的训练集进行训练&#xff0c;原因如下 随机森林的分类性能&…

day-36 删除链表的倒数第 N 个结点

思路 首先计算出链表的长度&#xff0c;然后删除第n个节点即可&#xff0c;但要注意考虑特殊情况 解题方法 特殊情况&#xff1a;1.删除节点为最后一个节点 2.删除节点为头结点 Code /*** Definition for singly-linked list.* public class ListNode {* int val;* …

函数:计算数组的元素和

一、计算数组的元素和 参数传递给函数时&#xff0c;实际上只有数组的首地址作为指针传递给了函数。 在函数定义中的int a[ ]等价于int *a。在只有地址信息的情况下&#xff0c;是无法知道数组里有多少个元素的&#xff0c;因此在计算数组中的元素和时&#xff0c;要加一个参…

MongoDB下载安装入门 + SpringBoot简单集成

MongoDB安装入门 SpringBoot简单集成 MongoDB下载安装下载安装连接图形化界面MongoDB Compass Navicat Premium Spring Boot集成API操作添加maven配置数据库连接调用Mongo API MongoDB下载安装 下载安装 MongoDB官网地址&#xff1a;https://www.mongodb.com/ 下载地址&…

CobaltStrike基本渗透

目录 CobaltStrike简介 主要功能&#xff1a; 使用注意&#xff1a; 在使用CobaltStrike进行渗透测试时&#xff0c;务必遵守法律法规&#xff0c;并获得合法授权。 CobaltStrike安装 前提 安装 服务端安装 windows安装 CS基本使用 监听器配置 一些基本的攻击…