数据结构:排序解析

文章目录

  • 前言
  • 一、常见排序算法的实现
    • 1.插入排序
      • 1.直接插入排序
      • 2.希尔排序
    • 2.交换排序
      • 1.冒泡排序
      • 2.快速排序
        • 1.hoare版
        • 2.挖坑版
        • 3.前后指针版
        • 4.改进版
        • 5.非递归版
    • 3.选择排序
      • 1.直接选择排序
      • 2.堆排序
    • 4.归并排序
      • 1.归并排序递归实现
      • 2.归并排序非递归实现
    • 5.计数排序
  • 二、排序算法复杂度及稳定性
  • 排序测试

前言

所谓排序,就是使一串记录,按照其中的某个或某些关键字的大小,递增或递减的排列起来的操作。排序在我们生活中非常常见,比如买东西看的销量,价格的对比等。排序也分为内部排序和外部排序。内部排序是数据元素全部放在内存中的排序,外部排序则是数据元素太多不能同时放在内存中,根据排序过程的要求不能在内外存之间移动数据的排序。下面让我们正式认识排序吧。

一、常见排序算法的实现

1.插入排序

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

1.直接插入排序

void  InsertSort(int* nums, int numsSize)
{int i = 0;//i变量控制的是整个比较元素的数量for (i = 0; i < numsSize; i++){int num = nums[i];//从后面一次和前面的元素进行比较,前面的元素大于后面的数据,则前面的元素向后移动int j = i - 1;while (j > -1){if (nums[j] > num){//要交换的元素小于前一个元素nums[j + 1] = nums[j];j--;}else{break;}}//把该元素填到正确的位置nums[j + 1] = num;}
}

在这里插入图片描述
测试用例:

void sortArray(int* nums, int numsSize)
{InsertSort(nums, numsSize);//插入排序
}
void print(int* nums, int numsSize)
{int i = 0;for (i = 0; i < numsSize; i++){printf("%d ", nums[i]);}
}
int main()
{int nums[] = { 3,9,0,-2,1 };int numsSize = sizeof(nums) / sizeof(nums[0]);//计算数组大小sortArray(nums, numsSize);//调用排序算法print(nums, numsSize);//打印排序结果return 0;
}

在这里插入图片描述
直接插入排序的优点:元素集合越接近有序,直接插入排序算法的时间效率越高。
时间复杂度:O(N ^2)
空间复杂度O(1)
直接插入排序是一种稳定的排序算法。

2.希尔排序

将待排序的序列分成若干个子序列,对每个子序列进行插入排序,使得整个序列基本有序,然后再对整个序列进行插入排序。是插入排序的改进

void ShellSort(int* nums, int numsSize)
{int group = numsSize;while (group > 1){//进行分组//加1为了保证最后一次分组为1,组后一次必须要进行正常的插入排序group = group / 3 + 1;int i = 0;//每次对分的组进行排序//和插入排序思路相同for (i = 0; i < numsSize; i++){int num = nums[i];int j = i - group;while (j >= 0){if (nums[j] > num){nums[j + group] = nums[j];j -= group;}else{break;}}nums[j + group] = num;}}
}

在这里插入图片描述
group为1时为插入排序,必须要保证最后一次group为1,这样排序才能正确。希尔排序法也称缩小增量法
希尔排序是对直接插入排序的优化。
会很快。这样整体而言,可以达到优化的效果。我们实现后可以进行性能测试的对比。
当group > 1时都是预排序,目的是让数组更接近于有序,让大的数能更快到达后面,小的数可以更快到达前面。当group = 1时,数组已经接近有序的了,这时间使用插入可以让插入排序时间复杂度接近O(N)。从而达到优化效果。希尔排序的时间复杂度大约为O(N^1.3)。
测试用例:

void sortArray(int* nums, int numsSize)
{//InsertSort(nums, numsSize);//插入排序ShellSort(nums, numsSize);//希尔排序
}
int main()
{int nums[] = { 3,9,0,-2,1 };int numsSize = sizeof(nums) / sizeof(nums[0]);//计算数组大小sortArray(nums, numsSize);//调用排序算法print(nums, numsSize);//打印排序结果return 0;
}

在这里插入图片描述

2.交换排序

1.冒泡排序

void BubbleSort(int* nums, int numsSize)
{int i = 0;//控制循环次数for (i = 0; i < numsSize; i++){int j = 0;//用记录该数组是否有序可以提前退出循环int flag = 0;//用来控制比较次数for (j = 0; j < numsSize - i - 1; j++){if (nums[j + 1] < nums[j]){swap(&nums[j], &nums[j + 1]);flag = 1;}}//当该此循环不在进行交换则证明数组已经有序,可以提前退出循环if (flag == 0){break;}}
}

在这里插入图片描述
冒泡排序非常容易理解,它的时间复杂度为O(N^2) ,空间复杂度:O(1)且很稳定。

2.快速排序

任取待排序元素序列中的某元素作为标准值,按照该排序码将待排序集合分成两段,左边中所有元素均小于该值,右边中所有元素均大于该值,然后左右两边重复该过程,直到所有元素都排列在相应位置上为止。

1.hoare版

void PartSort1(int* nums, int left, int right)
{//当区间不存在或者区间只有一个数时结束递归if (left >= right){return ;}int key = left;int begin = left;int end = right;while (begin < end){//右边先走,目的是结束是相遇位置一定比key值小//开始找比选定值小的元素while ((begin < end) && (nums[key] <= nums[end])){end--;}//开始找比选定值大的元素while ((begin < end) && (nums[begin] <= nums[key])){begin++;}//把两个数进行交换swap(&nums[begin], &nums[end]);}//把关键值和相遇点的值进行交换,由于右边先走,相遇值一定小于关键值swap(&nums[key], &nums[begin]);key = begin;//开始递归左边区间PartSort1(nums, left, key - 1);//开始递归右边区间PartSort1(nums, key + 1, right);
}

在这里插入图片描述

分别递归左右区间,直到递归为不可在分割的区间,是分治算法,每次递归都会有一个数回到正确的位置。

2.挖坑版

 void PartSort2(int* nums, int left, int right){if (left >= right){return;}   int hole = left;//坑的位置    int key = nums[left];//记录初始坑位置的值int begin = left;int end = right;while (begin < end){while ((begin < end) && (key <= nums[end])){end--;}   nums[hole] = nums[end];//把小于初始坑位置的填到坑中hole = end;//更新坑的位置while ((begin < end) && (nums[begin] <= key)){begin++;}nums[hole] = nums[begin];//把大于初始坑位置的填到坑中hole = begin;//更新坑的位置}//坑的位置放置初始坑位置的值nums[begin] = key;//开始递归左边区间PartSort2(nums, left, hole - 1);//开始递归右边区间PartSort2(nums, hole + 1, right);}

在这里插入图片描述
注意要先将第一个数据存起来,形成第一个坑位才可以进行覆盖。

3.前后指针版

void PartSort3(int* nums, int left, int right){if (left >= right){return;}//记录关键值int key = nums[left];//快指针为关键值的下一个位置int fast = left + 1;//慢指针为关键值的位置int slow = left;while (fast <= right){//当快指针的值小于关键值时if (nums[fast] < key){//当慢指针的下一个不为快指针时则不进行交换if (++slow != fast){swap(&nums[fast], &nums[slow]);				}}//对快指针进行移动fast++;//简写形式//if (nums[fast] < key && ++slow != fast)//{//	swap(&nums[slow], &nums[fast]);//}//++fast;}//关键值的位置和慢指针进行交换swap(&nums[left], &nums[slow]);//开始递归左边区间PartSort3(nums, left, slow - 1);//开始递归右边区间PartSort3(nums, slow + 1, right);}

在这里插入图片描述

4.改进版

当要排序的区间为有序时,我们排序就是最坏的情况,这时间就需要我们进行优化一下。
我们要加三数取中操作。

//三数取中
void middle(int* nums, int left, int right)
{//找到中间的数,交换到数组开头,因为我们关键值选则的为数组的左边值int middle = (left + right) / 2;if (nums[left] < nums[middle]){if (nums[middle] < nums[right]){swap(&nums[left], &nums[middle]);}else{swap(&nums[left], &nums[right]);}}else{if (nums[right] < nums[left]){swap(&nums[left], &nums[right]);}}
}
void QuickSort(int* nums, int left, int right)
{if (left >= right){return;}middle(nums, left, right);//把中间值换到排序的开始位置int key = left;int begin = left;int end = right;while (begin < end){//右边先走,目的是结束是相遇位置一定比key值小while ((begin < end) && (nums[key] <= nums[end])){end--;}while ((begin < end) && (nums[begin] <= nums[key])){begin++;}swap(&nums[begin], &nums[end]);}swap(&nums[key], &nums[begin]);key = begin;QuickSort(nums, left, key - 1);QuickSort(nums, key + 1, right);
}

我们实现的版本1的改进,版本2和3改进同理,只是增加一个调用函数。

5.非递归版

当我们拍的数据递归调用太深的情况就会造成栈破坏,所以非递归版本的快排也是重中之重。让我们实现一下吧。非递归中我们用到之前学的栈来辅助我们完成。

void QuickSortNonR(int* nums, int left, int right)
{Stack st;//创建栈StackInit(&st);//初始话栈StackPush(&st, right);//把要排序的右边界入栈,这时会先左边界先出栈StackPush(&st, left);//把要排序的左边界入栈while (!StackEmpty(&st))//如果栈不为空,则一直进行循环{int left = StackTop(&st);//获得要排序的左边界StackPop(&st);//把左边界出栈int right = StackTop(&st);//获得要排序的右边界StackPop(&st);//把右边界出栈if (left >= right)//如果边界不合法则跳过本次循环{continue;}//快速排序版本1int key = left;int begin = left;int end = right;while (begin < end){//右边先走,目的是结束是相遇位置一定比key值小while ((begin < end) && (nums[key] <= nums[end])){end--;}while ((begin < end) && (nums[begin] <= nums[key])){begin++;}swap(&nums[begin], &nums[end]);}swap(&nums[key], &nums[begin]);key = begin;StackPush(&st, key-1);//把左边界的结束位置入栈StackPush(&st, left);//把左边界的起始位置入栈StackPush(&st, right);//把右边界的结束位置入栈StackPush(&st, key+1);//把右边界的起始位置入栈}StackDestroy(&st);//销毁栈
}

在这里插入图片描述
快排在一般情况下效率非常高,且可以搭配其他排序进行小区间优化。它的时间复杂度为O(N*logN),空间复杂度为O(logN),但不稳定

3.选择排序

每一次从待排序的数据元素中选出最小(或最大)的一个值,存放在数据的起始位置,直到全部待排序的数据元素排完。

1.直接选择排序

void SelectSort(int* nums, int numsSize)
{int i = 0;for (i = 0; i < numsSize; i++){int min = i;//记录最小数的下标int j = 0;for (j = i; j < numsSize; j++)//开始寻找最小数{if (nums[j] < nums[min]){min = j;//记录下标}}if (min != i){swap(&nums[min], &nums[i]);//如果最小数和开始位置不相同则进行交换}}
}

在这里插入图片描述
直接选择排序非常好理解,但是效率太低。实际中很少使用

2.堆排序

堆的思想和树一样。堆排序是指利用堆积树(堆)这种数据结构所设计的一种排序算法,我们升序要建大堆,降序要建小堆

void AdjustDwon(int* nums, int n, int root)
{int left = root * 2 + 1;while (left < n){if (((left + 1) < n) && (nums[left] < nums[left + 1]))//当右子树存在并且右子树的值大于左子树{left = left + 1;//更新节点的下标}if (nums[root] < nums[left]){swap(&nums[root], &nums[left]);//如果根节点小于孩子节点,就进行交换root = left;//更新根节点left = root * 2 + 1;//更新孩子节点}else//已符合大堆结构,跳出循环{break;}}
}
//建大堆
void HeapSort(int* nums, int numsSize)
{int i = 0;//从第一个非叶子节点开始进行建堆,当左右都为大堆时才会排根节点for (i = (numsSize - 1 - 1) / 2; i >= 0; --i){AdjustDwon(nums, numsSize, i);}while (numsSize--){swap(&nums[0], &nums[numsSize]);//如果根节点小于孩子节点,就进行交换//调整堆结构AdjustDwon(nums, numsSize, 0);}
}

在这里插入图片描述

堆排序使用堆来选数,效率比直接排序高很多。它的时间复杂度为O(N*logN),且空间复杂度为O(1),但是不稳定。

4.归并排序

归并排序是建立在归并操作上的一种有效的排序算法,该算法是采用分治法。先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表。归并需要一个临时的空间来存放子序列,用来拷贝到源序列中

1.归并排序递归实现

void MergeSort(int* nums, int left, int right,int *tmp)
{if (left >= right){return;}//把区间拆分为两段int middle = (left + right) >> 1;//拆分MergeSort(nums, left, middle, tmp);MergeSort(nums, middle+1, right, tmp);//归并int begin1 = left;int begin2 = middle + 1;int end1 = middle;int end2 = right;int i = 0;//和链表的链接差不多//直到有一个区间结束结束循环while ((begin1 <= end1) && (begin2 <= end2)){//那个值小那个值进入开辟的数组if (nums[begin1] <= nums[begin2]){tmp[i++] = nums[begin1++];}else{tmp[i++] = nums[begin2++];}}//找到未完全结束的数组,并且把数组中的元素尾加到开辟的数组中while (begin1 <= end1){tmp[i++] = nums[begin1++];}while (begin2 <= end2){tmp[i++] = nums[begin2++];}//把开辟的数组中的内容拷贝到源数组中//拷贝时要注意拷贝时的位置memcpy(nums + left, tmp, (right - left + 1) * sizeof(int));
}

在这里插入图片描述

2.归并排序非递归实现

void MergeSortNonR(int* nums, int numsSize, int* tmp)
{//归并所用的数int gap = 1;int i = 0;while(gap < numsSize)//当归并使用的数小于数组大小时进行循环{for (i = 0; i < numsSize;)//用i来控制归并的位置{int begin1 = i;int begin2 = i + gap;int end1 = i + gap - 1;int end2 = i + 2 * gap - 1;//当end1越界时进行修正,此时begin2和end2都会越界时进行修正if (end1 > numsSize - 1){end1 = numsSize - 1;begin2 = numsSize + 1;end2 = numsSize;}//当begin2越界时进行修正,此时end2也会越界else if (begin2 > numsSize - 1){begin2 = numsSize + 1;end2 = numsSize;}//当end2越界时进行修正else if(end2 > numsSize - 1){end2 = numsSize - 1;}//开始进行归并while ((begin1 <= end1) && (begin2 <= end2)){if (nums[begin1] <= nums[begin2]){tmp[i++] = nums[begin1++];}else{tmp[i++] = nums[begin2++];}}//找到未结束的数组插入到临时数组中while (begin1 <= end1){tmp[i++] = nums[begin1++];}while (begin2 <= end2){tmp[i++] = nums[begin2++];}}//把临时数组的内容拷贝到源数组中memcpy(nums, tmp, numsSize * sizeof(int));//把归并的范围扩大gap *= 2;}
}

在这里插入图片描述
归并排序的非递归要注意边界的修正,不然会产生越界的情况。
归并的缺点在于需要O(N)的空间,但归并排序的思考更多的是解决在磁盘中的外排问题。可以当内排序,也可以当外排序使用,且时间复杂度为O(N*logN),是一种稳定的排序。

5.计数排序

void CountSort(int* nums, int numsSize)
{int i = 0;int min = nums[i];int max = nums[i];//找到原数组中的最大值和最小值for (i = 0; i < numsSize; i++){if (min > nums[i]){min = nums[i];}if (max < nums[i]){max = nums[i];}}//计算出排序中最大和最小值的差,加上1为要开辟临时数组的大小int num = max - min + 1;//创建相应的大小的空间int* tmp = (int*)malloc(sizeof(int) * num);//对创建的空间进行初始话,把里面的元素全部置0memset(tmp, 0, sizeof(int) * num);//遍历原数组,把该元素值的下标映射到临时数组中for (i = 0; i < numsSize; i++){tmp[nums[i] - min]++;}int j = 0;//遍历临时数组,把该元素不为0的恢复原值拷贝到原数组中for (i = 0; i < num; i++){while (tmp[i]--){nums[j++] = i + min;}}free(tmp);
}

在这里插入图片描述
计数排序在数据范围集中时,效率很高,但是适用范围及场景有限。

二、排序算法复杂度及稳定性

排序方法平均情况最好情况最坏情况空间消耗稳定性
直接插入排序O(N^2)O(N)O(N^2)O(1)稳定
希尔排序O(N*logN)~O(N^2)O(N^1.3)O(N^2)O(1)不稳定
冒泡排序O(N^2)O(N)O(N^2)O(1)稳定
快速排序O(N*logN)O(N*logN)O(N^2)O(N*logN)~O(N)不稳定
选择排序O(N^2)O(N^2)O(N^2)O(1)不稳定
堆排序O(N*logN)O(N*logN)O(N*logN)O(1)不稳定
归并排序O(N*logN)O(N*logN)O(N*logN)O(N)稳定

排序测试

int tmp1[20];
int tmp2[20];
int tmp3[20];
int tmp4[20];
int tmp5[20];
int tmp6[20];
int tmp7[20];
int tmp8[20];
int tmp9[20];
int tmp10[20];
int tmp11[20];
int tmp12[20];
int tmp13[20];
void init()
{int i = 0;int nums = 0;for (i = 0; i < 20; i++){nums = rand() % 100;tmp1[i] = nums;tmp2[i] = nums;tmp3[i] = nums;tmp4[i] = nums;tmp5[i] = nums;tmp6[i] = nums;tmp7[i] = nums;tmp8[i] = nums;tmp9[i] = nums;tmp10[i] = nums;tmp11[i] = nums;tmp12[i] = nums;tmp13[i] = nums;}
}
void test()
{int numsSize = 20;InsertSort(tmp1, numsSize);//插入排序ShellSort(tmp2, numsSize);//希尔排序BubbleSort(tmp3, numsSize);//冒泡排序PartSort1(tmp4, 0, numsSize - 1);//快排1PartSort2(tmp5, 0, numsSize - 1);//快排2PartSort3(tmp6, 0, numsSize - 1);//快排3QuickSort(tmp7, 0, numsSize - 1);//快排改进QuickSortNonR(tmp8, 0, numsSize - 1);//快排非递归SelectSort(tmp9, numsSize);HeapSort(tmp10, numsSize);int* tmp = (int*)malloc(sizeof(int) * numsSize);MergeSort(tmp11, 0, numsSize - 1, tmp);MergeSortNonR(tmp12, numsSize - 1, tmp);CountSort(tmp13, numsSize);free(tmp);
}
void print(int* nums, int numsSize)
{int i = 0;for (i = 0; i < numsSize; i++){printf("%d ", nums[i]);}printf("\n");
}
void Print()
{print(tmp1, 20);print(tmp2, 20);print(tmp3, 20);print(tmp4, 20);print(tmp5, 20);print(tmp6, 20);print(tmp7, 20);print(tmp8, 20);print(tmp9, 20);print(tmp10, 20);print(tmp11, 20);print(tmp12, 20);print(tmp13, 20);
}
int main()
{srand((unsigned)time());//int nums[] = { 3,9,0,-2,1 };//int numsSize = sizeof(nums) / sizeof(nums[0]);//计算数组大小//sortArray(nums, numsSize);//调用排序算法init();//对排序的数组赋值test();//调用各个排序函数//print(nums, numsSize);//打印排序结果Print();//打印各个排序结果return 0;
}

在这里插入图片描述

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

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

相关文章

训练简单的线性模型,预测电影评分和票房收入

文章目录 训练简单的线性模型&#xff0c;预测电影评分和票房收入数据集加载数据可视化数据分割数据集训练模型可视化结果应用模型保存和加载模型 训练简单的线性模型&#xff0c;预测电影评分和票房收入 这是一个简单的线性模型&#xff0c;用于预测电影的评分和票房收入。不…

idea全局搜索失效,Ctrl+shift+F快捷键不起作用

方法1&#xff1a;是否与搜狗等输入法软件存在快捷键冲突&#xff0c;当然也可能是你新下载的什么软件导致的快捷键冲突导致IDEA全局搜索失效。比如下图&#xff1a; 可以改掉输入法的快捷键或者直接关闭输入法的快捷键&#xff0c;这样idea的全局搜索功能就恢复了。 方法2&…

1.9 动态解密ShellCode反弹

动态解密执行技术可以对抗杀软的磁盘特征查杀。其原理是将程序代码段中的代码进行加密&#xff0c;然后将加密后的代码回写到原始位置。当程序运行时&#xff0c;将动态解密加密代码&#xff0c;并将解密后的代码回写到原始位置&#xff0c;从而实现内存加载。这种技术可以有效…

【Cookie和Session的那些事儿】

&#x1f320;作者&#xff1a;TheMythWS. &#x1f386;专栏&#xff1a;《集合与数据结构》 &#x1f387;座右铭&#xff1a;不走心的努力都是在敷衍自己&#xff0c;让自己所做的选择&#xff0c;熠熠发光。 目录 认识Cookie和Session Cookie Cookie对象的特点 Cookie对…

Unity 之 参数类型之值类型参数的用法

文章目录 基本数据类型结构体结构体的进一步补充 总结&#xff1a; 当谈论值类型参数时&#xff0c;我们可以从基本数据类型和结构体两个方面详细解释。值类型参数指的是以值的形式传递给函数或方法的数据&#xff0c;而不是引用。 基本数据类型 基本数据类型的值类型参数&…

数据库介绍

一.什么是数据库&#xff1f; 通俗的来讲数据库就是用来存放数据的地方&#xff0c;可以理解为和冰箱一样 官方&#xff1a; 数据库&#xff08;Database&#xff09;是按照数据结构来组织、存储和管理数据的仓库。 每个数据库都有一个或多个不同的 API 用于创建&#xff0c;…

说说Flink双流join

分析&回答 Flink双流JOIN主要分为两大类 一类是基于原生State的Connect算子操作另一类是基于窗口的JOIN操作。其中基于窗口的JOIN可细分为window join和interval join两种。 基于原生State的Connect算子操作 实现原理&#xff1a;底层原理依赖Flink的State状态存储&…

11.添加侧边栏,并导入数据

修改CommonAside的代码&#xff1a; <template><div><el-menu default-active"1-4-1" class"el-menu-vertical-demo" open"handleOpen" close"handleClose":collapse"isCollapse"><!--<el-menu-it…

UE5打完包后,启动程序不能全屏

最近看到ue5的打包程序后不能默认自动全屏&#xff0c;效果如下&#xff0c;发现并不是全屏的&#xff0c;而且就算点击放大也不是全屏 解决办法&#xff1a;设置如下之后在打包就可以了 但是会一直打印错误的日志&#xff0c;不过这个不影响使用

芯片开发之难如何破解?龙智诚邀您前往DR IP-SoC China 2023 Day

2023年9月6日&#xff08;周三&#xff09;&#xff0c;龙智即将亮相D&R IP-SoC China 2023 Day&#xff0c;呈现集成了Perforce与Atlassian产品的芯片开发解决方案&#xff0c;助力企业更好、更快地进行芯片开发。 龙智资深顾问、技术支持部门负责人李培将带来主题演讲—…

(数字图像处理MATLAB+Python)第十一章图像描述与分析-第三、四节:几何表述和形状描述

文章目录 一&#xff1a;几何描述&#xff08;1&#xff09;像素间几何关系A&#xff1a;邻接与连通B&#xff1a;距离 &#xff08;2&#xff09;像素间几何特征A&#xff1a;位置B&#xff1a;方向C&#xff1a;尺寸 &#xff08;3&#xff09;程序 二&#xff1a;形状描述&a…

yolov5自定义模型训练三

经过11个小时cpu训练完如下 在runs/train/expx里存放训练的结果&#xff0c; 测试是否可以检测ok 网上找的这张识别效果不是很好&#xff0c;通过加大训练次数和数据集的话精度可以提升。 训练后的权重也可以用视频源来识别&#xff0c; python detect.py --source 0 # webca…

Fiddler Response私人订制

在客户端接口的测试中&#xff0c;我们经常会需要模拟各种返回状态或者特定的返回值&#xff0c;常见的是用Fiddler模拟各种请求返回值场景&#xff0c;如重定向AutoResponder、请求拦截修改再下发等等。小编在近期的测试中遇到的一些特殊的请求返回模拟的测试场景&#xff0c;…

docker作业

目录 1、使用mysql:5.6和 owncloud 镜像&#xff0c;构建一个个人网盘。 1.1启动镜像 1.2启动cloud镜像 1.3浏览器访问 ​编辑 2、安装搭建私有仓库 Harbor 2.1下载docker-compose 2.2 磁盘挂载&#xff0c;保存harbor 2.3 修改配置文件 2.4安装 2.5浏览器访问 2.6 新…

MybatisPlus(2)

前言&#x1f36d; ❤️❤️❤️SSM专栏更新中&#xff0c;各位大佬觉得写得不错&#xff0c;支持一下&#xff0c;感谢了&#xff01;❤️❤️❤️ Spring Spring MVC MyBatis_冷兮雪的博客-CSDN博客 上篇我们简单介绍了MybatisPlus的方便之处&#xff0c;这篇来深入了解Myb…

代码随想录算法训练营第二十四天|理论基础 77. 组合

理论基础 其实在讲解二叉树的时候&#xff0c;就给大家介绍过回溯&#xff0c;这次正式开启回溯算法&#xff0c;大家可以先看视频&#xff0c;对回溯算法有一个整体的了解。 题目链接/文章讲解&#xff1a;代码随想录 视频讲解&#xff1a;带你学透回溯算法&#xff08;理论篇…

Maven之高版本的 lombok 和 tomcat 7 插件冲突问题

高版本的 lombok 和 tomcat 7 插件冲突问题 在开发期间&#xff0c;当我们使用 tomcat7-maven-plugin 来作为运行环境运行我们项目使&#xff0c;如果我们项目中使用了 1.16.20 及以上版本的 lombok 包&#xff0c;项目启动时会报错&#xff1a; for annotations org.apache.…

使用代理服务器和pip安装软件包

在开着代理服务器的情况下&#xff0c;直接pip install 软件包名会出现如下错误&#xff0c; WARNING: Retrying (Retry(total4, connectNone, readNone, redirectNone, statusNone)) after connection broken by SSLError(SSLZeroReturnError(6, TLS/SSL connection has been…

设计模式--代理模式(Proxy Pattern)

一、什么是代理模式&#xff08;Proxy Pattern&#xff09; 代理模式&#xff08;Proxy Pattern&#xff09;是一种结构型设计模式&#xff0c;它允许一个对象&#xff08;代理&#xff09;充当另一个对象&#xff08;真实对象&#xff09;的接口&#xff0c;以控制对该对象的…

智能工厂移动式作业轻薄加固三防平板数据采集终端

在这个高度自动化和数字化的环境中&#xff0c;数据采集变得尤为重要。为了满足这个需求&#xff0c;工业三防平板数据采集终端应运而生。工业三防平板数据采集终端采用了轻量级高强度镁合金材质&#xff0c;这使得它在保持轻薄的同时具有更强的坚固性。这种材质还具有耐磨防损…