【数据结构】九、排序

目录

一、排序概述

二、插入排序

2.1直接插入排序

2.2折半插入排序

2.3二路插入排序

2.4表插入排序

2.5希尔排序

三、交换排序

3.1冒泡排序

3.2快速排序

四、选择排序

4.1简单选择排序

4.2锦标赛排序

4.3堆排序

五、归并排序

六、基数排序

七、总结 


一、排序概述

定义:将一组存放在数据表中的无序数据按照一定的顺序排列起来

目的:便于查找

排序算法衡量指标

  • 时间效率——排序速度
  • 空间效率——占内存辅助空间大小
  • 稳定性——若两个记录A和B的关键字值相等,且排序后A、B的先后次序保持不变,则称这种排序算法是稳定的

内部排序:待排序记录都在内存中

外部排序:数据量过大,将数据分批调入内存进行排序,还要将结果及时放入外存

待排序记录在内存中的存储和处理

  1. 顺序排序:排序时直接移动记录
  2. 链表排序:排序时只移动指针
  3. 地址排序:排序时先移动地址,最后再移动记录 

内部排序算法分类

  1. 插入排序
  2. 交换排序
  3. 选择排序
  4. 归并排序
  5. 基数排序 

列表结构及建立

typedef struct {
	int array[MAXSIZE + 1];
	int length;
}list;

void initlist(list& l)
{
	printf("number?");
	scanf_s("%d", &l.length);
	for (int i = 1; i <= l.length; i++)
	{
		printf("data:");
		scanf_s("%d", &l.array[i]);
	}
}

二、插入排序

基本思想:每步将一个待排序的对象,按其关键码大小,插入到前面已经排好序的一组对象的适当位置上,直到对象全部插入为止。简言之,边插入边排序,保证子序列中随时都是排好序的。

2.1直接插入排序

对于每一个元素,在已形成的有序线性表中从后向前找插入位置,原位置元素向后移,新元素插入。是最简单的排序法。

直接插入排序
时间效率

最好:O(n),数据本就有序,比较n-1次

最差:O(n^2),数据逆序,从第二个元素开始,每个元素都要与有序部分全比较一遍,比较1+2+...n-1次

空间效率

O(1),占用一个缓冲单元
稳定性稳定

代码

#include<stdio.h>
#include<stdlib.h>

#define MAXSIZE 20

typedef struct {
	int array[MAXSIZE + 1];
	int length;
}list;

void initlist(list& l)
{
	printf("number?");
	scanf_s("%d", &l.length);
	for (int i = 1; i <= l.length; i++)
	{
		printf("data:");
		scanf_s("%d", &l.array[i]);
	}
}

void sort(list& l)
{
	int i, j;
	for (i = 2; i <= l.length; i++)  //0号为缓冲位,1号默认为有序,所以从2号开始遍历
	{
		if (l.array[i - 1] > l.array[i])    //新元素大于等于有序部分最后一位(即前一个元素)时无需操作,小于时进行操作
		{
			l.array[0] = l.array[i];        //新元素值复制到缓冲区
			j = i-1;
			while (l.array[j] > l.array[0]) //将有序部分大于新元素的部分后移
			{
				l.array[j + 1] = l.array[j];
				j--;
			}
			l.array[j + 1] = l.array[0];	//新元素插入
		}
	}

	for (i = 1; i <= l.length; i++)
		printf("%d ", l.array[i]);
}

int main() {
	list l;
	initlist(l);
	sort(l);
}

2.2折半插入排序

子表有序且为顺序存储结构,则插入时采用折半查找定可加速定位。与直接插入排序相比,元素间的比较次数减少

折半插入排序
优点比较次数大大减少,全部元素比较次数仅为O(nlog_2 n)
时间效率移动次数并未减少, 所以排序效率仍为O(n^2)
空间效率O(1)
稳定性稳定

2.3二路插入排序

增加一个元素数和待排数组相同的循环数组d

先将list第一个元素赋给d第一个元素,然后以此元素为基准,把list中其他元素插入到基准的前面或后面,最终从头指针到尾指针即为有序数组

2.4表插入排序

在顺序存储结构中,给每个记录增开一个指针分量,在排序过程中不移动元素,只修改指针,最终得到一个有序链表

表插入排序举例
表插入排序
时间效率无需移动记录,只需修改2n次指针值。但由于比较次数没有减少,故时间效率仍为O(n^2)
空间效率低,因为增开了指针分量。但在运算过程中没有用到更多的辅助单元
稳定性稳定

2.5希尔排序

先将整个待排序列分割为若干子序列,子序列中分别插入排序,再扩大子序列范围,插入排序,至整个序列有序

子序列的选择:将相隔一定距离的元素划分为一个序列,间隔逐渐缩短

希尔排序
时间效率O(n^1.25)~O(1.6n^1.25)      由经验公式得到
空间效率O(1)
稳定性不稳定

代码

#include <stdio.h>
#include <malloc.h>

void shellsort(int* a, int len)
{
    int i, j, k, tmp, gap;  // gap 为步长
    for (gap = len / 2; gap > 0; gap /= 2) // 步长初始化为数组长度的一半,每次遍历后步长减半
    { 
        for (i = 0; i < gap; ++i) // 变量 i 为每次分组的第一个元素下标;间隔数也是组数
        {  
            for (j = i + gap; j < len; j += gap) //对每组元素进行插入排序;在每组中第一个默认为有序,从第二个开始遍历
            { 
                tmp = a[j];  // 备份a[j]的值
                k = j - gap;  // k初始化为j的前一个元素

                while (k >= 0 && a[k] > tmp) // 把一组中有序部分比tmp的值大的元素向后移动
                {
                    a[k + gap] = a[k]; 
                    k -= gap;
                }
                a[k + gap] = tmp;   // 把tmp插入
            }
        
        }
    }
}

int main(void)
{
    int i, len, * a;
    printf("请输入要排的数的个数:");
    scanf_s("%d", &len);
    a = (int*)malloc(len * sizeof(int)); // 动态定义数组
    if (!a)  return NULL;

    printf("请输入要排的数:\n");
    for (i = 0; i < len; i++) // 数组值的输入
        scanf_s("%d", &a[i]);

    shellsort(a, len); // 调用希尔排序函数

    printf("希尔升序排列后结果为:\n");
    for (i = 0; i < len; i++) // 排序后的结果的输出
        printf("%d\t", a[i]);
    printf("\n");
}

用希尔排序方法对一个数据序列进行排序时,若第1趟排序结果为9,1,4,13,7,8,20,23,15,则该趟排序采用的增量(间隔)可能是(   )

  • A. 2
  • B. 3
  • C. 4
  • D. 5

 答案:B    依次对选项进行假设,当组内都有序时假设成立 

三、交换排序

两两比较关键码,如果逆序,则进行交换

3.1冒泡排序

每趟不断将相邻两记录两两比较,并按“前小后大”(或“前大后小”)规则交换。每趟结束时,能挤出一个最大值到最后面

冒泡排序
优点每一趟整理元素时,不仅可以完全确定表尾一个元素的位置,还可以对前面的元素作一些整理,所以比一般的排序要快

时间效率

最好情况:初始排列有序,只执行一趟冒泡,做 n-1 次比较,不移动对象;

最坏情形:初始排列逆序,执行n-1趟冒泡,第i趟(1<=i<=n) 做了n - i 次比较,执行了 n - i 次交换.此时比较总次数:n(n-1)/2  记录移动总次数:3/2n(n-1)

最坏情况O(n^2)

空间效率

O(1)
稳定性稳定

代码

#include<stdio.h>
#include<stdlib.h>

void sort(int* list, int len)
{
    for (int i = 0; i < len - 1; i++)  //进行len-1次排序
    {
        for (int j = 1; j < len - i; j++)   //每次从第2个元素遍历到len-i号元素
        {
            if (list[j - 1] > list[j])
            {
                int t = list[j];
                list[j] = list[j - 1];
                list[j - 1] = t;
            }
        }
    }
}

int main() {
	int i, len, * a;
    printf("请输入要排的数的个数:");
    scanf_s("%d", &len);
    a = (int*)malloc(len * sizeof(int)); // 动态定义数组
    if (!a)  return NULL;

    printf("请输入要排的数:\n");
    for (i = 0; i < len; i++) // 数组值的输入
        scanf_s("%d", &a[i]);

    sort(a, len);

    for (i = 0; i < len; i++)
        printf("%d ", a[i]);
}

对一组数据(2,12,16,88,5,10)进行排序,若前三趟排序结果如下( )
第一趟:2,12,16,5,10,88
第二趟:2,12,5,10,16,88
第三趟:2,5,10,12,16,88
则采用的排序方法可能是:

  • A. 快速排序
  • B. 冒泡排序
  • C. 基数排序
  • D. 希尔排序

答案:B   每次排序都有最大值挤到最后 

3.2快速排序

思路以首元素为基准,首元素此时为“空闲位”。先从后向前找比首元素小的,复制到空闲位,自身变为新的空闲位;再从前往后找比基准大的,复制到空闲位,自身成为新的空闲位。当前后指针相遇时把基准插入。此时列表基准左边都比它小,右边都比它大,向左右递归继续排序。

时间效率O(nlog_2n)  每趟可以确定的数据元素是呈指数增加
空间效率O(log_2n)     因为递归要用栈(存每层low,high和pivot)
稳定性不稳定

代码

//快速排序:以首位数为基准,用两指针从两侧逼近,把小于基准的都放到基准左侧,大于基准的都放到基准右侧,再缩小范围,递归。
void quicksort(int*& list, int l, int r) {  //传入数组,开始和结束的编号
 
	if (l < r) {
		int p1 = l;
		int p2 = r;       //两指针指向两侧
		int target = list[l];   //首元素为基准
 
		while (p1 < p2) {  //以下操作都需要当两指针未重合时才能执行
 
			while (p1 < p2 && list[p2] > target)  //从后向前找到不大于target的值
				p2--;
 
			if (p1 < p2)
				list[p1++] = list[p2];    //把这个值赋给p1,p1后移
 
			while (p1 < p2 && list[p1] < target)    //从前向后找到不小于target的值
				p1++;
 
			if (p1 < p2)
				list[p2--] = list[p1];    //把这个值赋给p2,p2前移
		}
		list[p1] = target;     //把重合之处赋为target
 
		//递归调用
		quicksort(list, l, p1 - 1);
		quicksort(list, p1 + 1, r);
	}
}

下列序列中,(    )是执行第一趟快速排序后所得的序列。(下划线表示已找到位置的元素)

  • A. [68,11,18,69]_[23,93,73]
  • B. [68,11,69,23]_[18,93,73]
  • C. [93,73]_[68,11,69,23,18]
  • D. [73,11,69,23,18]_[93,68]

答案:D  只有D能找到一个数,使左边数组都小于它,右边数组大于它

四、选择排序

选择排序的基本思想:每一趟(第i趟)在后面n - i + 1个待排记录中选取关键字最小的记录作为有序序列中的第 i 个记录。

4.1简单选择排序

简单选择排序
时间效率O(n^2)   走 n - 1 趟,每趟遍历 n - i 个元素
空间效率O(1)
稳定性不稳定

代码

void simple_section_sort(int* list, int len)
{
    int min, x;
    for (int i = 0; i < len - 1; i++)  // 要对前n-1个位置进行选择,插入
    {
        min = 65535;
        x = i;
        for (int j = i; j < len; j++)  //选择出i到末尾的最小值
        {
            if (list[j] < min)
            {
                min = list[j];
                x = j;
            }
        }           
        int tmp = list[x];   //将最小值与第i个元素交换
        list[x] = list[i];
        list[i] = tmp;

    } 
}

对一组数据(84,47,25,15,21)排序,数据的排列次序在排序的过程中的变化为
(1) 84 47 25 15 21  (2) 15 47 25 84 21   (3) 15 21 25 84 47  (4) 15 21 25 47 84 
则采用的排序是 (     )

  • A. 选择
  • B. 冒泡
  • C. 快速
  • D. 插入

答案:A     最小值不断增加

4.2锦标赛排序

思路:把待排元素当作一棵完全二叉树的叶子节点,叶子不足的补齐;从下向上建立二叉树,父节点为子节点中较小值;此时根节点为排序的第一个结果;然后把树中的这个值变为无穷,更新父节点,得到新的根节点为排序的第二个结果;直到所有叶节点都遍历。

锦标赛排序
时间效率O(nlog_2n)   n个记录各自比较约log2n次
空间效率O(n)    胜者树附加节点n-1个
稳定性稳定    当遇到两个数值相同时,认为左边较小

代码

不写了,知道过程就行  :)

4.3堆排序

准备知识

1.堆的结构是完全二叉树。构造堆的时候从上往下,从左往右依次添加节点

2.一般用数组来表示堆,用下标的计算关系来指明父子关系

3.下标为 i 的结点的父结点下标为 (i-1)/2;其左右子结点分别为 (2i + 1)、(2i + 2)

4.大根堆:父节点值大于两子节点     小根堆:父节点值小于两子节点

建堆

例:关键字序列T= (21,25,49,25,16,08),建大根堆

1.将原始序列画成完全二叉树的形式(准备知识1)

初始堆

2.从完全二叉树的最后一个非终端节点(编号为 [n/2])开始调整,图中为49

3.该节点(49)与它的两个子节点(08)进行比较,把较大值放到父节点的位置(49>8,不动)

4.对倒数第二个非终端节点进行此操作(25>25*,25>16,不动 ),一直遍历到根节点

5.另外,被换下来的节点要继续向下比较(如根节点21,21<25<49,21与49交换,交换后21要与子节点(08)继续比较,判断是否还要交换)

大根堆

此时根节点为最大值,开始排序

排序

1)最大值在根节点,也就是数组第一位。把第一位与最后一位第n位交换,把最大值放到最后

2)数组从1到n-1重新建堆。最大值又上浮到第一位

3)再对调第一位和第n-1位,如此重复,得到有序序列

算法流程

void HeapSort (HeapType &H )  //对顺序表H进行堆排序
{
    for (i = H.length / 2; i >0; --i)
       HeapAdjust(H, i, H.length);     //倒序遍历非叶子节点,建立初始堆

    for (i = H.length; i > 1; --i) 
    { 
       H.r[1] ←→ H.r[i];         //最大值和尾部交换
       HeapAdjust(H, 1, i-1);    //把刚换上去的头节点进行调整,重建最大堆
    } 
}

//HeapAdjust是针对结点 i 的堆调整函数,其含义是:从结点i开始到堆尾为止
//从上向下比较,如果子女的值大于双亲结点的值,则互相交换,即把局部调整为大根堆
堆排序
时间效率O(nlog_2n)   因为整个排序过程中需要调用n-1次HeapAdjust( )算法,而算法本身耗时为log_2n
空间效率O(1)     仅在首尾交换时用到一个临时变量temp
稳定性不稳定

练习

已知关键序列5,8,12,19,28,20,15,22是小根堆(最小堆),插入关键字3,调整后得到的小根堆是?

答案:3,5,12,8,28,20,15,22,19

五、归并排序

思路:把一个长度为n的无序序列看成是n个长度为 1 的有序子序列。将数组的每一个元素划分为一个有序表。两两合并,组内分别排序;再两两合并,组内排序;最终得到有序序列。

归并排序示意图
归并排序
时间效率O(nlog_2n)     有序子序列的长度是以2的次方递增的,所以归并过程有log_2n“层”;每层要归并 n / len 次,每次要比较 len 次
空间效率O(n)      在合并两子序列时,需要一个长度为n的辅助序列
稳定性稳定

代码

#include<stdio.h>
#include<stdlib.h>
 
void merge(int* list, int low, int mid, int high)
{
    int p;
    int* a = (int*)malloc(sizeof(int) * (high - low + 1));
    if (!a)  return;

    for (p = low; p <= high; p++)
        a[p] = list[p];

    int i, j, k;
    for (i = low, j = mid + 1, k = low; i <= mid && j <= high; k++)
    {
        if (list[i] > list[j])
            a[k] = list[j++];
        else
            a[k] = list[i++];
    }

    while (i <= mid)
        a[k++] = list[i++];
    while (j <= high)
        a[k++] = list[j++];

    for (p = low; p <= high; p++)
        list[p] = a[p];
}

void mergesort(int* list, int low, int high)  //归并排序
{
    if (low < high)   
    {
        int mid = (low + high) / 2;
        mergesort(list, low, mid);         //对前半部分归并排序
        mergesort(list, mid + 1, high);    //对后半部分归并排序
        merge(list, low, mid, high);       //把排序完的部分合并
    }
}

int main(void)
{
    int i, len, * list;
    printf("请输入要排的数的个数:");
    scanf_s("%d", &len);
    list = (int*)malloc(len * sizeof(int)); // 动态定义数组
    if (!list)  return NULL;

    printf("请输入要排的数:\n");
    for (i = 0; i < len; i++) // 数组值的输入
        scanf_s("%d", &list[i]);

    mergesort(list, 0, len - 1);

    for (i = 0; i < len; i++)
    printf("%d ", list[i]);

}

六、基数排序

基本思想:从多维度对元素进行排序,比如对扑克牌进行排序,可以先按花色分类,再按数字大小分类;也可以先按数字大小分类,再按花色分类。这也叫多关键字排序。

多关键字排序的实现通常有两种实现方法:

  • 最高位优先法MSD (Most Significant Digit first)
  • 最低位优先法LSD (Least Significant Digit first)

若规定花色为第一关键字(高位),面值为第二关键字(低位),则上文第一种方法为MSD,第二种为LSD。

数值排序思路

把数字的每一位看作一个维度。最多有几位,就要经过几趟排序。先从数字最低位开始比较。

建立编号0~9的十个队列

遍历数组中的数字,按照个位数字将它们放入对应的队列(分配)

遍历完后,按照从上到下,从左到右的顺序把数字从队列中取出得到第一遍整理后的数组(收集)

再按照十位数字入队列,再取出...直到最高位

例:

为什么从最低位开始比较?

虽然最高位最能决定数字大小,但先排高位后排低位会把总体的趋势打乱;先排低位,虽然高位相同的数字是分散的,但如果单独取出来看,会发现高位相同的数字间正变得有序。最后排高位,确定总体趋势,得到有序数组。

基数排序
时间效率O(d(n+radix))      假设有 n 个记录,每个记录关键字有 d 位每个关键字的取值有radix个,则每趟分配需要的时间为O(n),每趟收集需要的时间为O(radix),合计每趟总时间为O(n+radix)。全部排序需要重复进行d 趟“分配”与“收集”。

空间效率

O(n+radix)     基数排序需要增加n+2radix个附加链接指针。存储数据的静态链表需要额外n个指针,每个静态队列需要头尾两个指针。
稳定性稳定

代码

#include<stdio.h>
#include<stdlib.h>

typedef struct {  //队列类型
    int head;
    int tail;
    int* base;
}array;   

void radix_sort(int* list, int len)
{ 
    int i, j, k;   //代表三层循环变量

    int high = 0;       //找最大值来计算元素的最高位数high
    int max = list[0];
    for (i = 0; i < len; i++)
        if (list[i] > max)
            max = list[i];
    while (max)
    {
        max /= 10;
        high++;
    }
   
    array* ten_arr = (array*)malloc(10 * sizeof(array));  //10个列表
    if (!ten_arr)  return;

    for (i = 0; i < 10; i++)  //列表初始化
    {
        ten_arr[i].head = ten_arr[i].tail = 0;
        ten_arr[i].base = (int*)malloc(sizeof(int) * 10);  //每个列表能放10个元素
        if (!ten_arr[i].base)  return;
    }
        
    int b = 1;  //b用于计算,表明当前取的是哪一位
    for (i = 0; i < high; i++)  
    {
        for (j = 0; j < len; j++)  //遍历数组元素
        {
            int number = (list[j] / b) % 10;    //取指定位数字
            ten_arr[number].base[ten_arr[number].tail++] = list[j];  //把元素放进对应队列
        }           
        b *= 10;  //b倍增,下次循环取下一位

        k = 0;
        for (j = 0; j < 10; j++)  //把队列中的数据收集起来放回列表中
        {
            while (ten_arr[j].head != ten_arr[j].tail) {
                list[k++] = ten_arr[j].base[ten_arr[j].head++];
            }               
            ten_arr[j].head = ten_arr[j].tail = 0;    //队列清空,这玩意不要放到while里面:(

        }
       
    }
}

int main(void)
{
    int i, len, * list;
    printf("数的个数:");
    scanf_s("%d", &len);
    list = (int*)malloc(len * sizeof(int)); 
    if (!list)  return NULL;

    printf("输入数:\n");
    for (i = 0; i < len; i++) 
        scanf_s("%d", &list[i]);

    radix_sort(list, len);

    for (i = 0; i < len; i++)
        printf("%d ", list[i]);

}

七、总结 

稳定的排序算法:鸡毛插龟壳(基数、冒泡、插入、归并

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

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

相关文章

DBeaver连接国产数据库的步骤

驱动配置 第一次安装过DBeaver之后&#xff0c;配置下驱动仓库&#xff0c;安装下图所示操作。 添加马爸爸的maven库连接地址 id&#xff1a; maven.aliyun.com 名称&#xff1a; maven.aliyun.com url&#xff1a; https://maven.aliyun.com/repository/central/ 或者 ht…

TCP协议:可靠传输的基石

目录 1. 数据完整性的保证 2. 数据的有序传输 3. 确认应答机制 4. 流量控制 5. 拥塞控制 6. 重传机制 结论 引言 TCP&#xff08;Transmission Control Protocol&#xff09;是计算机网络中的一个重要协议&#xff0c;它以其可靠性而闻名。TCP是一种面向连接的协议&…

影响晶振频率稳定性的因素及解决方法

晶振作为电子设备中的核心元件&#xff0c;其频率稳定性对设备的性能和可靠性具有重要影响。晶发电子将介绍影响晶振频率稳定性的因素&#xff0c;并探讨相应的解决方法。 一、影响晶振频率稳定性的因素 频率&#xff1a;晶振的频率是影响其性能的最重要因素之一。在选择晶振…

MongoDB介绍

一、MongoDB介绍 1.1 mongoDB介绍 MongoDB 是由C语言编写的&#xff0c;是一个基于分布式文件存储的开源数据库系统。 在高负载的情况下&#xff0c;添加更多的节点&#xff0c;可以保证服务器性能。 MongoDB 旨在为WEB应用提供可扩展的高性能数据存储解决方案。 MongoDB …

Jetpack DataStore

文章目录 Jetpack DataStore概述DataStore 对比 SP添加依赖库Preferences DataStore路径创建 Preferences DataStore获取数据保存数据修改数据删除数据清除全部数据 Proto DataStore配置AndroidStudio安装插件配置proto文件创建序列化器 创建 Proto DataStore获取数据保存数据修…

Spring AOP入门指南:轻松掌握面向切面编程的基础知识

面向切面编程 1&#xff0c;AOP简介1.1 什么是AOP?1.2 AOP作用1.3 AOP核心概念 2&#xff0c;AOP入门案例2.1 需求分析2.2 思路分析2.3 环境准备2.4 AOP实现步骤步骤1:添加依赖步骤2:定义接口与实现类步骤3:定义通知类和通知步骤4:定义切入点步骤5:制作切面步骤6:将通知类配给…

swing快速入门(二十三)弹球小游戏

注释很详细&#xff0c;直接上代码 上一篇 新增内容 1. 键盘响应监听 2. 使用定时器事件更新画板 3. 定时器事件的开始与暂停 4. 弹球小游戏的坐标逻辑判断 import javax.swing.*; import java.awt.*; import java.awt.event.*;public class swing_test_19 {//创建一个窗…

如何选择适合的UI自动化测试工具

随着软件开发项目的复杂性增加&#xff0c;UI自动化测试成为确保应用程序质量的关键步骤之一。然而&#xff0c;在选择UI自动化测试工具时&#xff0c;开发团队需要考虑多个因素&#xff0c;以确保选取的工具适用于项目需求并提供可靠的测试结果。 1. 了解项目需求 在选择UI自动…

esp32-s3训练自己的数据进行目标检测、图像分类

esp32-s3训练自己的数据进行目标检测、图像分类 一、下载项目二、环境三、训练和导出模型四、部署模型五、存在的问题 esp-idf的安装参考我前面的文章&#xff1a; esp32cam和esp32-s3烧录human_face_detect实现人脸识别 一、下载项目 训练、转换模型&#xff1a;ModelAssist…

大型医院PACS系统源码,影像存储与传输系统源码,支持多种图像处理及三维重建功能

PACS系统是医院影像科室中应用的一种系统&#xff0c;主要用于获取、传输、存档和处理医学影像。它通过各种接口&#xff0c;如模拟、DICOM和网络&#xff0c;以数字化的方式将各种医学影像&#xff0c;如核磁共振、CT扫描、超声波等保存起来&#xff0c;并在需要时能够快速调取…

Docker部署 flowable-ui 进行流程建模

Docker部署 flowable-ui 进行流程建模 简介 安装Docker Desktop,本篇无安装步骤安装正常打开运行后&#xff0c;正式开始部署flowable-uicmd执行拉取镜像操作docker pull flowable/flowable-uicmd启动镜像docker run -d --name flowable -p 8081:8080 flowable/flowable-ui修…

基于博弈树的开源五子棋AI教程[4 静态棋盘评估]

引子 静态棋盘的评估是棋力的一个很重要的体现&#xff0c;一个优秀的基于博弈树搜索的AI往往有上千行工作量&#xff0c;本文没有做深入讨论&#xff0c;仅仅写了个引子用来抛砖引玉。 评估一般从两个角度入手&#xff0c;一个是子力&#xff0c;另一个是局势。 1 评估维度 …

SSH无密登陆配置

1 SSH介绍 ssh命令用于远程登录到其他计算机&#xff0c;实现安全的远程管理。 基本语法&#xff1a; ssh 域名/IP地址 示例&#xff1a; &#xff08;1&#xff09;从hadoop100服务器上远程连接hadoop101服务器 [hadoophadoop100 ~]$ ssh hadoop101 如果出现如下内容 Ar…

【C语言】动态内存管理基础知识——动态通讯录,如何实现通讯录容量的动态化

引言 动态内存管理的函数有&#xff1a;malloc,calloc,ralloc,free,本文讲解动态内存函数和使用&#xff0c;如何进行动态内存管理,实现通讯录联系人容量的动态化&#xff0c;对常见动态内存错误进行总结。 ✨ 猪巴戒&#xff1a;个人主页✨ 所属专栏&#xff1a;《C语言进阶》…

idea 远程调试linux上的代码

背景介绍 开发过程中&#xff0c;我们经常会遇到部署的代码运行出问题、看日志由不是很直观、我们希望可以像调试本地代码一样去调试远程代码; IDEA提供了Remote工具,基于JVM的跨平台能力&#xff0c;我们可以远程调试部署的代码。 前提 保证远程和本地跑的代码是一致的 操…

yocto系列讲解[实战篇]93 - 添加Qtwebengine和Browser实例

By: fulinux E-mail: fulinux@sina.com Blog: https://blog.csdn.net/fulinus 喜欢的盆友欢迎点赞和订阅! 你的喜欢就是我写作的动力! 目录 概述集成meta-qt5移植过程中的问题问题1:virtual/libgl set to mesa, not mesa-gl问题2:dmabuf-server-buffer tries to use undecl…

GBASE南大通用数据库在Windows和Linux中创建数据源

Windows 中数据源信息可能存在于两个地方&#xff1a;在 Windows 注册表中&#xff08;对 Windows 系统&#xff09;&#xff0c; 或在一个 DSN 文件中&#xff08;对任何系统&#xff09;。 如果信息在 Windows 注册表中&#xff0c;它叫做“机器数据源”。它可能是一个“用 …

Sentinel 流量治理组件教程

前言 官网首页&#xff1a;home | Sentinel (sentinelguard.io) 随着微服务的流行&#xff0c;服务和服务之间的稳定性变得越来越重要。Sentinel 是面向分布式、多语言异构化服务架构的流量治理组件&#xff0c;主要以流量为切入点&#xff0c;从流量路由、流量控制、流量整形…

京东tp26旋转验证

记录一下&#xff0c;狗东的tp26旋转验证码&#xff0c;难点还是在这个轨迹上。我真的是一点都不喜欢玩轨迹&#xff01;&#xff01;&#xff01;&#xff01; 类似于百度旋转的图&#xff0c;不过他这个东西还是稍微有点差距的。 鉴于生病了脑子不太好使&#xff0c;就不过多…

全光谱全天候耐久性性能测试氙灯老化箱太阳光模拟器

氙灯老化箱应用领域 添加剂 & 着色剂胶粘剂 & 密封剂建材汽车食品& 饮料平面艺术 包装材料油漆& 涂料光伏塑料纺织品风能 & 太阳能消费类电子产品 氙灯老化箱描述 氙灯老化箱是一种用于模拟阳光、雨水和温度循环的老化测试设备。它使用氙灯作为光源&am…