当前位置: 首页 > news >正文

【数据结构】快排的详细讲解

目录:

介绍

一,递归快排确定基准值

二,递归遍历

三,非递归的快排

四,快排的效率


介绍

        快排是排序算法中效率是比较高的,快排的基本思想是运用二分思想,与二叉树的前序遍历类似,将数据划分,每次划分确定1个基准值(就是已经确定好有序后位置的数据),以升序为例,基准值左面的数据都比此值小,右面的数据都比此值大,然后以基准值为分界线,经过不断划分,最终基准值的个数达到n,数据即有序,因此,递归运用是不二选法,也可运用非递归,但是比较麻烦。

一,递归快排确定基准值

确定基准值的方法常用的有三种,普通法,挖坑法,前后指针法。

1,普通法,具体思想图如下(以升序为例):


        上面说过,基准值的确定过程要保证左面的数据都比此值小或大,右面的数据都要比此值大或小,因此,此基准值就确定了在整个数据中的位置。以升序为例,我们可以从开头和末尾遍历数据,比开头(以首元素为基准)元素大的放在最后,比开头元素小的数据放在前面,最终当两者相遇后再与开头元素交换即可确定基准值(注意:此步骤有细节,具体后面会说明)。如下图:

基准值过程图

        现在有个注意要素套提一下,当上图中的前面L和后面R相遇时,如何保证此值一定比首元素小呢?这里我们需要控制好L的走向即可,即让R先走,当遇见比首元素小时退出,然后让L走,最后让两者进行交换,这样一来无论出现什么情况,当L与R相遇时对应的数据将一定比首元素(即以第一个元素为基准)小,此步骤称为预排序。

基准值的确定代码如下:

void Swap(int* x1, int* x2) {
    int t = *x1;
    *x1 = *x2;
    *x2 = t;
}

int PartSort1(int* a, int begin, int end) {
    int key = begin;
    while (begin < end) {
        //注意此步骤,end必须先开始(即当左边开始行走右边一定有比key小的值),
        //因为要控制最后的begin最终比key(开头元素)小,因此,右边必须先走.

        while (begin < end && a[end] >= a[key]) {
            end--;
        }
        //当走左边时,最终会Swap(a + end, a + begin);交换后begin的最终比key小
        while (begin < end && a[begin] <= a[key]) {
            begin++;
        }
        Swap(a + end, a + begin);
    }
    Swap(a + key, a + begin);
    return begin;
}


2,挖坑法,原理图如下(以升序为例):

        挖坑发大致思想与普通法一样,不同的是挖坑发有了坑位。挖坑发是先将首元素保存,将此位置形成坑位(其实坑位上有数据,但坑位的数据不影响,为了方便理解,所以在上图中的坑位就没写上去),然后开始首尾遍历(尾要先遍历,原理同上),比key大的元素放在后面,比key小的元素放在前面,一旦不满足此情况,这个数据将给到位置L或位置R,原本的位置将会形成坑位,直到两者相遇为止,结束遍历,最后把key的值放入坑位即可。代码如下:

int PartSort2(int* a, int begin, int end) {
    int key = a[begin];
    int hole = begin;//开头先形成坑位
    while (begin < end) {
        // 右边先走(原理与PartSort1原理一样),找小,填到左边的坑,右边形成新的坑位
        while (begin < end && a[end] >= key) {
            end--;
        }
        a[hole] = a[end];
        hole = end;
        // 左边再走,找大,填到右边的坑,左边形成新的坑位
        while (begin < end && a[begin] <= key) {
            begin++;
        }
        a[hole] = a[begin];
        hole = begin;
    }
    a[hole] = key;
    return hole;
}


3,前后指针法(prev是前指针,cur是后指针,此指针是位置指针,不是我们所常说的指针型),原理图如下:

        前后指针法跟上面两种方法有很大不同,如上,以第一个元素为基准,即定义key值为首元素,cur往前遍历,prev随之跟上cur的步伐,当prev遇到的数据比key小,prve向前移动;当prev遇到的数据比key大,prev停止移动,此时,cur不断向前移动,一旦找到比key小的数据就会跟prev指向的数据进行交换,最后,当cur遍历完整个数据后cur与key会进行交换,确定此时key所对应的值比左边数据大,比右边数据小。代码如下:

void Swap(int* x1, int* x2) {
    int t = *x1;
    *x1 = *x2;
    *x2 = t;
}
int PartSort3(int* a, int begin, int end) {
    int front = begin + 1;
    int back = begin;
    while (front <= end) {
        if (a[front] <= a[begin]) {
            back++;
            Swap(a + back, a + front);
        }
        front++;
    }
    //因为后指针控制,所以当程序结束后back所指向的数据都比keyi所指向的数据小
    Swap(a + begin, a + back);
    return back;
}


总:以上三种遍历确定基准值的方法在快排称为预排序,每一趟预排序都可确定数据中一个元素的排序位置,每当确定一个数据后相对位置后,我们只需要不断以上次遍历时确定的基准值为界,递归遍历数据,即可确定最终确定序列。


二,递归遍历

        当我们明白如何确定基准值后,接下来就是程序的结构搭建了,上面说过,快排递归跟二叉树的前序遍历一样,并且还需要以基准值为分界线,不断确定基准值,具体思路导图如下:

        当确定好基准值key后,以区间[begin, key - 1]和区间[key + 1, end]进行划分(begin是要进行遍历时,开头元素的坐标,end是要遍历时,结尾元素的坐标,如上图),以次区间不断进行与二叉树前序遍历相同的递归,根据上图所示,很明显,当begin>=end时结束下一层递归。代码如下:

void QuickSort(int* a, int begin, int end)
{
    //即当不存在区间时结束,即就排好了一个数
    if (begin >= end)
        return;
    //运用普通法PartSort1,此算法是返回一个顺序表中中间值的坐标,在坐标左边都小于此数,在坐标的右边都大于此数
    int keyi = PartSort1(a, begin, end);//也可用挖坑法和前后指针法
    // 区间递归: 以keyi为界,左[begin, keyi-1],右[keyi+1, end],一直缩小,最终会逐渐会缩小成有序
    QuickSort(a, begin, keyi - 1);//在keyi的左面进行遍历
    QuickSort(a, keyi + 1, end);//在keyi的右面进行遍历
}

下面是总代码:

#include <stdio.h>
void Swap(int* x1, int* x2) {int t = *x1;*x1 = *x2;*x2 = t;
}
int PartSort1(int* a, int begin, int end) {int key = begin;while (begin < end) {//注意此步骤,end必须先开始(即当左边开始行走右边一定有比key小的值),//因为要控制最后的begin最终比key(开头元素)小,因此,右边必须先走.while (begin < end && a[end] >= a[key]) {end--;}//当走左边时,最终会Swap(a + end, a + begin);交换后begin的最终比key小while (begin < end && a[begin] <= a[key]) {begin++;}Swap(a + end, a + begin);}Swap(a + key, a + begin);return begin;
}
void QuickSort(int* a, int begin, int end)
{//即当不存在区间时结束,即就排好了一个数if (begin >= end)return;//PartSort1算法是返回一个顺序表中中间值的坐标,在坐标左边都小于此数,在坐标的右边都大于此数int keyi = PartSort1(a, begin, end);// 区间递归: 左[begin, keyi-1] keyi 右[keyi+1, end],一直缩小,最终会逐渐会缩小成排序QuickSort(a, begin, keyi - 1);//在keyi的左面进行遍历QuickSort(a, keyi + 1, end);//在keyi的右面进行遍历
}
void Print(int* a, int n) {for (int i = 0; i < n; i++) {fprintf(stdout, "%d ", a[i]);}puts("");
}
void TestQuickSort()
{int a[] = { 6,1,2,7,9,3,4,5,10,8 };QuickSort(a, 0, sizeof(a) / sizeof(int) - 1);Print(a, sizeof(a) / sizeof(int));
}
int main() {TestQuickSort();return 0;
}

运行图:


三,非递归的快排

        运用非递归,大多数要运用栈结构,因为递归本身其实就是不断入栈和出栈,递归过程跟栈结构一样,进入递归就是入栈,出函数就是出栈,都是先进后出。快排的非递归实现,我们也可用栈来实现。根据前面递归的运用,递归是不断进行区间分割,我们可将此区间放入栈中,然后进行不断循环遍历,每当遍历时就将区间放入栈中,一旦用完此区间就释放,跟递归中函数栈帧的创建与销毁一样。非递归结构代码如下:

1,栈的建立

typedef struct stack {
    int* Data;
    int Capacity;
    int Top;
}Stack;
 //以下三个是要运用栈结构的算法
void StackInit(Stack* S);
void StackPop(Stack* S);
void StackPush(Stack* S, int X);
//栈功能的实现
void StackInit(Stack* S) {//初始化栈
    assert(S);
    S->Data = 0;
    S->Capacity = 0;
    S->Top = -1;
}
void StackPop(Stack* S) {//出栈
    assert(S || S->Data || S->Top != -1);
    S->Top--;
}
void StackPush(Stack* S, int X) {//入栈
    assert(S);
    if (!S->Data) {
        S->Data = (int*)malloc(sizeof(int) * 4);
        assert(S->Data);
        S->Capacity = 4;
    }
    else if (S->Top == S->Capacity - 1) {
        S->Data = (int*)realloc(S->Data, (sizeof(int) * S->Capacity) * 2);
        assert(S->Data);
        S->Capacity *= 2;
    }
    S->Data[++S->Top] = X;
}

2,非递归的结构

void QuickSort(int* a, int left, int right) {
 //创建栈结构S,以栈来模仿递归过程
    Stack* S = (Stack*)malloc(sizeof(Stack));
    StackInit(S);
    StackPush(S, right);
    StackPush(S, left);
    while (S->Top != -1) {
        //确定左右区间,每当遍历完一次时要及时更换,即从栈中去除操作
        int begin = S->Data[S->Top];
        StackPop(S);
        int end = S->Data[S->Top];
        StackPop(S);
        //用指定好的区间进行预排序,即一次遍历
        int key = PartSort1(a, begin, end);
        //进行左区间的遍历
        if (end - 1 > begin) {
        //注意栈结构先进后出的特点,要先把end装进去
            StackPush(S, end - 1);
            StackPush(S, begin);
        }
        //进行右区间的遍历
        if (begin + 1 < end) {
        //同理,要先把end装进去
            StackPush(S, end);
            StackPush(S, begin + 1);
        }
    }
    free(S);
    //注意,不能在此算法内这样写,因为这是的a是首元素地址,即指针,sizeof(a)为地址的大小
    //Print(a, sizeof(a) / sizeof(int));

}

        以上是非递归过程中的逻辑代码,除此两大步,其它的逻辑运用与递归无任何区别,总代码如下:

#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
typedef struct stack {int* Data;int Capacity;int Top;
}Stack;//以下三个是要运用栈结构的算法
void StackInit(Stack* S);
void StackPop(Stack* S);
void StackPush(Stack* S, int X);
//栈功能的实现
void StackInit(Stack* S) {//初始化栈assert(S);S->Data = 0;S->Capacity = 0;S->Top = -1;
}
void StackPop(Stack* S) {//出栈assert(S || S->Data || S->Top != -1);S->Top--;
}
void StackPush(Stack* S, int X) {//入栈assert(S);if (!S->Data) {S->Data = (int*)malloc(sizeof(int) * 4);assert(S->Data);S->Capacity = 4;}else if (S->Top == S->Capacity - 1) {S->Data = (int*)realloc(S->Data, (sizeof(int) * S->Capacity) * 2);assert(S->Data);S->Capacity *= 2;}S->Data[++S->Top] = X;
}
void Swap(int* x1, int* x2) {int t = *x1;*x1 = *x2;*x2 = t;
}
int PartSort1(int* a, int begin, int end) {int key = begin;while (begin < end) {//注意此步骤,end必须先开始(即当左边开始行走右边一定有比key小的值),//因为要控制最后的begin最终比key(开头元素)小,因此,右边必须先走.while (begin < end && a[end] >= a[key]) {end--;}//当走左边时,最终会Swap(a + end, a + begin);交换后begin的最终比key小while (begin < end && a[begin] <= a[key]) {begin++;}Swap(a + end, a + begin);}Swap(a + key, a + begin);return begin;
}
void QuickSort(int* a, int left, int right) {//创建栈结构S,以栈来模仿递归过程Stack* S = (Stack*)malloc(sizeof(Stack));StackInit(S);StackPush(S, right);StackPush(S, left);while (S->Top != -1) {//确定左右区间,每当遍历完一次时要及时更换,即从栈中去除操作int begin = S->Data[S->Top];StackPop(S);int end = S->Data[S->Top];StackPop(S);//用指定好的区间进行预排序,即一次遍历int key = PartSort1(a, begin, end);//进行左区间的遍历if (end - 1 > begin) {//注意栈结构先进后出的特点,要先把end装进去StackPush(S, end - 1);StackPush(S, begin);}//进行右区间的遍历if (begin + 1 < end) {//同理,要先把end装进去StackPush(S, end);StackPush(S, begin + 1);}}free(S);//注意,不能在此算法内这样写,因为这是的a是首元素地址,即指针,sizeof(a)为地址的大小//Print(a, sizeof(a) / sizeof(int));
}
void Print(int* a, int n) {for (int i = 0; i < n; i++) {fprintf(stdout, "%d ", a[i]);}puts("");
}
int main() {int a[] = { 0,5,7,9,3,4,1,6,2,8 };QuickSort(a, 0, sizeof(a) / sizeof(int) - 1);Print(a, sizeof(a) / sizeof(int));return 0;
}

运行图:


四,快排的效率

1,快排的效率分析

        快排效率在平常说是效率比较高的,大致根据二叉树原理计算,快排时间复杂度为O(nlogn),空间复杂度为O(logn),但这只是对于大多时候,其实快排的时间效率是很不确定的,快排的效率跟数据的原有序列有关,序列越接近有序,快排效率越低。我们先观察以下图:

快排效率最好情况


快排效率最坏情况

        可知,快排预排序的时间效率在区间[logn,n],当原有序列越有序时,无论是递归还是非递归时间效率都很低,有序时效率最低,而遍历元素的时间复杂度不变,一直是O(n),因此快排的时间效率在区间[nlogn,n^2]。


2,三数取中

        当快排在有序时(升序为例),数据会靠近左边进行排序,而要想提高快排的效率,就必须尽量让基准值尽量往中间靠拢,但这样很难控制,因为这与数据原有的序列有关。虽然说我们不能直接控制,但是我们可控制最坏情况来进而控制时间效率,即序列有序时的情况。

        通常,我们是选取首元素为基准值的,因此,只要控制好首元素不为基准值的情况即可,也就是三数取中。

        三数取中是将判断首元素,尾元素,中间元素三者之间的大小,将中间大的数据与首元素交换,使首元素不可能为基准值。代码如下:

int GetMidi(int* a, int left, int right)
{
    int mid = (left + right) / 2;//中间数mid
    //下面比较 left mid right 三者之间大小,将中间大的数据的下标返回过去
    //先人left与mid比较,然后进一步判断right

    if (a[left] < a[mid])
    {
        if (a[mid] < a[right])
        {
            return mid;
        }
        else if (a[left] > a[right])  // mid是最大值
        {
            return left;
        }
        else
        {
            return right;
        }
    }
    else
    {
        if (a[mid] > a[right])
        {
            return mid;
        }
        else if (a[left] < a[right]) // mid是最小
        {
            return left;
        }
        else
        {
            return right;
        }
    }
}

        具体思想就是先两两比较,然后进一步与第三者比较,上面代码中选举了left与mid两者之间比较,然后再跟第三者right比较,满足中间大的数据返回其下标。


3,改善后算法的运用

        有了三数取中,快排将不会出现最坏情况,虽说有可能会出现次坏情况,但基本是不可能的,因为这种情况很是要求原序列的次序和三数取中的交换,因次,如若在算法中加上三数取中后算法的时间复杂度基本为O(nlogn)。下面是改进后运用的代码:

int GetMidi(int* a, int left, int right)
{
    int mid = (left + right) / 2;//中间数mid
    //下面比较 left mid right 三者之间大小,将中间大的数据的下标返回过去
    //先人left与mid比较,然后进一步判断right

    if (a[left] < a[mid])
    {
        if (a[mid] < a[right])
        {
            return mid;
        }
        else if (a[left] > a[right])  // mid是最大值
        {
            return left;
        }
        else
        {
            return right;
        }
    }
    else
    {
        if (a[mid] > a[right])
        {
            return mid;
        }
        else if (a[left] < a[right]) // mid是最小
        {
            return left;
        }
        else
        {
            return right;
        }
    }
}
void Swap(int* x1, int* x2) {
    int t = *x1;
    *x1 = *x2;
    *x2 = t;
}
//普通法
int PartSort1(int* a, int begin, int end) {
    //运用三数取中,与每次预排序的区间首元素交换,防止出现最坏情况
    int midi = GetMidi(a, begin, end);
    Swap(a + begin, a + midi);
    //以下代码正常不变
    int key = begin;
    while (begin < end) {
        //注意此步骤,end必须先开始(即当左边开始行走右边一定有比key小的值),
        //因为要控制最后的begin最终比key(开头元素)小,因此,右边必须先走.

        while (begin < end && a[end] >= a[key]) {
            end--;
        }
        //当走左边时,最终会Swap(a + end, a + begin);交换后begin的最终比key小
        while (begin < end && a[begin] <= a[key]) {
            begin++;
        }
        Swap(a + end, a + begin);
    }
    Swap(a + key, a + begin);
    return begin;
}
//挖坑发
int PartSort2(int* a, int begin, int end) {
    //运用三数取中,与每次预排序的区间首元素交换,防止出现最坏情况
    int midi = GetMidi(a, begin, end);
    Swap(a + begin, a + midi);
    //以下代码正常不变
    int key = a[begin];
    int hole = begin;//开头先形成坑位
    while (begin < end) {
        // 右边先走(原理与PartSort1原理一样),找小,填到左边的坑,右边形成新的坑位
        while (begin < end && a[end] >= key) {
            end--;
        }
        a[hole] = a[end];
        hole = end;
        // 左边再走,找大,填到右边的坑,左边形成新的坑位
        while (begin < end && a[begin] <= key) {
            begin++;
        }
        a[hole] = a[begin];
        hole = begin;
    }
    a[hole] = key;
    return hole;
}
//前后指针法
int PartSort3(int* a, int begin, int end) {
    //运用三数取中,与每次预排序的区间首元素交换,防止出现最坏情况
    int midi = GetMidi(a, begin, end);
    Swap(a + begin, a + midi);
    //以下代码正常不变
    int front = begin + 1;
    int back = begin;
    while (front <= end) {
        if (a[front] <= a[begin]) {
            back++;
            Swap(a + back, a + front);
        }
        front++;
    }
    //因为后指针控制,所以当程序结束后back所指向的数据都比keyi所指向的数据小
    Swap(a + begin, a + back);
    return back;
}

        在以上中,除了预排序算法需要改进,其它的都不用动即可实现高效的快排。最后,跟大家再次强调一下快排的效率,快排在大多数情况下确实效率很高,但快排的效率受原数据的序列影响比较大,当序列越接近有序时,快排的效率可能还没有其它算法高,在以后的运用中要不要用快排还需根据原数据的情况而定。

相关文章:

【数据结构】快排的详细讲解

目录&#xff1a; 介绍 一&#xff0c;递归快排确定基准值 二&#xff0c;递归遍历 三&#xff0c;非递归的快排 四&#xff0c;快排的效率 介绍 快排是排序算法中效率是比较高的&#xff0c;快排的基本思想是运用二分思想&#xff0c;与二叉树的前序遍历类似&#xff0c;…...

蓝牙资讯|三星推迟发布智能戒指Galaxy Ring,智能穿戴小型化是大趋势

根据外媒 The Elec 报道&#xff0c;Galaxy Ring这款戒指主要面向健康和 XR 头显市场&#xff0c;该智能戒指可能被延期至 2024 年第三季度后发布。 外媒声称三星 Galaxy Ring 的上市周期&#xff0c;主要取决医疗认证的相关审批时间&#xff0c;三星计划将在 2024 年第三季度…...

移动端tree树

注意&#xff1a; 这是uniapp的写法&#xff0c;vue想用的话需要改造一下&#xff0c;里边的view和text&#xff0c;vue不能用&#xff0c;改成div&#xff0c;span即可。 样式rpx也要改成px tree树组件(QQ群&#xff1a;旧群没了&#xff0c;新群&#xff1a;801142650) - …...

SpringTask ----定时任务框架 ----苍穹外卖day10

目录 SpringTask 需求分析 快速入门 使用步骤 ​编辑业务开发 SpringTask 定时任务场景特化的框架 需求分析 快速入门 使用cron表达式来使用该框架 使用步骤 添加注解 自定义定时任务类 重点在于以下cron表达式的书写,精确表达触发的间隔 业务开发 主task方法 time使用(-…...

Fuzz测试:发现软件隐患和漏洞的秘密武器

0x01 什么是模糊测试 模糊测试&#xff08;Fuzz Testing&#xff09;是一种广泛用于软件安全和质量测试的自动化测试方法。它的基本思想是向输入参数或数据中注入随机、不规则或异常的数据&#xff0c;以检测目标程序或系统在处理不合法、不正常或边缘情况下的行为。模糊测试通…...

无为WiFi的一批服务器

我们在多个地区拥有高速服务器&#xff0c;保证网速给力&#xff0c;刷片无压力 嘿嘿 <?phpinclude("./includes/common.php"); $actisset($_GET[act])?daddslashes($_GET[act]):null; $urldaddslashes($_GET[url]); $authcodedaddslashes($_GET[authcode]);he…...

SpringBoot3.0——踩坑

SpringBoot3.0后有一些改动 JDK要17以上lombok <dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.20</version> </dependency>servlet <dependency><groupId>ja…...

Springboot的自动装配原理和文件上传FastDFS

Spring Boot的自动装配原理&#xff1a; Spring Boot的自动装配原理是基于约定大于配置的原则&#xff0c;它通过扫描类路径下的各种文件以及类的注解信息来自动配置应用程序的各种组件和功能。Spring Boot会根据约定的规则自动配置相应的Bean&#xff0c;这些Bean都是单例的&…...

【数据库开发】DQL操作和多表设计

数据库开发 一、数据库操作-DQL 1.概述 用来查询数据库表中的记录&#xff0c;查询操作分为两部分&#xff0c;单表操作和多表操作&#xff0c;针对于查询而言&#xff08;相较于增删改更加的灵活&#xff09;基于目标分析条件转换为SQL语句 2.语法 SELECT 字段列表 FROM表…...

用PyTorch轻松实现二分类:逻辑回归入门

&#x1f497;&#x1f497;&#x1f497;欢迎来到我的博客&#xff0c;你将找到有关如何使用技术解决问题的文章&#xff0c;也会找到某个技术的学习路线。无论你是何种职业&#xff0c;我都希望我的博客对你有所帮助。最后不要忘记订阅我的博客以获取最新文章&#xff0c;也欢…...

[nltk_data] Error loading stopwords: <urlopen error [WinError 10054]

报错提示&#xff1a; >>> import nltk >>> nltk.download(stopwords) 按照提示执行后 [nltk_data] Error loading stopwords: <urlopen error [WinError 10054] 找到路径C:\\Users\\EDY\\nltk_data&#xff0c;如果没有nltk_data文件夹&#xff0c;在…...

基于Spring Boot的网上租贸系统设计与实现(源码+lw+部署文档+讲解等)

文章目录 前言具体实现截图论文参考详细视频演示为什么选择我自己的网站自己的小程序&#xff08;小蔡coding&#xff09;有保障的售后福利 代码参考源码获取 前言 &#x1f497;博主介绍&#xff1a;✌全网粉丝10W,CSDN特邀作者、博客专家、CSDN新星计划导师、全栈领域优质创作…...

通过IP地址管理提升企业网络安全防御

在今天的数字时代&#xff0c;企业面临着越来越多的网络安全威胁。这些威胁可能来自各种来源&#xff0c;包括恶意软件、网络攻击和数据泄露。为了提高网络安全防御&#xff0c;企业需要采取一系列措施&#xff0c;其中IP地址管理是一个重要的方面 1. IP地址的基础知识 首先&a…...

termius mac版无需登录注册直接永久使用

1. 下载地址&#xff1a;termius下载 2. 解压安装 3. 当出现 “termius”已损坏,无法打开 则输入以下命令即可&#xff1a;sudo xattr -r -d com.apple.quarantine /Applications/Termius.app 最后去 系统设置-> 隐私与安全性-> 仍要打开 4. 删除app-update.yml文件&…...

TPU编程竞赛|Stable Diffusion大模型巅峰对决,第五届全球校园人工智能算法精英赛正式启动!

目录 赛题介绍 赛题背景 赛题任务 赛程安排 评分机制 奖项设置 近日&#xff0c;2023第五届全球校园人工智能算法精英赛正式开启报名。作为赛题合作方&#xff0c;算丰承办了“算法专项赛”赛道&#xff0c;提供赛题「面向Stable Diffusion的图像提示语优化」&#xff0c…...

微信小程序 rpx 转 px

前言 略 rpx 转 px let query wx.createSelectorQuery(); query.selectViewport().boundingClientRect(function(res){let rpx2Px 1 * (res.width/750);console.log("1rpx " rpx2Px "px"); }); query.exec();参考 https://blog.csdn.net/qq_39702…...

机器学习之旅-从Python 开始

导读你想知道如何开始机器学习吗&#xff1f;在这篇文章中&#xff0c;我将简要概括一下使用 Python 来开始机器学习的一些步骤。Python 是一门流行的开源程序设计语言&#xff0c;也是在人工智能及其它相关科学领域中最常用的语言之一。机器学习简称 ML&#xff0c;是人工智能…...

100天精通Python(可视化篇)——第103天:Pyecharts绘制多种炫酷水球图参数说明+代码实战

文章目录 专栏导读一、水球图介绍1. 水球图是什么?2. 水球图的应用场景二、水球图类配置选项1. 导包2. Liquid类3. add函数三、水球图实战1. 基础水球图2. 矩形水球图3. 圆棱角矩形水球图4. 三角形水球图5. 菱形水球图6. 箭头型水球图7. 修改数据精度8. 设置无边框9. 多个并排…...

好用的文件备份软件推荐!

为什么需要文件备份软件&#xff1f; 在我们使用计算机的日常工作生活中&#xff0c;可能会遇到各种不同类型的文件&#xff0c;例如文档、Word文档、Excel表格、PPT演示文稿、图片等&#xff0c;这些数据中可能有些对我们来说很重要&#xff0c;但是可能会因为一些意外状况…...

1130 - Host ‘192.168.10.10‘ is not allowed to connect to this MysOL server

mysql 远程登录报错误信息&#xff1a;1130 - Host 124.114.155.70 is not allowed to connect to this MysOL server //需要在mysql 数据库目录下修改 use mysql; //更改用户的登录主机为所有主机&#xff0c;%代表所有主机 update user set host% where userroot; //刷新权…...

如何实现 Es 全文检索、高亮文本略缩处理

如何实现 Es 全文检索、高亮文本略缩处理 前言技术选型JAVA 常用语法说明全文检索开发高亮开发Es Map 转对象使用核心代码 Trans 接口&#xff08;支持父类属性的复杂映射&#xff09;Trans 接口的不足真实项目落地效果 前言 最近手上在做 Es 全文检索的需求&#xff0c;类似于…...

Netty(四)NIO-优化与源码

Netty优化与源码 1. 优化 1.1 扩展序列化算法 序列化&#xff0c;反序列化主要用于消息正文的转换。 序列化&#xff1a;将java对象转为要传输对象(byte[]或json&#xff0c;最终都是byte[]) 反序列化&#xff1a;将正文还原成java对象。 //java自带的序列化 // 反序列化 b…...

我的创业之路:我为什么选择 Angular 作为前端的开发框架?

我是一名后端开发人员&#xff0c;在上班时我的主要精力集中在搜索和推荐系统的开发和设计工作上&#xff0c;我比较熟悉的语言包括java、golang和python。对于前端技术中typescript、dom、webpack等流行的框架和工具也懂一些。目前&#xff0c;已成为一名自由职业者&#xff0…...

阿里云服务器ECS是什么?云服务器详细介绍

阿里云服务器ECS英文全程Elastic Compute Service&#xff0c;云服务器ECS是一种安全可靠、弹性可伸缩的云计算服务&#xff0c;阿里云提供多种云服务器ECS实例规格&#xff0c;如经济型e实例、通用算力型u1、ECS计算型c7、通用型g7、GPU实例等&#xff0c;阿里云服务器网分享阿…...

深入了解快速排序:原理、性能分析与 Java 实现

快速排序&#xff08;Quick Sort&#xff09;是一种经典的、高效的排序算法&#xff0c;被广泛应用于计算机科学和软件开发领域。本文将深入探讨快速排序的工作原理、步骤以及其在不同情况下的性能表现。 什么是快速排序&#xff1f; 快速排序是一种基于分治策略的排序算法&am…...

[晕事]今天做了件晕事22;寻找99-sysctl.conf; systemd

这个文件&#xff0c;使用ls命令看不出来是一个链接。 然后满世界的找这个文件怎么来的&#xff0c;后来发现是systemd里的一个文件。 从systemd的源文件里也没找到相关的文件信息。 最后把这个rpm安装包下载下来&#xff0c;才找到这个文件原来是一个链接 #ll /etc/sysctl.d/9…...

2578. 最小和分割

给你一个正整数 num &#xff0c;请你将它分割成两个非负整数 num1 和 num2 &#xff0c;满足&#xff1a; num1 和 num2 直接连起来&#xff0c;得到 num 各数位的一个排列。 换句话说&#xff0c;num1 和 num2 中所有数字出现的次数之和等于 num 中所有数字出现的次数。num1…...

Mybatis mapper报错:Class not found: org.jboss.vfs.VFS

报错 Logging initialized using class org.apache.ibatis.logging.stdout.StdOutImpl adapter. Class not found: org.jboss.vfs.VFS JBoss 6 VFS API is not available in this environment. Class not found: org.jboss.vfs.VirtualFile VFS implementation org.apache.iba…...

ARM作业1

三盏灯流水 代码 .text .global _start _start: 1.设置GPIOE寄存器的时钟使能 RCC_MP_AHB4ENSETR[4]->1 0x50000a28 LDR R0,0X50000A28 LDR R1,[R0] 从r0为起始地址的4字节数据取出放在R1 ORR R1,R1,#(0x3<<4) 第4位设置为1 STR R1,[R0] 写回2.设置PE10管…...

leetcode 502. IPO

假设 力扣&#xff08;LeetCode&#xff09;即将开始 IPO 。为了以更高的价格将股票卖给风险投资公司&#xff0c;力扣 希望在 IPO 之前开展一些项目以增加其资本。 由于资源有限&#xff0c;它只能在 IPO 之前完成最多 k 个不同的项目。帮助 力扣 设计完成最多 k 个不同项目后…...

网站链接文字/郑州网站推广公司咨询

一、Git fetch和git pull的区别: 都可以从远程获取最新版本到本地 1.Git fetch:只是从远程获取最新版本到本地,不会merge(合并) git fetch origin master //从远程的origin的master主分支上获取最新版本到origin/master分支上 git log -p master..origin/master //比较本地…...

好用的网站后台/域名申请的流程

题目&#xff1a; 给定一个排序数组和一个目标值&#xff0c;在数组中找到目标值&#xff0c;并返回其索引。如果目标值不存在于数组中&#xff0c;返回它将会被按顺序插入的位置。 请必须使用时间复杂度为 O(log n) 的算法。 示例 1: 输入: nums [1,3,5,6], target 5 输出: …...

织梦上网站次导航怎么做/关键词seo资源

昨天&#xff0c;2018京东人工智能创新峰会举行&#xff0c;京东集团副总裁、AI 平台与研究部负责人周伯文揭开了京东技术布局下的 AI 战略全景图。这个全景图概括起来说就是“三大主体、七大应用场景和五个人工智能产业化的布局方向”&#xff0c;即&#xff1a;以 AI 开放平台…...

河北秦皇岛建设局网站/百度首页入口

CentOS 6.9 SSH配置用户免密码登录 1、 演示环境&#xff1a; 192.168.1.144&#xff1a;CentOS 6.9 x86_64 192.168.1.146&#xff1a;CentOS 7.4 x86_64 2、 演示目标&#xff1a;192.168.1.144通过密钥认证的方式免密码直接登录192.168.1.146 3、 192.168.1.144安装软件包&a…...

东莞公司注册地址变更流程/青岛seo推广

题目链接&#xff1a;http://poj.org/problem?id1068 思路分析&#xff1a;对栈的模拟&#xff0c;将栈中元素视为广义表&#xff0c;如 (((()()())))&#xff0c;可以看做 LS < a1, a2..., a12 >,对于可以配对的序列&#xff0c;如 <a4, a5>看做一个元素&#xf…...

怎样用手机做推广免费网站/seo主要做什么

Navicat for Oracle 经常断开 右键 打开连接属性...