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

链表的快速排序(C/C++实现)

一、前言

大家在做需要排名的项目的时候,需要把各种数据从高到低排序。如果用的快速排序的话,处理数组是十分简单的。因为数组的存储空间的连续的,可以通过下标就可以简单的实现。但如果是链表的话,内存地址是随机分配的,不能像数组那样通过下标就直接实现。所以在这里给大家介绍一个简单实现的快速排序。

二、快速排序简单介绍

快速排序的是交换排序其中的一种,主要是采用分治的思想,每次迭代在当前区间中选取一个数作为哨兵,通过一系列的交换操作将当前区间分为左区间和右区间【使得左区间的值全部小于等于哨兵,右区间的值全部大于等于哨兵】。然后再对左区间、右区间执行这种划分区间的策略操作,当区间的长度为1时停止。等到所有分治的区间长度都为1时,此时的原数组就已经是一个排好序的数组了。代码如下:

void quickSort(int q[], int l, int r)
{// 当前区间的长度小于等于1时停止循环if (l >= r)  return;// 创建哨兵 midint mid = q[l];// 创建i,j指针进行移动int i = l, j = r;// 进行区间数字交换,使得左侧区间全小于等于mid,右侧区间全大于等于midwhile (i < j){// j指针从右向左移动,至到遇到第一个小于哨兵的值while (q[j] >= mid && i < j) j--;// 将该值移动到左区间中q[i] = q[j];// i指针从左向右移动,至到遇到第大个小于哨兵的值while (q[i] <= mid && i < j) i++;// 将该值移动到右区间中q[j] = q[i];}// 交换结束后此时i,j指针指向的同一个位置,即哨兵应该放的位置// 而左区间已经是全部小于等于哨兵的值,右区间已经是全部大于等于哨兵的值了。q[i] = mid;// 对划分出来的左右区间的再一次进行快排quickSort(q, l, i - 1);quickSort(q, i + 1, r);
}

但这只适用于连续存储空间。对于链表来说,不太适用。所以接下来我将介绍一个比较简单的代码来实现链表的快速排序。

三、代码实现:

该链表是包含有头结点的,即第一个结点不放数据):

// 自定义的结构体,用来存储链表的内容
typedef struct node
{int data = -1; // 数据域struct node* next = NULL; // 指针域,指向后一个元素struct node* pre = NULL; // 指针域,指向前一个元素
}NODE;//别名
// 函数声明
// 判断l是否走到了r的右边,如果在返回true,如果不在则返回false 【要求l和r在同一个链表上,且定义时l是r左侧的节点】
bool isRight(const NODE* l, const NODE* r);
// 判断l是否还在r的左边,如果在返回true,如果不在则返回false【要求l和r在同一个链表上,且定义时l是r左侧的节点】
bool isLeft(const NODE* l, const NODE* r);
// 在链表中挖出这个节点,即断开这个节点和链表的关系
NODE* dug(NODE* node);
// 在node所属的链表中,在node节点前插入target节点【此时target节点是一个孤立的节点,并没有链接链表】
void insertBefore(NODE* node, NODE* target);
// 在node所属的链表中,在node节点后插入target节点【此时target节点是一个孤立的节点,并没有链接链表】
void insertAfter(NODE* node, NODE* target);
// 进行快速排序
void quickSort(NODE* l, NODE* r) 
{// 如果当前区间的元素已经只剩一个或者不剩了,那么结束递归if (isRight(l, r)) {return;}// 记录当前区间的外的前一个节点和当前区间外的后一个节点,防止进行交换后这个区间的第一个节点和最后一个节点的顺序找不到了// 由于头节点的存在,可以保证该区间外一定存在前一个节点NODE* preL = l->pre;// 但是不一定该区间外是否还有后一个节点NODE* nextR;bool tailDug = false; //标记是否给该区间外创建了后一个节点// 如果该区间外没有后一个节点了if (r->next == NULL) {// 则创建一个新的节点用来记录区间的最后一个节点nextR = (NODE*)malloc(sizeof(NODE));r->next = nextR;nextR->pre = r;nextR->next = NULL;tailDug = true;} // 如果该区间外后面还有一个节点,则直接使用这个节点来帮助记录区间的末尾节点else{nextR = r->next;}// 选择哨兵节点【区间的第一个节点】NODE* mid = dug(l);// 更新左、右指针的位置NODE* i = preL->next, * j = nextR->pre;// 进行快排的交换移动// 当左指针还在右指针的左侧时,进行交换判断while (isLeft(i, j)){// 右指针左移,至到遇到第一个小于哨兵的节点或者i,j指针相遇了,那么就停下while (j->data >= mid->data && isLeft(i, j)) { j = j->pre; }NODE* temp = NULL;// 如果此时i,j指针还未相遇,则右指针当前指向的节点是小于哨兵的节点,需要移动到左区间中。【说明它满足的上面while的 j->data >= mid->data】if (isLeft(i, j)) {// j指针前移一位,因为上面的判断已经知道当前这个节点应该放在左区间了,故下一次判断时j指针不需要判断这个节点了,直接从前一个节点开始判断即可。j = j->pre;// 将刚才j指针找到的节点移动到i节点前面,【因为i节点的左侧都应该是小于等于哨兵值的节点】temp = j->next;dug(temp);insertBefore(i, temp);}// 左指针右移,至到遇到第一个大于哨兵的节点或者i,j指针相遇了,那么就停下while (i->data <= mid->data && isLeft(i, j)) { i = i->next; }// 如果此时i,j指针还未相遇,则左指针当前指向的节点是大于哨兵的节点,需要移动到右区间中。【说明它满足的上面while的 i->data <= mid->data 】if (isLeft(i, j)) {// i指针后移一位,因为上面的判断已经知道当前这个节点应该放在右区间了,故下一次判断时i指针不需要判断这个节点了,直接从后一个节点开始判断即可。i = i->next;// 将刚才i指针找到的节点移动到j节点后面,【因为j节点的右侧都应该是大于等于哨兵值的节点】temp = i->pre;dug(temp);insertAfter(j, temp);}}// 此时的i,j指针已经相遇了,故下面使用到i的地方都可以替换为j// 最后一次填坑,此时只剩哨兵这个节点的位置需要重新放进来了。// 如果当前节点小于哨兵,则代表当前相遇位置的节点【i,j】是左区间的最后一个节点,那么哨兵应该放在该节点的右侧if (i->data < mid->data) {insertAfter(i, mid);//当前相遇的节点【i,j】代表左区间的最后一个元素,故放在该节点后面即代表放在了左区间和右区间的正中间} // 否则代表当前相遇位置的节点【i,j】是右区间的第一个节点,那么哨兵应该放在该节点的左侧else {insertBefore(i, mid);//当前相遇的节点【i,j】代表右区间的第一个元素,故放在该节点前面即代表放在了左区间和右区间的正中间}// 更新这个区间的区间内的第一个节点和最后一个节点l = preL->next;r = nextR->pre;// 如果区间外的后一个节点实际上是不存在的,那么删除这个被我们临时创建出来的节点if (tailDug) {dug(nextR);}// 进行左右区间的快排quickSort(l, mid->pre), quickSort(mid->next, r);
}
// 函数实现
bool isRight(const NODE* l, const NODE* r)
{return l == NULL || r == NULL || l == r || l == r->next;
}
bool isLeft(const NODE* l, const NODE* r)
{return !isRight(l, r);//如果不在右边,则代表在左边
}
NODE* dug(NODE* node)
{// 如果当前节点在链表中是最后一个节点if (node->next == NULL){// 则将前一个节点指向NULL即可NODE* l = node->pre;l->next = NULL;return node;}// 如果当前节点不是最后一个节点else{// 将当前节点在链表中的前一个节点与当前节点在链表中的后一个节点联系起来NODE* l = node->pre;NODE* r = node->next;l->next = r;r->pre = l;// 断开当前节点与链表的联系node->pre = NULL;node->next = NULL;return node;}
}
void insertBefore(NODE* node, NODE* target)
{// 获取链表中node的前一个节点NODE* l = node->pre;// 将target节点插入到 l 节点和 node 节点之间l->next = target;node->pre = target;target->pre = l;target->next = node;
}
void insertAfter(NODE* node, NODE* target)
{// 获取链表中node的后一个节点NODE* r = node->next;// 将target节点插入到 node 节点和 r 节点之间r->pre = target;node->next = target;target->pre = node;target->next = r;
}

四、分析讲解

假设需要排序的链表数据为:2 3 6 1 9。那么链表的结构如下:
在这里插入图片描述

4.1 第一个递归过程

4.1.1 数据预处理

4.1.1.1 需要处理的链表结点【区间数据】

在这里插入图片描述

4.1.1.2 本次递归的结点介绍【未获取哨兵结点之前】

在这里插入图片描述
提示:由于需要处理的区间结点的最后一个结点9 后面不再有结点,故需要 创建一个新的结点nextR 插入在9这个结点后面,这样就可以精准的找到我们这个区间的最后一个数据结点的位置【由于nextR这个结点是不会进行位置交换的,故nextR的前一个结点一定是当前区间的最后一个数据结点】。

4.1.1.3 获取哨兵结点

在这里插入图片描述
提示:哨兵结点mid是一般取的是区间的第一个结点,即2这个结点。而本文的快速排序会将哨兵结点从链表中挖出去,这样可以方便后续的处理。故现在区间结点只有四个数据了,即3 6 1 9

4.1.1.4 本次递归所有结点介绍

在这里插入图片描述
结点介绍:
mid:哨兵结点,用于确定其他每个结点的位置,来使得其他结点进行移动。
l:区间的第一个结点,一般只在初始化其他结点的时候用到。
r:区间的最后一个结点,一般只在初始化其他结点的时候用到。
preL:区间第一个结点的前一个结点,由于位置不会发生改变,故用来找区间的第一个结点。
nextR:区间最后一个结点的后一个结点,由于位置不会发生改变,故用来找区间的最后一个结点。
i:从区间的第一个结点向区间的最后一个结点进行移动,用于每一次循环移动数据的结点判断。
j:从区间的最后一个结点向区间的第一个结点进行移动,用于每一次循环移动数据的结点判断。

4.1.2 循环移动数据

4.1.2.1 第一次循环结果

目的:第一次循环,判断j所在的结点是否需要移动位置。
过程
第一步: j当前所在的结点是9,由于9大于哨兵结点2,故当前结点不需要移动,j结点向左移动,此时j结点成为了1结点。
第二步: j当前所在的结点是1,由于1小于于哨兵结点2,故当前结点需要移动。将当前j所在的结点【1结点】移动到i所在的结点【3结点】前面。让j的位置仍然保持距离区间最后一个结点的距离不变,那么此时j所指向的结点即为6结点。【因为从区间结尾开始处理的话,此时只有9结点正常通过判断确定了位置,但是6结点还未通过判断确定位置,那么j就应该指向区间最后一个未确认位置的结点
在这里插入图片描述

4.1.2.2 第二次循环结果

目的:第二次循环,判断i所在的结点是否需要移动位置。
过程
第一步: i当前所在的结点是3,由于3大于哨兵结点2,故当前结点需要移动。将当前i所在的结点【3结点】移动到j所在的结点【6结点】后面。让i的位置仍然保持距离区间第一个结点的距离不变,那么此时i所指向的结点即为6结点。【因为从区间开始开始处理的话,此时只有1结点正常通过判断确定了位置,但是6结点还未通过判断确定位置,那么i就应该指向区间第一个未确认位置的结点
在这里插入图片描述

4.1.2.3 第三次循环结果

目的:由于ij指针已经相遇,那么目前只需要确定哨兵结点的位置,本轮循环就结束了。
过程:由于快排算法的性质决定了,i指针左侧的结点都小于哨兵结点的值,j指针右侧结点的值都大于哨兵结点的值。故我们比较一下当前i结点(或者j结点,因为每次循环到了最后一步的时候,ij结点都会相遇)的值和哨兵结点的值的大小。由于i结点6大于哨兵结点2,那么哨兵结点2就需要插入到链表中i结点6的左侧。此时本轮位置移动已经完成,哨兵结点2的左侧结点均为小于哨兵结点值的结点,哨兵结点2的右侧结点均为大于哨兵结点值的结点。
在这里插入图片描述

4.1.2.4 下一次循环的区间划分

目的:本轮位置移动已经完成了,已经确定了结点2的位置,但其他结点的位置还未确定,还需要继续进行分冶结点2两侧的区间进行快排位置移动。
过程:最开始指向区间头、尾的结点的lr,在进行了无数次交换了,我们可以发现它们已经不在区间的第一个结点和最后一个结点了。但由于preLnextR结点始终没有移动过位置,preL的下一个结点一直指向的是区间的第一个结点【目前指向的结点1,即快排结束后区间的第一个结点】,nextR的上一个结点一直指向的是区间的最一个结点【目前指向的结点9,即快排结束后区间的最后一个结点】。故我们可以确定需要继续进行快排的两个区间为:preL->next, mid->premid->next, nextR->pre。【即(preL的下一个结点,哨兵结点的上一个结点)、(哨兵结点的下一个结点,nextR的上一个结点)】。而哨兵结点已经确定好在整个链表的位置了,故不需要参与后续的其他区间迭代的位置移动了。而由于此时nextR结点是创建的新结点,在原因链表中不需要,在最后我们将该结点从链表中删掉即可。
故下一轮的递归区间为:
在这里插入图片描述

五、可运行的完整代码:

#include<stdio.h>
#include<stdlib.h>// 自定义的结构体,用来存储链表的内容
typedef struct node
{int data = -1; // 数据域struct node* next = NULL; // 指针域,指向后一个元素struct node* pre = NULL; // 指针域,指向前一个元素
}NODE;//别名// 找到链表的最后一个节点
NODE* findTail(NODE* head) 
{while (head->next != NULL) { //当没有下一个元素的时候,就代表当前元素是链表的最后一个元素head = head->next;}return head;
}// 给链表新增节点
void add(NODE* head, int data)
{NODE* tail = findTail(head); //获取链表的最后一个节点// 创建新节点NODE* p = (NODE*)malloc(sizeof(NODE));// p 为新增的结点p->data = data; // 把值赋给p中的data域p->next = NULL; // 初始化操作,p是最后一个节点,故没有下一个节点了,因此next指针域需要指向NULL// 将新创建的结点与当前链表创建关联p->pre = tail; //新节点左指针域应该指向链表中的最后一个节点tail->next = p; //链表中最后一个节点的右指针域应该指向这个新节点。【至此新节点成功加入到链表中】
}// 判断l是否走到了r的右边,如果在返回true,如果不在则返回false 【要求l和r在同一个链表上,且定义时l是r左侧的节点】
bool isRight(const NODE* l, const NODE* r) 
{return l == NULL || r == NULL || l == r || l == r->next;
}// 判断l是否还在r的左边,如果在返回true,如果不在则返回false【要求l和r在同一个链表上,且定义时l是r左侧的节点】
bool isLeft(const NODE* l, const NODE* r) 
{return !isRight(l, r);//如果不在右边,则代表在左边
}// 在链表中挖出这个节点,即断开这个节点和链表的关系
NODE* dug(NODE* node) 
{// 如果当前节点在链表中是最后一个节点if (node->next == NULL) {// 则将前一个节点指向NULL即可NODE* l = node->pre;l->next = NULL;return node;}// 如果当前节点不是最后一个节点else {// 将当前节点在链表中的前一个节点与当前节点在链表中的后一个节点联系起来NODE* l = node->pre;NODE* r = node->next;l->next = r;r->pre = l;// 断开当前节点与链表的联系node->pre = NULL;node->next = NULL;return node;}
}// 在node所属的链表中,在node节点前插入target节点【此时target节点是一个孤立的节点,并没有链接链表】
void insertBefore(NODE* node, NODE* target)
{// 获取链表中node的前一个节点NODE* l = node->pre;// 将target节点插入到 l 节点和 node 节点之间l->next = target;node->pre = target;target->pre = l;target->next = node;
}// 在node所属的链表中,在node节点后插入target节点【此时target节点是一个孤立的节点,并没有链接链表】
void insertAfter(NODE* node, NODE* target)
{// 获取链表中node的后一个节点NODE* r = node->next;// 将target节点插入到 node 节点和 r 节点之间r->pre = target;node->next = target;target->pre = node;target->next = r;
}// 进行快速排序
void quickSort(NODE* l, NODE* r) 
{// 如果当前区间的元素已经只剩一个或者不剩了,那么结束递归if (isRight(l, r)) {return;}// 记录当前区间的外的前一个节点和当前区间外的后一个节点,防止进行交换后这个区间的第一个节点和最后一个节点的顺序找不到了// 由于头节点的存在,可以保证该区间外一定存在前一个节点NODE* preL = l->pre;// 但是不一定该区间外是否还有后一个节点NODE* nextR;bool tailDug = false; //标记是否给该区间外创建了后一个节点// 如果该区间外没有后一个节点了if (r->next == NULL) {// 则创建一个新的节点用来记录区间的最后一个节点nextR = (NODE*)malloc(sizeof(NODE));r->next = nextR;nextR->pre = r;nextR->next = NULL;tailDug = true;} // 如果该区间外后面还有一个节点,则直接使用这个节点来帮助记录区间的末尾节点else{nextR = r->next;}// 选择哨兵节点【区间的第一个节点】NODE* mid = dug(l);// 更新左、右指针的位置NODE* i = preL->next, * j = nextR->pre;// 进行快排的交换移动// 当左指针还在右指针的左侧时,进行交换判断while (isLeft(i, j)){// 右指针左移,至到遇到第一个小于哨兵的节点或者i,j指针相遇了,那么就停下while (j->data >= mid->data && isLeft(i, j)) { j = j->pre; }NODE* temp = NULL;// 如果此时i,j指针还未相遇,则右指针当前指向的节点是小于哨兵的节点,需要移动到左区间中。【说明它满足的上面while的 j->data >= mid->data】if (isLeft(i, j)) {// j指针前移一位,因为上面的判断已经知道当前这个节点应该放在左区间了,故下一次判断时j指针不需要判断这个节点了,直接从前一个节点开始判断即可。j = j->pre;// 将刚才j指针找到的节点移动到i节点前面,【因为i节点的左侧都应该是小于等于哨兵值的节点】temp = j->next;dug(temp);insertBefore(i, temp);}// 左指针右移,至到遇到第一个大于哨兵的节点或者i,j指针相遇了,那么就停下while (i->data <= mid->data && isLeft(i, j)) { i = i->next; }// 如果此时i,j指针还未相遇,则左指针当前指向的节点是大于哨兵的节点,需要移动到右区间中。【说明它满足的上面while的 i->data <= mid->data 】if (isLeft(i, j)) {// i指针后移一位,因为上面的判断已经知道当前这个节点应该放在右区间了,故下一次判断时i指针不需要判断这个节点了,直接从后一个节点开始判断即可。i = i->next;// 将刚才i指针找到的节点移动到j节点后面,【因为j节点的右侧都应该是大于等于哨兵值的节点】temp = i->pre;dug(temp);insertAfter(j, temp);}}// 此时的i,j指针已经相遇了,故下面使用到i的地方都可以替换为j// 最后一次填坑,此时只剩哨兵这个节点的位置需要重新放进来了。// 如果当前节点小于哨兵,则代表当前相遇位置的节点【i,j】是左区间的最后一个节点,那么哨兵应该放在该节点的右侧if (i->data < mid->data) {insertAfter(i, mid);//当前相遇的节点【i,j】代表左区间的最后一个元素,故放在该节点后面即代表放在了左区间和右区间的正中间} // 否则代表当前相遇位置的节点【i,j】是右区间的第一个节点,那么哨兵应该放在该节点的左侧else {insertBefore(i, mid);//当前相遇的节点【i,j】代表右区间的第一个元素,故放在该节点前面即代表放在了左区间和右区间的正中间}// 更新这个区间的区间内的第一个节点和最后一个节点l = preL->next;r = nextR->pre;// 如果区间外的后一个节点实际上是不存在的,那么删除这个被我们临时创建出来的节点if (tailDug) {dug(nextR);}// 进行左右区间的快排quickSort(l, mid->pre), quickSort(mid->next, r);
}int main()
{NODE* head = (NODE*)malloc(sizeof(NODE));//定义头结点int n;//链表的长度printf("请输入链表的长度: ");scanf("%d", &n);printf("请输入链表中的数字: ");for (int i = 0; i < n; i++){int x;//每一个结点的值scanf("%d", &x);add(head, x);//向链表追加结点}//进行冒泡排序quickSort(head->next, findTail(head));NODE* p = head->next;//因为第一个结点没有存放数据,所以从第二个结点开始输出while (p != NULL){printf("%d\t", p->data);p = p->next;}return 0;
}

**

温馨提示:第一个结点不是用来放数据的,是用来辅助完成排序的。

题目测试地址:C语言网-快速排序题目测试

**

相关文章

快速排序(C/C++实现)—— 简单易懂系列
单链表的冒泡排序(C/C++实现)

相关文章:

链表的快速排序(C/C++实现)

一、前言 大家在做需要排名的项目的时候&#xff0c;需要把各种数据从高到低排序。如果用的快速排序的话&#xff0c;处理数组是十分简单的。因为数组的存储空间的连续的&#xff0c;可以通过下标就可以简单的实现。但如果是链表的话&#xff0c;内存地址是随机分配的&#xf…...

css总结(记录一下...)

文字 语法说明word-wrapword-wrap:normal| break-word normal:使用浏览器默认的换行 break-word:允许在单词内换行 text-overflow clip:修剪文本 ellipsis:显示省略符号来代表被修剪的文本 text-shadow可向文本应用的阴影。能够规定水平阴影、垂直阴影、模糊距离&#xff0c;以…...

SpringBoot 处理 @KafkaListener 消息

消息监听容器 1、KafkaMessageListenerContainer 由spring提供用于监听以及拉取消息&#xff0c;并将这些消息按指定格式转换后交给由KafkaListener注解的方法处理&#xff0c;相当于一个消费者&#xff1b; 看看其整体代码结构&#xff1a; 可以发现其入口方法为doStart(),…...

Spring Boot-API版本控制问题

在现代软件开发中&#xff0c;API&#xff08;应用程序接口&#xff09;版本控制是一项至关重要的技术。随着应用的不断迭代&#xff0c;API 的改动不可避免&#xff0c;如何在引入新版本的同时保证向后兼容&#xff0c;避免对现有用户的影响&#xff0c;是每个开发者需要考虑的…...

Git 提取和拉取的区别在哪

1. 提取&#xff08;Fetch&#xff09; 操作说明&#xff1a;Fetch 操作会从远程仓库下载最新的提交、分支信息等&#xff0c;但不会将这些更改合并到你当前的分支中。它只是将远程仓库的更新信息存储在本地&#xff0c;并不会自动修改你当前的工作区。 使用场景&#xff1a; …...

【数据结构与算法 | 每日一题 | 力扣篇】力扣2390, 2848

1. 力扣2390&#xff1a;从字符串中删除星号 1.1 题目&#xff1a; 给你一个包含若干星号 * 的字符串 s 。 在一步操作中&#xff0c;你可以&#xff1a; 选中 s 中的一个星号。移除星号 左侧 最近的那个 非星号 字符&#xff0c;并移除该星号自身。 返回移除 所有 星号之…...

破解信息架构实施的密码:常见挑战与最佳解决方案全指南

信息架构的成功实施是企业数字化转型的关键步骤&#xff0c;但在实际操作中&#xff0c;企业往往会遇到各种复杂的挑战。这些挑战包括 技术整合的难度、数据管理的复杂性、合规性要求的变化 以及 资源限制 等。《信息架构&#xff1a;商业智能&分析与元数据管理参考模型》为…...

CodeChef Starters 151 (Div.2) A~D

codechef是真敢给分&#xff0c;上把刚注册&#xff0c;这把就div2了&#xff0c;再加上一周没打过还是有点不适应的&#xff0c;好在最后还是能够顺利上分 今天的封面是P3R的设置菜单 我抠出来做我自己的游戏主页了&#xff08; A - Convert string 题意 在01串里面可以翻转…...

Redis学习——数据不一致怎么办?更新缓存失败了又怎么办?

文章目录 引言正文读写缓存的数据一致性只读缓存的数据一致性删除和修改数据不一致问题操作执行失败导致数据不一致解决办法 多线程访问导致数据不一致问题总结 总结参考信息 引言 最近面试快手的时候被问到了缓存不一致怎么解决&#xff1f;一开始还是很懵的&#xff0c;因为…...

跨境电商代购新纪元:一键解锁全球好物,系统流程全揭秘

添加图片注释&#xff0c;不超过 140 字&#xff08;可选&#xff09; 在全球化日益加深的今天&#xff0c;跨境电商代购成为了连接消费者与世界各地优质商品的桥梁。本文将在CSDN平台上&#xff0c;深入剖析跨境电商代购系统的功能流程&#xff0c;带您一窥其背后的技术奥秘与…...

Mac 上终端使用 MySql 记录

文章目录 下载安装终端进入 MySql常用操作查看数据库选择一个数据库查看当前选择的数据库Navcat 打开提示报错参考文章 下载安装 先下载社区版的 MySql 安装的过程需要设置 root 的密码&#xff0c;这个是要进入数据库所设定的&#xff0c;所以要记住 终端进入 MySql 首先输…...

461. 汉明距离

一&#xff1a;题目&#xff1a; 两个整数之间的 汉明距离 指的是这两个数字对应二进制位不同的位置的数目。 给你两个整数 x 和 y&#xff0c;计算并返回它们之间的汉明距离。 示例 1&#xff1a; 输入&#xff1a;x 1, y 4 输出&#xff1a;2 解释&#xff1a; 1 (0 0…...

开发指南061-nexus权限管理

平台后台服务的核心是组件&#xff0c;管理组件的软件有&#xff1a; Apache的Archiva、JFrog的Artifactory、Sonatype的Nexus。 本平台选择nexus。nexus的权限模型是用户-角色-权限体系&#xff1a;通过组合权限定义角色&#xff0c;通过给用户赋角色来赋权限。有关nexus的权…...

Qt 弹出菜单右键菜单 QMenu 设置不同颜色的子项

概述 在Qt中&#xff0c;可以使用样式表&#xff08;StyleSheet&#xff09;来自定义 QMenu 的外观&#xff0c;包括其子项&#xff08;如菜单项QAction&#xff09;的颜色。但是&#xff0c;这通常可以设置 QMenu 的整体样式&#xff0c;而不能单独设置某个子项的颜色。不过&…...

Git换行符自动转换参数core.autocrlf的用法

core.autocrlf 是 Git 中用于控制换行符自动转换的配置选项。它有以下几个可能的值&#xff1a; 1. true 作用&#xff1a;在 checkin 时将 CRLF 转换为 LF&#xff0c;在 checkout 时将 LF 转换为 CRLF。适用场景&#xff1a;适用于 Windows 用户&#xff0c;希望在本地文件…...

C语言的结构体类型

在我们使用C语言进行编写代码时&#xff0c;常常会使用已经给定的类型来创建变量&#xff0c;比如int型&#xff0c;char型&#xff0c;double型等&#xff0c;而当我们想创建一些较为复杂的东西时&#xff0c;单单用一个类型变量是没办法做到的&#xff0c;比如我们想创建一个…...

illustrator 收集字体插件VBscript

这是早些年从俄罗斯网站上看到的一个收集字体插件,语言是用VBscript写的,能用,但个别字体不能收集完成,现在Adobe也在illustrator中加入了收集字体打包功能,所以这个也很少用啦。 使用方法: 下好插件,或把下面的代码存入到本地侯后缀名改为.vbs,然后把.ai文件往.vbs文…...

【LLM多模态】文生视频评测基准VBench

note VBench的16个维度自动化评估指标代码实践&#xff08;待完成&#xff09;16个维度的prompt举例人类偏好标注&#xff1a;计算VBench评估结果与人类偏好之间的相关性、用于DPO微调 文章目录 note一、相关背景二、VBench评测基准概述&#xff1a;论文如何解决这个问题&…...

通过覆写 url_for 将 flask 应用部署到子目录下

0. 缘起 最近用 flask 写了一个 web 应用&#xff0c;需要部署到服务器上。而服务器主域名已经被使用了&#xff0c;只能给主域名加个子目录进行部署&#xff0c;比如主域名 example.org &#xff0c;我需要在 example.org/flask 下部署。这时 flask 应用里的内部连接们就出现…...

攻防世界---->埃尔隆德32

做题笔记。 下载 查壳。 32ida 打开。 发现就一个判断。 跟进看看。 // 首次a20 int __cdecl sub_8048414(_BYTE *a1, int a2) {int result; // eaxswitch ( a2 ){case 0:if ( *a1 105 )goto LABEL_19;result 0;break;case 1:if ( *a1 101 ) // e…...

[特殊字符] 智能合约中的数据是如何在区块链中保持一致的?

&#x1f9e0; 智能合约中的数据是如何在区块链中保持一致的&#xff1f; 为什么所有区块链节点都能得出相同结果&#xff1f;合约调用这么复杂&#xff0c;状态真能保持一致吗&#xff1f;本篇带你从底层视角理解“状态一致性”的真相。 一、智能合约的数据存储在哪里&#xf…...

React 第五十五节 Router 中 useAsyncError的使用详解

前言 useAsyncError 是 React Router v6.4 引入的一个钩子&#xff0c;用于处理异步操作&#xff08;如数据加载&#xff09;中的错误。下面我将详细解释其用途并提供代码示例。 一、useAsyncError 用途 处理异步错误&#xff1a;捕获在 loader 或 action 中发生的异步错误替…...

Prompt Tuning、P-Tuning、Prefix Tuning的区别

一、Prompt Tuning、P-Tuning、Prefix Tuning的区别 1. Prompt Tuning(提示调优) 核心思想:固定预训练模型参数,仅学习额外的连续提示向量(通常是嵌入层的一部分)。实现方式:在输入文本前添加可训练的连续向量(软提示),模型只更新这些提示参数。优势:参数量少(仅提…...

Python:操作 Excel 折叠

💖亲爱的技术爱好者们,热烈欢迎来到 Kant2048 的博客!我是 Thomas Kant,很开心能在CSDN上与你们相遇~💖 本博客的精华专栏: 【自动化测试】 【测试经验】 【人工智能】 【Python】 Python 操作 Excel 系列 读取单元格数据按行写入设置行高和列宽自动调整行高和列宽水平…...

基于uniapp+WebSocket实现聊天对话、消息监听、消息推送、聊天室等功能,多端兼容

基于 ​UniApp + WebSocket​实现多端兼容的实时通讯系统,涵盖WebSocket连接建立、消息收发机制、多端兼容性配置、消息实时监听等功能,适配​微信小程序、H5、Android、iOS等终端 目录 技术选型分析WebSocket协议优势UniApp跨平台特性WebSocket 基础实现连接管理消息收发连接…...

JVM垃圾回收机制全解析

Java虚拟机&#xff08;JVM&#xff09;中的垃圾收集器&#xff08;Garbage Collector&#xff0c;简称GC&#xff09;是用于自动管理内存的机制。它负责识别和清除不再被程序使用的对象&#xff0c;从而释放内存空间&#xff0c;避免内存泄漏和内存溢出等问题。垃圾收集器在Ja…...

转转集团旗下首家二手多品类循环仓店“超级转转”开业

6月9日&#xff0c;国内领先的循环经济企业转转集团旗下首家二手多品类循环仓店“超级转转”正式开业。 转转集团创始人兼CEO黄炜、转转循环时尚发起人朱珠、转转集团COO兼红布林CEO胡伟琨、王府井集团副总裁祝捷等出席了开业剪彩仪式。 据「TMT星球」了解&#xff0c;“超级…...

【Zephyr 系列 10】实战项目:打造一个蓝牙传感器终端 + 网关系统(完整架构与全栈实现)

🧠关键词:Zephyr、BLE、终端、网关、广播、连接、传感器、数据采集、低功耗、系统集成 📌目标读者:希望基于 Zephyr 构建 BLE 系统架构、实现终端与网关协作、具备产品交付能力的开发者 📊篇幅字数:约 5200 字 ✨ 项目总览 在物联网实际项目中,**“终端 + 网关”**是…...

uniapp中使用aixos 报错

问题&#xff1a; 在uniapp中使用aixos&#xff0c;运行后报如下错误&#xff1a; AxiosError: There is no suitable adapter to dispatch the request since : - adapter xhr is not supported by the environment - adapter http is not available in the build 解决方案&…...

蓝桥杯3498 01串的熵

问题描述 对于一个长度为 23333333的 01 串, 如果其信息熵为 11625907.5798&#xff0c; 且 0 出现次数比 1 少, 那么这个 01 串中 0 出现了多少次? #include<iostream> #include<cmath> using namespace std;int n 23333333;int main() {//枚举 0 出现的次数//因…...