六大排序精解

排序概念

排序:所谓排序,就是使一串记录,按照其中的某个或某些关键字的大小,递增或递减的排列起来的操作。
稳定性:假定在待排序的记录序列中,存在多个具有相同的关键字的记录,若经过排序,这些记录的相对次序保持不变,即在原序列中,r[i]=r[j],且r[i]在r[j]之前,而在排序后的序列中,r[i]仍在r[j]之前,则称这种排序算法是稳定的;否则称为不稳定的。
内部排序:数据元素全部放在内存中的排序。
外部排序:数据元素太多不能同时放在内存中,根据排序过程的要求不能在内外存之间移动数据的排序

排序的几种分类

常见的排序算法及主要思想:

- 插入排序:每次将一个元素插入到已经排好序的有序序列中,从前向后依次对所有元素进行插入排序。

- 选择排序:每次在待排序的数据元素中选出最小(或最大)的一个元素,然后将其与第一个元素交换位置。

- 冒泡排序:通过相邻元素之间的比较和交换位置的方式,使得每次比较后最大(或最小)的元素都会沉底。

- 希尔排序:是插入排序的一种更高效的改进版本。它利用插入排序在近乎有序的情况下的性能,通过预先部分排序将输入序列分割成几个子序列,分别进行插入排序。

- 归并排序:采用分治法(Divide and Conquer)的思想,将已有序的子序列合并,得到完全有序的序列。

- 快速排序:通过一趟排序将待排记录分割成独立的两部分,其中一部分记录的关键字均比另一部分的关键字小,则可分别对这两部分记录继续进行排序,以达到整个序列有序。

- 堆排序:利用堆这种数据结构来排序。通过构建大顶堆和调整堆的方式,每次都能找到当前序列的最大值。

以上是几种常见的排序算法,它们的时间复杂度和稳定性不同。排序的目的是使数据按某种顺序排列,是算法和数据结构中重要的基础概念。

排序过程与实现

1.冒泡排序

1.1 主要思想及过程

主要思想是通过不断比较相邻的元素并交换它们,使得较大(或较小)的元素逐渐“浮”到数组的一端。具体来说,冒泡排序的主要步骤如下:

  1. 从数组的第一个元素开始,依次比较相邻的两个元素,如果顺序不对则交换它们,使得较大(或较小)的元素向后移动。
  2. 继续对数组中的每一对相邻元素进行比较和交换,直到所有元素都被遍历一次。这样一次遍历之后,最大(或最小)的元素就会“冒泡”到数组的末尾。
  3. 重复以上步骤,每次遍历都会将当前未排序部分的最大(或最小)元素“冒泡”到相应位置,直到整个数组有序。

冒泡排序的时间复杂度为O(n2),其中n为数组的长度。尽管冒泡排序简单直观,但对于大规模数据集来说效率较低,通常不适用于大型数据排序。

下图是冒泡排序的过程动图。 

1.2 代码实现 

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

运行结果 

2. 选择排序 

2.1 主要思想及过程 

主要思想是在未排序部分中选择最小(或最大)的元素,然后将其放到已排序部分的末尾。

选择排序的主要步骤如下:

  1. 从数组中选择最小(或最大)的元素,将其与数组的第一个元素交换位置,此时第一个元素就是已排序部分的最小(或最大)元素。
  2. 在剩余未排序的部分中继续选择最小(或最大)的元素,将其与已排序部分的末尾元素交换位置,将其加入已排序部分。
  3. 重复以上步骤,每次选择出未排序部分的最小(或最大)元素并加入已排序部分,直到整个数组排序完成。

选择排序的时间复杂度也为O(n2),其中n为数组的长度。虽然选择排序比冒泡排序稍微高效一些,但仍然不适用于大规模数据排序。和冒泡排序一样,选择排序是一种简单但不够高效的排序算法。

动图如下:

2.2 代码实现 

这里的代码思想相较上图有所改进,遍历一次同时记录未排序部分的最大与最小值,而后交换至未排序部分的首尾处。 

void SelectSort(int* a, int n)
{int begin = 0, end = n - 1;//从首尾同时开始while (begin < end){int max_i = end, min_i = begin;//先假定max与min所在位置for (int i = begin; i <= end; i++)//每一趟遍历都找到一个max与min{//这里不能对begin与end做修改if (a[i] < a[min_i]){min_i = i;//更新min的位置}if (a[i] > a[max_i]){max_i = i;//更新max的位置}}Swap(&a[begin], &a[min_i]);//交换min与begin处的值if (begin == max_i)//如果此时begin与max在同一位置,那么之前的交换就将max交换到了min处{max_i = min_i;//这种情况下更新max位置}Swap(&a[end], &a[max_i]);--end;++begin;}
}

 运行结果

3. 插入排序 

3.1 主要思想及过程 

主要思想是将未排序部分的元素逐个插入到已排序部分的合适位置,从而逐步构建有序序列。

插入排序的主要步骤如下:

1. 将数组视为两部分:已排序部分和未排序部分。初始时,已排序部分只包含数组的第一个元素,而未排序部分包含剩余的元素。
2. 从未排序部分取出第一个元素,将其插入到已排序部分的合适位置,使得插入后仍然保持有序。
3. 继续从未排序部分取出元素,逐个插入到已排序部分的合适位置,直到未排序部分为空,所有元素都被排序。

插入排序的时间复杂度为O(n^2),最好情况下是O(n),其中n为数组的长度。插入排序在处理小型数据集或部分有序的数据时表现良好,因为它的内循环在有序部分中的操作次数较少。因此,插入排序通常用于对小型数据集进行排序,或作为其他排序算法的一部分。

 动图如下:

3.2 代码实现 

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 (a[end] > tmp)//已排序部分的末位大于tmp{a[end + 1] = a[end];//元素后移end--;//end左移}else//找到合适位置,退出循环{break;}}a[end + 1] = tmp;//将tmp插入}	
}

运行结果

 4. 希尔排序

4.1 主要思想及过程

希尔排序(Shell Sort)是一种改进的插入排序算法,也被称为“缩小增量排序”。希尔排序通过将数组分割成若干个子序列,对这些子序列分别进行插入排序,最后再对整个数组进行一次插入排序,从而实现对整个数组的排序。

希尔排序的主要步骤如下:

1. 选择一个增量序列,通常为n/2,n/4,n/8,...直到增量为1。
2. 对每个增量进行插入排序,即将数组分成若干个子序列,对每个子序列进行插入排序。
3. 逐渐减小增量,重复进行插入排序,直到增量为1。
4. 最后对整个数组进行一次插入排序。

希尔排序的时间复杂度取决于增量序列的选择,一般情况下在O(n\log n)到O(n^2)之间。希尔排序相比于插入排序有更好的性能,尤其适用于中等规模的数据集。希尔排序是一种高效的排序算法,尽管不如快速排序或归并排序那样高效,但在某些情况下仍然是一个不错的选择。

动图如下:

 4.2 代码实现

这里采取增量每次缩小三分之一的思想,最终的增量会变成1。

void ShellSort(int* a, int n)
{int gap = n;while (gap > 1){gap =gap/3+1;//gap每次缩小三倍,直到为1进行一次直接插入排序for(int i=0;i<n-gap;i++){int end = i;int tmp = a[end + gap];//以gap为单位,序列内相隔gap的元素为一组进行插入排序while (end >= 0){if (a[end] > tmp){a[end + gap] = a[end];//切记gapend-=gap;}else{break;}}a[end + gap] = tmp;}}

运行结果

5. 堆排序 

5.1 主要思想及过程 

堆排序(Heap Sort)是一种利用堆数据结构进行排序的算法,它利用了堆的性质来实现排序。堆是一种特殊的二叉树结构,分为最大堆和最小堆,其中最大堆满足父节点的值大于等于子节点的值,最小堆则相反。

堆排序的主要步骤如下:
1. 将待排序的数组构建成一个最大堆(或最小堆)。
2. 将堆顶元素(最大值或最小值)与堆的最后一个元素交换位置,然后对剩余的元素重新构建最大堆(或最小堆)。
3. 重复上述步骤,直到所有元素都被取出并排好序。

堆排序的时间复杂度为O(n*log n),其中n为数组的长度。堆排序是一种原地排序算法,不需要额外的空间,但由于其涉及到堆的构建和调整,实现起来较为复杂。堆排序适用于大规模数据集的排序,效率较高。

5.2 代码实现

这里我们建堆的过程使用向上调整算法,排序时使用向下调整算法

void BigADjustUP(int* a, int child)//大堆的向上调整,从子节点向上调整
{int parent = (child - 1) / 2;//寻找子节点的父亲while (child >= 0){if (a[child] > a[parent])//如果孩子大于父亲,{Swap(&a[child], &a[parent]);//交换父子的位置child = parent;//更新孩子节点parent = (parent - 1) / 2;//更新父亲节点}elsebreak;}
}
void BigADjustDown(int* a, int size, int parent)//大堆的向下调整
{int child = parent * 2 + 1;//找到父亲的孩子while (child < size)//孩子在size范围内{if (child + 1 < size && a[child] < a[child + 1])//左孩子小于右孩子{child = child + 1;//更新最大的孩子位置}if (a[child] > a[parent])//孩子大于父亲{Swap(&a[child], &a[parent]);//交换parent = child;//更新父亲与孩子的位置child = parent * 2 + 1;}elsebreak;}
}void HeapSort(int* a, int n)
{for (int i = 0; i < n; i++){BigADjustUP(a,i);//建堆}//for (int i = 0; i < n; i++)while (n > 0)//每次找到一个最大值放在最后面{Swap(&a[0], &a[n - 1]);//交换最后的节点与根节点位置BigADjustDown(a, n - 1, 0);//向下调整n--;//每次调整完最后一个节点不再参与排序}
}

 运行结果

6. 快速排序 

快速排序有很多种方法,这里介绍四种:霍尔排序法、挖坑法、前后指针法、非递归法。 即前三种都是递归完成的。

 6.1 霍尔法

6.1.1 主要思想及过程

霍尔方法(Hoare Partition Scheme)是快速排序算法中一种常用的分区方案,由Tony Hoare提出。霍尔方法通过选择一个基准值(key),将数组分为两部分,使得左边的元素都小于等于基准值,右边的元素都大于等于基准值,然后递归地对左右两部分进行排序。

霍尔方法的主要步骤如下:
1. 选择一个基准值(通常是数组的第一个元素)作为key。
2. 设置两个指针,一个指向数组的起始位置,一个指向数组的末尾。
3. 移动右指针,直到找到一个小于等于key的元素;移动左指针,直到找到一个大于等于key的元素;如果左指针小于右指针,则交换这两个元素。
4. 重复步骤3,直到左指针大于等于右指针。
5. 将key与左指针所指的元素交换位置,此时key左边的元素都小于等于key,右边的元素都大于等于key。
6. 递归地对左右两部分进行排序。

动图:

6.1.2 代码实现 
int Getmidi(int* a, int begin, int end)//三数取中
{int midi = (begin + end) / 2;if (a[begin] < a[midi]){if (a[begin] > a[end])return begin;else if (a[midi] < a[end]){return midi;}elsereturn end;}else{if (a[begin] < a[end])return begin;else if (a[midi] > a[end]){return midi;}elsereturn end;}
}int HoareQsort(int* a, int begin, int end)
{int mid_i = Getmidi(a, begin, end);//这里使用三数取中法来获取基准值,比之以首元素为基准值效率有所提升Swap(&a[mid_i], &a[begin]);int key_i = begin;//此时begin为三数的中间数int left = begin, right = end;//定义左右指针while (left < right)//两指针不能相遇{while (left < right && a[right] >= a[key_i])//右边先走,找小{right--;}while (left < right && a[left] <= a[key_i])//左边再走,找大{left++;}Swap(&a[left], &a[right]);//左右都停下,交换}Swap(&a[left], &a[key_i]);//此时左右指针相遇,交换指针与key_i处的值return left;//返回此时的keyi,此时keyi左边都比他小,右边都比他大,即位置已经固定
}void HoareQuickSort(int* a, int begin, int end)//霍尔方法的递归
{if (begin >= end)//递归至每个区间只有一个元素,返回return;int key_i = HoareQsort(a, begin, end);//返回霍尔方法得出的固定位置HoareQuickSort(a, begin, key_i - 1);//以此位置为分割,分别递归左右方的区间HoareQuickSort(a, key_i + 1, end);
}

6.2 挖坑法 

6.2.1 主要思想及过程 

快速排序的挖坑法(Partition方法)是一种常用的快速排序算法,其主要思想是通过选取一个基准值(通常是数组的第一个元素),将数组分为两部分,一部分比基准值小,另一部分比基准值大,然后递归地对这两部分进行排序。

具体过程如下:
1. 选取一个基准值(通常是数组的第一个元素)作为比较标准。
2. 设置两个指针,一个指向数组的起始位置(一般是左指针),一个指向数组的末尾位置(一般是右指针)。
3. 从右边开始,找到第一个小于基准值的元素,将其填入左指针的位置,左指针向右移动。
4. 从左边开始,找到第一个大于基准值的元素,将其填入右指针的位置,右指针向左移动。
5. 重复步骤3和步骤4,直到左指针和右指针相遇。
6. 将基准值填入左指针和右指针相遇的位置,此时基准值左边的元素都小于基准值,基准值右边的元素都大于基准值。
7. 递归地对基准值左边的部分和右边的部分进行相同的操作,直到排序完成。

通过不断地将数组分割为两部分并对每部分进行排序,最终可以得到一个有序的数组。挖坑法是快速排序中常用的一种分区方法,可以高效地对数组进行排序。

事实上挖坑法与霍尔方法思想上差不多,每趟排序都会确定一个基准值的最终位置,也就是左右指针相遇的位置。

6.2.2 代码实现
int Getmidi(int* a, int begin, int end)//三数取中
{int midi = (begin + end) / 2;if (a[begin] < a[midi]){if (a[begin] > a[end])return begin;else if (a[midi] < a[end]){return midi;}elsereturn end;}else{if (a[begin] < a[end])return begin;else if (a[midi] > a[end]){return midi;}elsereturn end;}
}int DigHoleQsort(int* a, int begin, int end)
{int mid_i = Getmidi(a, begin, end);//三数取中Swap(&a[mid_i], &a[begin]);//交换中间数至begin处int hole_i = begin;//在begin处挖坑int key = a[hole_i];//记录基准值int left = begin, right = end;while (left < right)//左右指针相遇即终止{while (left < right && a[right] >= key)//右边先走,找小{right--;}a[hole_i] = a[right];//找到小的填入坑内hole_i = right;while (left < right && a[left] <= key)//左边再走,找大{left++;}a[hole_i] = a[left];//找到大的填入坑内hole_i = left;}a[hole_i] = key;//将基准值填入坑内return hole_i;
}void DigHoleQuickSort(int* a, int begin, int end)
{if (begin >= end)return;int key_i = DigHoleQsort(a, begin, end);DigHoleQuickSort(a, begin, key_i - 1);DigHoleQuickSort(a, key_i + 1, end);
}

6.3 前后指针法 

6.3.1 主要思想及过程 

 前后指针法是快速排序的另一种常用的分区方法,也称为双指针法或荷兰国旗问题。

具体过程如下:
1. 选取一个基准值(通常是数组的第一个元素)作为比较标准。
2. 设置两个指针,一个指向数组的起始位置(一般是左指针),一个指向数组的末尾位置(一般是右指针)。
3. 左指针向右移动,直到找到一个大于等于基准值的元素。
4. 右指针向左移动,直到找到一个小于等于基准值的元素。
5. 如果左指针小于右指针,交换两个指针所指向的元素。
6. 重复步骤3和步骤4,直到左指针大于等于右指针。
7. 将基准值与右指针所指向的元素交换位置,此时基准值左边的元素都小于基准值,基准值右边的元素都大于基准值。
8. 递归地对基准值左边的部分和右边的部分进行相同的操作,直到排序完成。

前后指针法通过左右指针的移动,实现了对数组的原地分区,可以高效地对数组进行排序。

6.3.2 代码实现
int Getmidi(int* a, int begin, int end)//三数取中
{int midi = (begin + end) / 2;if (a[begin] < a[midi]){if (a[begin] > a[end])return begin;else if (a[midi] < a[end]){return midi;}elsereturn end;}else{if (a[begin] < a[end])return begin;else if (a[midi] > a[end]){return midi;}elsereturn end;}
}
int Prev_LastPointerQSort(int* a, int begin, int end)
{//cur找小,找到就停止,与++prev交换,分区:0-prev(小于基准值),prev-cur(大于基准值),cur-end(未排序)int mid_i = Getmidi(a, begin, end);//三数取中Swap(&a[mid_i],&a[begin]);//交换中间数至begin处int key_i = begin;//记录基准值下标int prev = begin, cur = prev + 1;//定义前后指针while (cur <= end)//前面指针越界即停止{if (a[cur] < a[key_i] && ++prev != cur)//cur处小于基准值,并且prev的下一个不等于cur{Swap(&a[cur], &a[prev]);//交换cur与prev的值}++cur;//cur++}Swap(&a[prev], &a[key_i]);//循环结束,交换基准值与prev处元素key_i = prev;//此时基准值在prev处return key_i;//返回已确定元素的位置
}void Prev_LastPointerQuickSort(int* a, int begin, int end)
{if (begin >= end)return;int key_i = Prev_LastPointerQSort(a, begin, end);Prev_LastPointerQuickSort(a, begin, key_i - 1);Prev_LastPointerQuickSort(a, key_i + 1, end);
}

6.4 快排的非递归实现 

6.4.1 主要思想及过程 

非递归法是指在实现快速排序时,不使用递归调用的方法来进行分区和排序。一种常见的非递归快速排序方法是使用栈来模拟递归调用的过程,实现分区和排序。

具体过程如下:
1. 将数组的起始位置和结束位置入栈,表示整个数组需要排序。
2. 循环执行以下步骤,直到栈为空:
   a. 出栈得到当前子数组的起始位置和结束位置。
   b. 选取一个基准值(通常是数组的第一个元素)作为比较标准。
   c. 使用前后指针法或挖坑法对当前子数组进行分区,将数组分为两部分。
   d. 将分区后的左右子数组的起始位置和结束位置入栈,表示需要对这两部分进行排序。
3. 循环结束后,整个数组就被排序完成。

通过使用栈来模拟递归调用的过程,非递归快速排序可以避免递归调用带来的额外开销,提高排序的效率。这种方法在实际应用中也是比较常见的一种实现方式。

6.4.2 代码实现

在c语言中,这里的栈是需要我们自己实现接口的。

void NonRecQsort(int* a, int begin, int end)
{Stack s;StackInit(&s);StackPush(&s, end);StackPush(&s, begin);//区间入栈while (StackEmpty(&s))//直到栈为空,所有区间出栈完成{int left = StackTop(&s);//区间出栈StackPop(&s);int right = StackTop(&s);StackPop(&s);int keyi = Prev_LastPointerQSort(a, left, right);//对区间进行一次排序,取keyi(左边的都比他小,右边的都比他大)if (left < keyi - 1)//左区间元素个数大于一{StackPush(&s, keyi - 1);StackPush(&s, left);}if (right > keyi + 1)//右区间元素个数大于1{StackPush(&s, right);StackPush(&s, keyi + 1);}}StackDestroy(&s);}

各大排序效率比较 

这里是100000个随机数的排序

void Test01()
{srand(time(0));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);int* a7 = (int*)malloc(sizeof(int) * N);int* a8 = (int*)malloc(sizeof(int) * N);int* a9 = (int*)malloc(sizeof(int) * N);int* a10 = (int*)malloc(sizeof(int) * N);for (int i = 0; i < N; i++){a1[i] = rand() + i;a2[i] = a1[i];a3[i] = a2[i];a4[i] = a3[i];a5[i] = a4[i];a6[i] = a5[i];a7[i] = a6[i];a8[i] = a7[i];	}int begin1 = clock();BubbleSort(a1, N);int end1 = clock();printf("BubbleSort() :  %d\n", end1-begin1);int begin2 = clock();InsertSort(a2, N);int end2 = clock();printf("InsertSort :  %d\n", end2 - begin2);int begin3 = clock();ShellSort(a3, N);int end3 = clock();printf("ShellSort :  %d\n", end3 - begin3);int begin4 = clock();SelectSort(a4, N);int end4 = clock();printf("SelectSort :  %d\n", end4 - begin4);int begin5 = clock();HoareQuickSort(a5, 0,N-1);int end5 = clock();printf("HoareQuickSort :  %d\n", end5 - begin5);int begin6 = clock();NonRecQsort(a6, 0, N - 1);int end6 = clock();printf("NonRecQsort :  %d\n", end6 - begin6);int begin7 = clock();DigHoleQuickSort(a7, 0, N - 1);int end7 = clock();printf("DigHoleQuickSort :  %d\n", end7 - begin7);int begin8 = clock();Prev_LastPointerQuickSort(a8, 0, N - 1);int end8 = clock();printf("Prev_LastPointerQuickSort :  %d\n", end8 - begin8);int begin9 = clock();HeapSort(a9,N);int end9 = clock();printf("HeapSort :  %d\n", end9 - begin9);
}

 

 

 

 

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

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

相关文章

安装nginx和PHP

首先规划四台虚拟机&#xff0c;之前的主从数据库已经两台&#xff0c;其余两台&#xff0c;一个设置nginx&#xff0c;一个是php 首先NGINX的概念&#xff0c;请参考https://blog.csdn.net/hyfsbxg/article/details/122322125。正向代理&#xff0c;反向代理&#xff0c;可以…

【每日八股】Java基础经典面试题4

前言&#xff1a;哈喽大家好&#xff0c;我是黑洞晓威&#xff0c;25届毕业生&#xff0c;正在为即将到来的秋招做准备。本篇将记录学习过程中经常出现的知识点以及自己学习薄弱的地方进行总结&#x1f970;。 本篇文章记录的Java基础面试题&#xff0c;如果你也在复习的话不妨…

【独立版】海之心陪诊系统-陪诊陪护小程序-V3.0

商品介绍 陪诊这个词在近两年才出现在人们的视野中&#xff0c;随着人口老龄化&#xff0c;社会信息化。我们的父母很多不会操作信息化的系统&#xff0c;以至于在手机上挂号和线下取号取报告比较困难&#xff0c;年轻人需要工作时间有限&#xff0c;陪诊需求因此而来。 陪诊…

Introduction to Data Mining 数据挖掘

Why Data Mining? • The Explosive Growth of Data: from terabytes to petabytes — Data collection and data availability ◦ Automated data collection tools, database systems, Web, computerized society — Major sources of abundant data ◦ Business: Web, e-co…

vue3 + ts +element-plus + vue-router + scss + axios搭建项目

本地环境&#xff1a; node版本&#xff1a;20.10.0 目录 一、搭建环境 二、创建项目 三、修改页面 四、封装路由vue-router 五、element-plus 六、安装scss 七、封装axios 一、搭建环境 1、安装vue脚手架 npm i -g vue/cli 2、查看脚手架版本 vue -V3、切换路径到需…

flask+ flask_socketio HTTP/1.1“ 400 公网IP 问题解决方案

很经典的一个跨域问题 在服务端改成socketio SocketIO(app, cors_allowed_origins"*")就可以了

数据可视化-ECharts Html项目实战(4)

在之前的文章中&#xff0c;我们学习了如何创建圆环图、嵌套圆环图、蓝丁格尔玫瑰图。想了解的朋友可以查看这篇文章。同时&#xff0c;希望我的文章能帮助到你&#xff0c;如果觉得我的文章写的不错&#xff0c;请留下你宝贵的点赞&#xff0c;谢谢。 数据可视化-ECharts Htm…

四、C语言中的数组:如何输入与输出二维数组(数组,完)

本章的学习内容如下 四、C语言中的数组&#xff1a;数组的创建与初始化四、C语言中的数组&#xff1a;数组的输入与元素个数C语言—第6次作业—十道代码题掌握一维数组四、C语言中的数组&#xff1a;二维数组 1.二维数组的输入与输出 当我们输入一维数组时需要一个循环来遍历…

uniApp中使用小程序XR-Frame创建3D场景(1)环境搭建

1.XR-Frame简介 XR-Frame作为微信小程序官方推出的3D框架&#xff0c;是目前所有小程序平台中3D效果最好的一个&#xff0c;由于其本身针对微信小程序做了优化&#xff0c;在性能方面比其他第三方库都要高很多。 2.与Three.js的区别 做3D小程序的同学们对Three.js一定不陌生…

huggingface_hub

文章目录 一、关于 huggingface_hub二、安装三、快速入门指南1、下载文件1.1 下载单个文件 hf_hub_download1.2 下载整个库 snapshot_download 2、登录3、创建一个存储库 create_repo4、上传文件4.1 上传单个文件 upload_file4.2 上传整个存储库 upload_folder 四、集成到 Hub …

图论06-飞地的数量(Java)

6.飞地的数量 题目描述 给你一个大小为 m x n 的二进制矩阵 grid &#xff0c;其中 0 表示一个海洋单元格、1 表示一个陆地单元格。 一次 移动 是指从一个陆地单元格走到另一个相邻&#xff08;上、下、左、右&#xff09;的陆地单元格或跨过 grid 的边界。 返回网格中 无法…

【PyCaret】使用PyCaret创建机器学习Pipeline进行多分类任务

发现一个好东西&#xff0c;PyCaret机器学习Pipeline&#xff0c;记录一下用其进行多分类任务的使用方法。 1、简介 PyCaret是一个开源的、不用写很多代码的Python机器学习库&#xff0c;可以自动化机器学习工作流程&#xff0c;是一个端到端的机器学习和模型管理工具&#xff…

登录与注册功能(简单版)(3)登录时使用Cookie增加记住我功能

目录 1、实现分析 2、步骤 1&#xff09;新建login.jsp 2&#xff09;修改LoginServlet&#xff1a; 3&#xff09;启动访问&#xff1a; 3、安全性考虑 4、最佳实践思路 1&#xff09;选择安全的认证机制 2&#xff09;强化会话管理 3&#xff09;安全地存储用户凭证…

Unity 粒子在UI中使用时需要注意的地方

最近项目中要在UI中挂载粒子特效,美术给过来的粒子直接放到UI中会有一些问题,查询一些资料后,总结了一下 一: 粒子的大小发生变化,与在预制件编辑中设计的大小不同 在预制件编辑模式下,大小正常 实际使用的时候特别大或者特别小 经过检查,发现预制件编辑模式下,默认画布的Rend…

上位机图像处理和嵌入式模块部署(qmacvisual点线测量)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 上面一篇文章&#xff0c;我们完成了直线的拟合操作。在实际场景中&#xff0c;拟合之后更多地是需要进行长度的测量。既然是测量&#xff0c;那么…

【JavaScript 漫游】【040】Blob 对象

文章简介 本篇文章为【JavaScript 漫游】专栏的第 040 篇文章&#xff0c;对浏览器模型中的 Blob 对象进行了总结。 概述 Blob 对象表示一个二进制文件的数据内容&#xff0c;比如一个图片文件的内容就可以通过 Blob 对象读写。它通常用来读写文件&#xff0c;它的名字是 Bi…

哪些企业适合构建企业新媒体矩阵?

⭐关注矩阵通服务号&#xff0c;探索企业新媒体矩阵搭建与营销策略 新媒体矩阵就是在某个平台或多个平台开设、联动多个账号&#xff0c;组建有关系的不同账号集群。 在数字化转型的浪潮下&#xff0c;矩阵已然成为企业实现品牌塑造、市场开拓与用户互动的重要阵地。 然而&…

2024Android-目前最稳定和高效的UI适配方案!你头秃都没想到还能这样吧!

但是这个方案有一个致命的缺陷&#xff0c;那就是需要精准命中才能适配&#xff0c;比如1920x1080的手机就一定要找到1920x1080的限定符&#xff0c;否则就只能用统一的默认的dimens文件了。而使用默认的尺寸的话&#xff0c;UI就很可能变形&#xff0c;简单说&#xff0c;就是…

记一次由于buff/cache导致服务器内存爆满的问题

目录 前言 复现 登录服务器查看占用内存进程排行 先了解一下什么是buff/cache&#xff1f; 尝试释放buffer/cache /proc/sys/vm/drop_caches dirty_ratio dirty_background_ratio dirty_writeback_centisecs dirty_expire_centisecs drop_caches page-cluster swap…

ideaSSM 人才引进管理系统bootstrap开发mysql数据库web结构java编程计算机网页源码maven项目

一、源码特点 idea 开发 SSM 人才引进管理系统是一套完善的信息管理系统&#xff0c;结合SSM框架和bootstrap完成本系统&#xff0c;对理解JSP java编程开发语言有帮助系统采用SSM框架&#xff08;MVC模式开发&#xff09;&#xff0c;系统具有完整的源代码和数据库&#xff…