【数据结构初阶】九、五种比较排序的讲解和实现(直接插入 \ 希尔 \ 直接选择 \ 堆 \ 冒泡 -- C语言)

=========================================================================

相关代码gitee自取

C语言学习日记: 加油努力 (gitee.com)

 =========================================================================

接上期

【数据结构初阶】八、非线性表里的二叉树(二叉树的实现 -- C语言链式结构)-CSDN博客

 =========================================================================

                     

排序

排序的概念

所谓排序,就是使一串记录
按照其中的某个或某些关键字的大小递增或递减排列起来的操作
                 

稳定性

假定在待排序的记录序列中存在多个具有相同关键字的记录
经过排序这些记录的相对次序保持不变
即在原序列中 r [ i ] = r [ j ] , r [ i ] r [ j ] 之前
在排序后的序列中r [ i ] 仍在 r [ j ] 之前
称这种排序算法是稳定的否则称为不稳定的

                 

内部排序(内排序)

数据元素全部放在内存中的排序内存中进行排序

属于内排序的排序算法
  • 插入排序
    直接插入排序 、希尔排序
                   
  • 选择排序
    直接选择排序 、排序
                    
  • 交换排序
    冒泡排序 、快速排序
                   
  • 并归排序(即属于内排序又属于外排序

                 

外部排序(外排序)

数据元素太多不能同时放在内存中

根据排序过程的要求不能在内外存之间移动数据的排序

即在磁盘中(“顺序写顺序读”)进行排序

属于外排序的排序算法
  • 并归排序(即属于内排序又属于外排序

                

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

                 

常见排序算法的实现

(详细解释在图片的注释中,代码分文件放下一标题处)

                   

一、插入排序

                        

插入排序 -- 直接插入排序

直接插入排序是一种简单的插入排序法

                 

该算法基本思想:

待排序的记录按其关键码值的大小逐个插入到一个已经排好序的有序序列中

直到所有的记录插入完为止得到一个新的有序序列
(想象我们玩扑克牌时给扑克牌大小排序就用了插入排序的思想

                      

实现思路:

插入第 i(i>=1) 个元素时
前面的 array[0]array[1],…,array[i-1] 已经排好序
此时 array[i] 的排序码 array[i-1]array[i-2],… 的排序码顺序进行比较
找到插入位置后 array[i] 插入原来位置上的元素顺序后移覆盖

                     

直接插入排序的特性总结:
  • 元素越接近有序直接插入排序算法时间效率越高 -- 最高可达O(N)
                            
  • 该算法时间复杂度O(N^2) -- 最坏的情况下(逆序)
                                
  • 该算法空间复杂度O(1)
                          
  • 该算法稳定性稳定
                      

---------------------------------------------------------------------------------------------

                       

InsertSort函数 -- 直接插入排序实现函数

  • 使用for循环进行循环插入排序
    设置前元素” 和 “后元素
                           
  • for循环中
    使用while循环后元素寻找合适位置
    找到后再将后元素插入
    之后再次进行for循环让下个后元素插入合适位置
图示:

该函数执行逻辑图:

对应函数测试:

            

            

---------------------------------------------------------------------------------------------

            

插入排序 -- 希尔排序(缩小增量排序)

希尔排序又称缩小增量法

             

该算法基本思想:

先选定一个整数gap值待排序文件中所有记录分成gap个组

所有距离为gap的记录分在同一组内,并对每一组内的记录进行直接插入排序

然后换个整数gap值再取gap组重复上述分组和排序的工作

gap=1 所有记录在同一组内时已经排好序了

               

希尔排序的特性总结:
  • 希尔排序直接插入排序的优化
                  
  • gap>1 时都是在进行预排序,目的是让数组更接近于有序
    gap==1 数组已经接近有序的了,这样再进行直接插入排序就会很快
    这样整体而言,可以达到优化的效果
                                  
  • 希尔排序的时间复杂度不好计算,因为gap的取值方法很多导致很难去计算
    因此在一些书中给出的希尔排序的时间复杂度也不固定,
    该函数大概的时间复杂度为:O(N^1.3)
                           
  • 该算法稳定性不稳定
                             

---------------------------------------------------------------------------------------------

                       

ShellSort函数 -- 希尔排序实现函数

  • 核心实现操作还是直接插入排序
    但是在对所有值进行直接插入排序先进行多次预排序操作
    预排序也是用直接插入排序完成)
    让数组达到尽量有序的状态
                  
  • 定义gap值变量,使用while循环控制多次预排序
    (当gap==1时,就相当于直接插入排序
                    
  • while循环中内嵌for循环完成当前gap组”的预排序
                     
  • 再内嵌for循环完成当前gap组其中一组的预排序
    (通过直接插入排序的方式实现)
                    
    • 最后再内嵌while循环配合完成直接插入排序
图示:

该函数执行逻辑图:

对应函数测试:

                     

                     


                    

二、选择排序

基本思想:

每一趟排序从待排序的数组元素中分别选择出最小最大的一个元素
再分别存放在数组的起始位置尾部位置
直到全部待排序的数组元素排序完成

                

                

选择排序 -- 直接选择排序

                    

该算法基本思想:

元素集合 array[i] -- array[n-1] 选择获取当前最小值元素当前最大值元素
当前最小值元素交换后放到当前数组起始位置
当前最大值元素交换后放到当前数组尾部位置

在剩余的 array[i+1] -- array[n-2] 集合中,重复上述操作直到集合剩余1个元素
               

直接选择排序的特性总结:
  • 直接选择排序比较好理解,但是效率不高实际很少使用
                      
  • 该算法时间复杂度O(N^2)
                         
  • 该算法空间复杂度O(1)
                       
  • 该算法稳定性不稳定
                         

---------------------------------------------------------------------------------------------

                       

SelectSort函数 -- 直接选择排序实现函数

  • 定义 数组开始(初始)位置下标begin 数组尾部(结束)位置下标end 变量
    使用while循环控制多趟直接选择排序
                        
  • (在while循环中完成一趟直接选择排序
    定义 存放当前最小值下标mini 存放当前最大值下标maxi 变量
    内嵌for循环遍历一次当前数组找到当前最大值当前最小值
                       
  • while循环中for循环外:)
    将找到的当前数组最小值放入数组起始左边位置
    当前数组最大值放入数组尾部右边位置,
    完成两值的排序后调整 begin end 变量缩小数组范围准备下趟直接选择排序
图示:

该函数执行逻辑图:

对应函数测试:

            

            

---------------------------------------------------------------------------------------------

            

选择排序 -- 堆排序

是一种完全二叉树
可以使用堆中的向下调整操作对普通数组进行排序升序降序

               

堆排序的特性总结:
  • 堆排序使用进行选择排序效率高了很多
                      
  • 该算法时间复杂度O(N*logN)
                         
  • 该算法空间复杂度O(1)
                       
  • 该算法稳定性不稳定
                         

---------------------------------------------------------------------------------------------

                       

堆排序的实现往期博客中已有详细描述:

【数据结构初阶】七、非线性表里的二叉树(堆的实现 -- C语言顺序结构)-CSDN博客

(包含堆排序实现函数图示对应函数执行逻辑图函数测试原代码

                     

                     


                    

三、交换排序

基本思想:

所谓交换,就是根据序列中两个记录键值的比较结果交换这两个记录在序列中的位置

             

交换排序的特点:

键值较大的记录序列的尾部移动键值较小的记录序列的前部移动

                      

                      

交换排序 -- 冒泡排序

                     

该算法基本思想:

数组中的元素1元素2进行比较,如果元素1大于元素2,则交换两者位置

比较此时的元素2元素3,如果元素2大于元素3,则交换两者位置

再比较此时的元素3元素4……

一趟冒泡排序完成后,就能完成当前数组中最大值的排序排在尾部),
再进行下一趟冒泡排序前缩小数组排序范围排除已经排序好的最大值),

这样多趟冒泡排序完成后就能完成数组的排序

                     

冒泡排序的特性总结:
  • 冒泡排序是一种非常容易理解的排序
                      
  • 该算法时间复杂度O(N^2)
                  
  • 该算法空间复杂度O(1)
                          
  • 该算法稳定性稳定
                           

---------------------------------------------------------------------------------------------

                       

BubbleSort函数 -- 冒泡排序实现函数

  • 定义嵌套for循环完成冒泡排序
    外层for循环控制当前数组范围数组范围慢慢减小
    减到变成1时排序完成至少有两个数才能比较
                            
  • 内层for循环循环一趟完成当前数组范围内的最值的排序
                        
  • 当前冒泡排序过程中
    设置一个变量exchange记录当前一趟冒泡排序过程中是否有发生元素的交换
    趟冒泡排序后,如果没有任何元素发生交换
    说明目前已经排好序了,那就直接终止之后的冒泡排序
图示:

该函数执行逻辑图:

对应函数测试:

                 

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

                      

对应代码:

Sort.h -- 排序头文件

#pragma once//包含之后所需头文件:
#include <stdio.h>//打印数组函数:
void PrintArray(int* a, int n);//直接插入排序函数:
//第一个参数:接收要排序的数组首元素地址(a)
//第二个参数:接收该数组的长度(n)
void InsertSort(int* a, int n);//希尔排序函数:
//第一个参数:接收要排序的数组首元素地址(a)
//第二个参数:接收该数组的长度(n)
void ShellSort(int* a, int n);
//1、预排序:分组排,间隔为gap(间距间隔)分为一组
//				预排序意义:
// 让大的数更快的到数组后面,小的数更快的到数组前面,
// gap值越大“跳”得越快,但是越不接近有序
// gap值越小“跳”得越慢,但是越接近有序
// 当gap==1时,就相当于直接插入排序
//2、直接插入排序//冒泡排序函数:
//第一个参数:接收要排序的数组首元素地址(a)
//第二个参数:接收该数组的长度(n)
void BubbleSort(int* a, int n);	//直接选择排序函数:
//第一个参数:接收要排序的数组首元素地址(a)
//第二个参数:接收该数组的长度(n)
void SelectSort(int* a, int n);

            

            

---------------------------------------------------------------------------------------------

            

Sort.c -- 排序函数实现文件

#define _CRT_SECURE_NO_WARNINGS 1//包含排序头文件:
#include "Sort.h"//打印数组函数:
void PrintArray(int* a, int n)
{for (int i = 0; i < n; i++){printf("%d ", a[i]);}printf("");
}//直接插入排序函数(升序):
//第一个参数:接收要排序的数组首元素地址(a)
//第二个参数:接收该数组的长度(n)
void InsertSort(int* a, int n)
{//使用for循环进行循环插入排序:/*要取“前后元素”,“后元素”要依次和“前面所有元素”进行比较,直到“后元素”找到合适位置并插入,而“后元素”下标最大为[n-1],所以“前元素”下标最大为[n-2]*/for (int i = 0; i < n - 1; i++)//循环到 i = n-2  --  “前元素”下标最大为[n-2]:{//遍历下标的起始位置从 0 开始,到 n-2 结束:int end = i; //“前元素”//保存end下标元素的后一个元素:int tmp = a[end + 1]; //“后元素”//使用while循环为“后元素”寻找合适位置://(“后元素”循环和其前面所有元素进行比较,直到找到合适位置)while (end >= 0)//“前面所有元素”:下标 >=0 时就还有 “前元素”,//那“后元素”就需要继续进行比较:{if (tmp < a[end])//“后元素” 小于 “前元素”:{//那就将“前元素(较大)”往后插入(覆盖):a[end + 1] = a[end];//a[end + 1],被覆盖的元素还保留在tmp中,//所以不用担心覆盖后找不到“后元素”}else//"后元素" 大于等于 "前元素":{//说明“后元素”的“前面较大元素”都已经往后覆盖完成了,//找到了"后元素"的恰当位置,//break退出循环将“后元素”tmp插入该位置break;}end--;//当前end--,下次循环判断“前前元素”需不需要再往前覆盖,//end减到-1退出while循环的话,说明“后元素”是数组中最小的元素,//导致其前面所有元素都需要往后覆盖挪出位置}//注意,合适的位置是[end + 1],//因为"后元素" 大于等于 "前元素"的话,//那“后元素”就理应排在“前元素”后面,即[end + 1],a[end + 1] = tmp;//如果是end减到-1退出的while循环,//那[end + 1]就等于0,即数组首元素位置,//让“后元素”排在数组首元素位置}
}
//时间复杂度:
//O(N^2) -- 逆序(最坏情况)
//O(N) -- 顺序有序
//冒泡排序和插入排序论时间复杂度它们是同一档次,
//但在细节上,如局部有序,插入排序会更优//希尔排序函数:
//第一个参数:接收要排序的数组首元素地址(a)
//第二个参数:接收该数组的长度(n)·
void ShellSort(int* a, int n)
{//定义分组间隔和分组个数:int gap = n;//只要当前预排序gap值还没到1,//while循环就继续循环进行预排序:while (gap > 1){//变化gap值进行多次预排序,//让数组越来越接近有序:gap = gap / 2;//当 gap > 1 时就是预排序//当 gap == 1 时就是插入排序//这个for循环控制 “当前gap组” 的排序://(一组“gap分”组排完再排另一组gap分组)for (int j = 0; j < gap; j++)/** 假设gap取3,* 就在数组中以3(gap)为间隔取数为一组(gap分组)* 总共取3(gap)组*/{//这个for循环控制gap组中其中一组的排序:for (int i = 0; i < n - gap; i += gap)/**					循环条件:n - gap  *控制“前元素end”范围,保证“后元素tmp”通过end取值时不出界*					迭代条件:i += gap*i每次迭代时就+gap,实现以gap为间隔取数为一组(gap分组)*/{//保存当前分组的“前元素”(记录):int end = i;//保存当前分组的“后元素”(记录):int tmp = a[end + gap];//使用while循环为“后元素”寻找合适位置://(“后元素”循环和其前面所有元素进行比较,直到找到合适位置)//(和直接插入类似,只是值与值间隔不同)while (end >= 0)//“前面所有元素”:下标 >=0 时就还有 “前元素”,//那“后元素”就需要继续进行比较:{if (tmp < a[end])//“后元素” 小于 “前元素”:{//(gap分组中:)//那就将“前元素(较大)”往后插入(覆盖):a[end + gap] = a[end];//a[end + gap],被覆盖的元素还保留在tmp中,//所以不用担心覆盖后找不到“后元素”end -= gap;//(gap分组中:)//当前end-=gap,下次循环判断“前前元素”需不需要再往前覆盖,//end减到<0时,退出while循环的话,说明“后元素”是数组中最小的元素,//导致其前面所有元素都需要往后覆盖挪出位置}else//"后元素" 大于等于 "前元素":{//说明“后元素”的“前面较大元素”都已经往后覆盖完成了,//找到了"后元素"的恰当位置,//break退出循环将“后元素”tmp插入该位置break;}}//注意,合适的位置是[end + gap],//因为"后元素" 大于等于 "前元素"的话,//那“后元素”就理应排在“前元素”后面,即[end + gap],a[end + gap] = tmp;//如果是 end减到<0 退出的while循环,//那[end + gap]就找到当前gap组首元素位置,//让“后元素”排在当前gap组首元素位置}}}
}//两值交换函数:
void Swap(int* x, int* y)
{//创建中间值进行值的交换:int tmp = *x;*x = *y;*y = tmp;
}//冒泡排序函数:
//第一个参数:接收要排序的数组首元素地址(a)
//第二个参数:接收该数组的长度(n)
void BubbleSort(int* a, int n)
{/** 定义嵌套for循环完成冒泡排序:* 内层for循环一趟完成当前数组范围内的最值的排序* 外层for循环则控制当前数组范围* 数组范围慢慢减小,减到变成1时排序完成* (至少有两个数才能比较)*///这个for循环控制内嵌for循环的数组范围:for (int j = 0; j < n; j++){int exchange = 0; //如果没发生交换该变量就为0//内嵌for循环进行循环比较交换:for (int i = 1; i < n-j; i++)/**n-j :通过判断条件控制数组范围*因为一趟下来就完成一个当前最值的排序,*下次再排序的数组范围就要排除这个已经排好序的最值,*通过外部for循环的j来控制数组范围:*/{if (a[i - 1] > a[i])//如果“前元素” 大于 “当前元素”://( i 从1开始){//进行交换:Swap(&a[i - 1], &a[i]);exchange = 1;//如果发生了变化该变量就为1}}/** 内嵌for循环整个执行完就是一趟,* 当遇到最大值后,因为最大所以会一直被交换* 直到被交换至数组尾部,* 这就完成了当前数组最大值的排序*/if (exchange == 0)//一趟冒泡排序后,如果没有发生交换:{//说明目前已经排好序了,//就没必要再进行之后的冒泡排序了:break;} }
}//直接选择排序函数:
//第一个参数:接收要排序的数组首元素地址(a)
//第二个参数:接收该数组的长度(n)
void SelectSort(int* a, int n)
{/** 思路:* 排序一趟选出当前最小值下标和当前最大值下标,* 通过对应下标将最小值放“左边”,最大值放“右边”*///数组开始位置下标 -- 0int begin = 0;//数组尾部(结束)位置下标 -- n-1int end = n - 1;//使用while循环控制多趟直接选择排序:while (begin < end)/** 只要 begin 还小于 end,左右下标就还没重合* begin 和 end 之间就还有元素要被排序*/{//对当前数组范围进行一趟直接选择排序://存放当前最小值下标:int mini = begin; //默认为下标0//存放当前最大值下标:int maxi = begin; //默认为下标0//使用for循环遍历一次当前数组,//找到当前最大值和当前最小值:for (int i = begin+1; i <= end; i++)/** mini 和 maxi 默认下标都是0* 所以循环时下标从[begin+1]开始,等于[n-1]结束*/{//选出当前最大值下标:if (a[i] > a[maxi])//如果“i下标元素”大于“maxi下标元素”:{//将较大值下标i赋给maxi下标:maxi = i;}//选出当前最小值下标:if (a[i] < a[mini])//如果“i下标元素”小于“mini下标元素”:{//将较小值下标i赋给mini下标:mini = i;}} //(for循环中)//将找到的当前数组最小值放入数组起始(左边)位置:Swap(&a[begin], &a[mini]);/** 注:如果begin下标元素为最大值,* 那么maxi下标也会指向该元素,即begin == maxi,* 当begin元素和mini交换后(只是值交换),* begin 和 maxi下标还是重叠在原位置,指向交换后的mini元素* 此时如果再执行 Swap(&a[end], &a[maxi]);* 就反而会将最小值移到数组尾部去,* 所以要调整 begin==maxi 重叠的情况:*/if (maxi == begin)//排除maxi和begin下标重叠的情况:{//maxi==begin等于当前最大值下标,上面交换后,//当前最大值就在mini下标处,//那就把maxi最大值下标指向mini下标处即可:maxi = mini;}//将找到的当前数组最大值放入数组尾部(右边)位置:Swap(&a[end], &a[maxi]);/** 执行到这就选出了两个最值并放到了合适位置(一趟直接选择排序),* 调整 begin 和 end 下标(调整数组范围),数组范围往中间缩小,* 再开始新一趟直接选择排序:*/++begin;--end;} //(while循环中)
}
//时间复杂度:O(N^2)

            

            

---------------------------------------------------------------------------------------------

            

Test.c -- 排序测试文件

#define _CRT_SECURE_NO_WARNINGS 1//包含排序头文件:
#include "Sort.h"//插入排序测试:
void ISTest()
{//创建要进行插入排序的数组:int a[] = { 3,4,2,1,5 };//调用插入排序函数进行排序:InsertSort(a, 5);//循环打印排序后的数组:printf("使用直接插入排序后的数组:> ");for (int i = 0; i < 5; i++){printf("%d ", a[i]);}
}//希尔排序测试:
void SSTest()
{//创建要进行插入排序的数组:int a[] = { 9,1,2,5,7,4,8,6,3,5 };//调用希尔排序函数进行排序:ShellSort(a, sizeof(a) / sizeof(int));//使用自定义打印函数打印排序后数组:printf("使用希尔排序后的数组:> ");PrintArray(a, sizeof(a) / sizeof(int));
}//冒泡排序测试:
void BSTest()
{//创建要进行插入排序的数组:int a[] = { 9,1,2,5,7,4,8,6,3,5 };//调用冒泡排序函数进行排序:BubbleSort(a, sizeof(a) / sizeof(int));//使用自定义打印函数打印排序后数组:printf("使用冒泡排序后的数组:> ");PrintArray(a, sizeof(a) / sizeof(int));
}//直接选择排序测试:
void SlSTest()
{//创建要进行插入排序的数组:int a[] = { 9,1,2,5,7,4,8,6,3,5 };//调用直接选择排序函数进行排序:SelectSort(a, sizeof(a) / sizeof(int));//使用自定义打印函数打印排序后数组:printf("使用直接选择排序后的数组:> ");PrintArray(a, sizeof(a) / sizeof(int));
}int main()
{//ISTest();//SSTest();//BSTest();SlSTest();return 0;
}

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

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

相关文章

网络编程(IP、端口、协议、UDP、TCP)【详解】

目录 1.什么是网络编程&#xff1f; 2.基本的通信架构 3.网络通信三要素 4.UDP通信-快速入门 5.UDP通信-多发多收 6.TCP通信-快速入门 7.TCP通信-多发多收 8.TCP通信-同时接收多个客户端 9.TCP通信-综合案例 1.什么是网络编程&#xff1f; 网络编程是可以让设…

Web开发学习-HTML

第一天 固定结构 如何注释&#xff1a;vs code中使用ctrl/可以达到注释这一行的效果&#xff0c;同时再次按下ctrl/&#xff0c;可以取消注释。 HTML标签的结构 例如&#xff1a;<strong>字体加粗</strong>这个就是双标签&#xff0c;<br>换行标签&#xff…

[RoarCTF 2019]Easy Calc

这题考查的是: 字符串解析特性目录读取文件内容读取 字符串解析特性详解&#xff1a;PHP字符串解析特性 &#xff08;$GET/$POST参数绕过&#xff09;&#xff08;含例题 buuctf easycalc&#xff09;_参数解析 绕过-CSDN博客 ascii码查询表&#xff1a;ASCII 表 | 菜鸟工具 …

flurl升级之后没有FlurlNewtonsoftJsonSerializer

新建NewtonsoftJsonSerializer.cs /// <summary> /// ISerializer implementation based on Newtonsoft.Json. /// Default serializer used in calls to GetJsonAsync, PostJsonAsync, etc. /// </summary> public class NewtonsoftJsonSerializer : IJsonSerial…

【贪心算法】Leetcode 455.分发饼干 376. 摆动序列 53. 最大子数组和

【贪心算法】Leetcode 455 分发饼干 376. 摆动序列【规律很多】53. 最大子数组和 455 分发饼干局部最优推全局最优&#xff1a;尽量用大饼干去满足大胃口的小朋友 376. 摆动序列【规律很多】思想&#xff1a;注意考虑一个坡度留首尾两个点、平坡、首尾 53. 最大子数组和【好思想…

18个惊艳的可视化大屏(第12辑):智慧校园与教育方向

智慧校园可视化大屏通过数据可视化技术&#xff0c;将学校各个方面的数据信息进行展示&#xff0c;可以提高信息公开透明度、优化校园管理、提高学生教育质量和提高校内活动宣传效果等。 1提高信息公开透明度&#xff1a; 通过大屏幕展示校园各个方面的数据信息&#xff0c;可…

MyBatisPlus(SpringBoot版)的分页插件

目录 一、前置工作: 1.整体项目目录结构 2.创建普通javamaven项目。 3.导入依赖&#xff0c;改造成springboot项目 4.配置启动类 5.创建service接口及其实现类 6.创建接口Mapper 7.配置数据源 8.创建数据库表 二、使用MP&#xff08;mybatisplus&#xff09;的分页插件 二、使…

COMPOSER安装使用WIN下升级PHP-V

想用TP6使用phpspreadsheet但是说我PHP版本低&#xff0c;原来是PHP7.0 composer要求至少7.4 直接修改环境变量&#xff0c;把PHP目录切换到7.4 composer升级比较简单&#xff0c;在PHP目录下CMD然后官网的命令执行下即可 下面就可以在TP根目录下执行命令安装PHPSPREADSHEET…

Docker数据集与自定义镜像:构建高效容器的关键要素

目录 博客前言 一.数据卷 1.数据卷介绍 2.实战 宿主机和容器共享目录 容器和容器之间共享目录 二.自定义镜像 1.自定义镜像介绍 2.实战 2.1自定义centos&#xff0c;具备vim及ifconfig作用 构建镜像 通过镜像运行一个容器进行测试 2.2自定义tomact&#xff08;文件为…

【IO流系列】字符流练习(拷贝、文件加密、修改文件数据)

字符流练习 练习1&#xff1a;文件夹拷贝1.1 需求1.2 代码实现1.3 输出结果 练习2&#xff1a;文件加密与解密2.1 需求2.2 代码实现2.3 输出结果 练习3&#xff1a;修改文件数据&#xff08;常规方法&#xff09;3.1 需求3.2 代码实现3.3 输出结果 练习4&#xff1a;修改文件数…

CSP-201712-2-游戏

CSP-201712-2-游戏 解题思路 初始化变量&#xff1a;定义整数变量n和k&#xff0c;分别用来存储小朋友的总数和淘汰的特定数字。然后定义了num&#xff08;用来记录当前报的数&#xff09;和peopleIndex&#xff08;用来记录当前报数的小朋友的索引&#xff09;。 初始化小朋…

无法访问云服务器上部署的Docker容器(二)

说明&#xff1a;记录一次使用公网IP 接口地址无法访问阿里云服务接口的问题&#xff1b; 描述 最近&#xff0c;我使用Docker部署了jeecg-boot项目&#xff0c;部署过程都没有问题&#xff0c;也没有错误信息。部署完成后&#xff0c;通过下面的地址访问后端Swagger接口文档…

react useMemo 用法

1&#xff0c;useCallback 的功能完全可以由 useMemo 所取代&#xff0c;如果你想通过使用 useMemo 返回一个记忆函数也是完全可以的。 usecallback(fn,inputs)is equivalent to useMemo(()> fn, inputs). 区别是:useCallback不会执行第一个参数函数&#xff0c;而是将它返…

获取当前数据 上下移动

点击按钮 上下移动 当前数据 代码 // 出国境管理 登记备案人员列表 <template><a-row><a-col span"24"><a-card :class"style[a-table-wrapper]"><!-- 出国境 登记备案人员列表 --><a-table:rowKey"records >…

sql 注入 之sqli-labs/less-6 双注入,双引号报错注入

和第五关类似&#xff0c;只不过闭合符号是双引号 1&#xff0c;查数据库 1"and%20(updatexml(1,concat(0x7e,(select%20database()),0x7e),1))%20-- 2.查表 内容有多行&#xff0c;所以使用limit依次查询 1"and%20(updatexml(1,concat(0x7e,(select%20table_nam…

【Linux系统化学习】线程概念

目录 线程的概念 线程的引出 什么是线程 理解线程比进程更加的轻量化 线程的优点 现成的缺点 线程异常 线程用途 Linux进程VS线程 线程的简单现象 线程的概念 有关操作系统的书籍或者课本都会这样描述线程&#xff1a; 线程是比进程轻量化的一种执行流线程是进程内部…

利用小蜜蜂AI智能问答ChatGPT+AI高清绘图生成图文故事案例

利用小蜜蜂AI智能问答ChatGPTAI高清绘图生成图文故事案例 这段时间利用小蜜蜂AI网站做了一些编程、绘图以及数据分析方面的案例。再过几个月&#xff0c;我的大孙子就要出生了。我要用小蜜蜂AI智能问答和AI高清绘图为大孙子生成一个1-9的数字图文故事。 小蜜蜂AI网站可以扫如…

前端打包部署(黑马学习笔记)

我们的前端工程开发好了&#xff0c;但是我们需要发布&#xff0c;那么如何发布呢&#xff1f;主要分为2步&#xff1a; 1.前端工程打包 2.通过nginx服务器发布前端工程 前端工程打包 接下来我们先来对前端工程进行打包 我们直接通过VS Code的NPM脚本中提供的build按钮来完…

【HTML5】浏览器不能显示字体报错Failed to decode downloaded font问题解决

把网上的项目中字体通过链接保存下来在本地上使用&#xff0c;在本地服务器上运行站点发现&#xff0c;用Chrome浏览器访问的时候&#xff0c;出现错误提示不能正常显示字体&#xff0c;怎么解决呢&#xff0c;看看怎么搞。 文章目录 发现问题提示警告提示错误 字体检查打开文件…

Redisson限流算法

引入依赖 <dependency><groupId>org.redisson</groupId><artifactId>redisson-spring-boot-starter</artifactId><version>3.12.3</version> </dependency>建议版本使用3.15.5以上 使用 这边写了一个demo示例&#xff0c;定…