c语言的qsort函数理解与使用
介绍:qsort 函数是 C 标准库中用于排序的快速排序算法函数。它的用法非常灵活,可以对任意类型的元素进行排序,只要提供了比较函数即可。
qsort 函数原型及参数解释:
void qsort (
void* base, //指向要排序的数组的首元素的指针
size_t num, //待排序数组中元素的个数
size_t size, //待排序数组中每个元素的大小(以字节为单位)
int (*compare)(const void*,const void*) //比较函数的指针,用于确定元素之间的排序
);
注意:
使用qsort函数时,需要根据实际情况编写一个合适的比较函数来确定排序规则。
比较函数可以根据元素的类型和排序需求进行自定义。
比较函数的原型如下:
int compare(const void *a, const void *b);
比较函数需要返回一个整数值,表示两个元素之间的关系:
如果返回值小于0,则表示a应该排在b之前。
如果返回值等于0,则表示a和b相等,它们的相对顺序不变。
如果返回值大于0,则表示a应该排在b之后。
对于一个数组或是任意需要进行排序的内容进行排序时可以理解如下:
// qsort中自定义比较函数compare返回值 > 0表示对需要排序的内容进行升序排序(小->大)
// qsort中自定义比较函数compare返回值 < 0表示对需要排序的内容进行降序排序(大->小)
实例:
// qsort排序举例:升序排序(小->大)
// 自定义比较函数返回值 > 0表示对需要排序的内容进行升序排序// qsort 函数是 C 标准库中用于排序的快速排序算法函数。
// 它的用法非常灵活,可以对任意类型的元素进行排序,只要提供了比较函数即可。#include <stdio.h>
#include <stdlib.h>// 比较函数的形式为:
// int cmp(const void *a, const void *b);
// 其中,cmp 函数用于比较 a 和 b 两个指针所指向的元素的大小关系,
// 如果 a 指向的元素小于 b 指向的元素,则返回负数;
// 如果 a 指向的元素大于 b 指向的元素,则返回正数;
// 如果 a 指向的元素等于 b 指向的元素,则返回 0。
// 下面我们来看一个最简单的实例代码,用于对整数数组进行排序:
int compare(const void *a, const void *b)
{printf("%d - %d = %d, ", *(int *)a, *(int *)b, (*(int *)a - *(int *)b));return (*(int*)a - *(int*)b);
}int main()
{int arr0[] = {2, 1};int len = sizeof(arr0) / sizeof(int);// 这段代码的核心部分就是使用 qsort 函数对整数数组进行排序,排序时需要传递一个比较函数 cmp。// cmp 函数的实现非常简单,就是计算 a 和 b 之间的差值。最后,我们依次输出排序后的整数数组。// 需要注意的是,在使用 qsort 函数时,我们需要传递以下参数:// 1. 待排序的数组的首地址。// 2. 数组中元素的个数。// 3. 每个元素的大小(以字节为单位)。// 4. 比较函数的地址(即函数指针)。// 这里我们传递的数组是 int 类型的数组,每个元素占据 4 个字节;// 比较函数 cmp 的地址可以直接传递函数名,也可以使用 & 运算符取地址。// 这就是 qsort 函数的基本用法。// 需要注意的是,cmp 函数要保证正确性和稳定性才能得到正确的排序结果,同时在实际使用时,也需要根据具体情况进行参数传递和处理。printf("arr0 升序排序过程:\n");// compare 返回值 > 0表示对数组arr1进行降序排序qsort(arr0, len, sizeof(int), compare);printf("\narr0 after sort:\n");for (int i = 0; i < len; i++) {printf("%d ", arr0[i]);}printf("\n");int arr1[] = {3, 2, 1, 5, -2, 9};int len1 = sizeof(arr1) / sizeof(int);printf("\narr1 升序排序过程:\n");// compare 返回值 > 0表示对数组arr1进行降序排序qsort(arr1, len1, sizeof(int), compare);printf("\narr1 after sort:\n");for (int i = 0; i < len1; i++) {printf("%d ", arr1[i]);}printf("\n");return 0;
}
// qsort排序举例:降序排序(大->小)
#include <stdio.h>
#include <stdlib.h>int cmp0(const void *a, const void *b)
{printf("%d - %d = %d, ", *(int *)a, *(int *)b, (*(int *)a - *(int *)b));return -(*(int*)a - *(int*)b);
}int cmp1(const void *a, const void *b)
{printf("%d - %d = %d, ", *(int *)b, *(int *)a, (*(int *)b - *(int*)a));return (*(int *)b - *(int*)a);
}int main()
{int arr[] = {5, 4, 2, 5, 3, 1};int len = sizeof(arr) / sizeof(int);printf("升序排序过程:\n");// cmp1返回值 < 0表示对数组arr1进行降序排序qsort(arr, len, sizeof(int), cmp0);printf("\nafter sort:\n");for (int i = 0; i < len; i++) {printf("%d ", arr[i]);}printf("\n");// cmp1返回值 < 0表示对数组arr1进行降序排序int arr1[] = {3, 2, 1, 5, -2, 9};printf("降序排序过程:\n");qsort(arr1, len, sizeof(int), cmp1);printf("\nafter sort:\n");for (int i = 0; i < len; i++) {printf("%d ", arr1[i]);}printf("\n");return 0;
}
// 对浮点数进行排序
#include <stdio.h>
#include <stdlib.h>// 对浮点数进行升序排序
int cmpFloat2Ascending(const void *a, const void *b)
{return *(float *)a - *(float *)b;
}// 对浮点数进行降序排序
int cmpFloat2Descending(const void *a, const void *b)
{return -(*(float *)a - *(float *)b);
}int main()
{float arr0[] = { -0.52, 1.7, 20.5, 9.9, 10.22 };int num0 = sizeof(arr0) / sizeof(int);printf("升序排序过程:\n");// cmp1返回值 < 0表示对数组arr1进行降序排序qsort(arr0, num0, sizeof(float), cmpFloat2Ascending);printf("\nafter sort:\n");for (int i = 0; i < num0; i++) {printf("%.2f ", arr0[i]);}printf("\n");// cmp1返回值 < 0表示对数组arr1进行降序排序float arr1[] = {3.3, 5.2, 1.1, 0.5, -1.2, 9.9};int num1 = sizeof(arr0) / sizeof(float);printf("降序排序过程:\n");qsort(arr1, num1, sizeof(float), cmpFloat2Descending);printf("\nafter sort:\n");for (int i = 0; i < num1; i++) {printf("%.2f ", arr1[i]);}printf("\n");return 0;
}
// qsort 函数对结构体类型的数据进行升序和降序排序:
// 这个程序定义了一个 Student 结构体类型,包含了学生的姓名、年龄和考试成绩三个成员变量。
// 在比较函数中,我们先比较考试成绩的大小,如果不同则返回差值;
// 如果考试成绩相同,则比较年龄的大小,如果不同则返回差值;
// 如果年龄也相同,则比较姓名的大小,从而实现了升序和降序排序。
// 在 main 函数中,我们首先定义了一个 Student 类型的数组,用于测试排序结果。
// 然后先调用 qsort 函数实现升序排序,并输出排序后的结果;
// 接着再调用 qsort 函数实现降序排序,并输出排序后的结果。
// 需要注意的是,在实际使用 qsort 函数时,需要根据具体情况进行参数传递和处理,
// 特别是在程序中使用了自定义结构体类型时,需要编写相应的比较函数来实现排序。
// 同时,也需要特别注意比较函数的实现方式,确保能够正确地比较结构体类型的各个成员变量。#include <stdio.h>
#include <stdlib.h>
#include <string.h>typedef struct {char name[20];int age;int score;
} Student;// 升序
int cmpAsc(const void *a, const void *b)
{Student *sa = (Student *)a;Student *sb = (Student *)b;if (sa->score != sb->score) {return sa->score - sb->score;} else if (sa->age != sb->age) {return sa->age - sb->age;} else {return strcmp(sa->name, sb->name);}
}// 降序
int cmpDesc(const void *a, const void *b)
{Student *sa = (Student *)a;Student *sb = (Student *)b;if (sa->score != sb->score) {return -(sa->score - sb->score);} else if (sa->age != sb->age) {return -(sa->age - sb->age);} else {return -strcmp(sa->name, sb->name);}
}int main()
{Student students[] = {{"Alice", 18, 80},{"Bob", 20, 70},{"Charlie", 19, 90},{"David", 18, 80},{"Ella", 20, 85}};int n = sizeof(students) / sizeof(students[0]);// 升序qsort(students, n, sizeof(Student), cmpAsc);printf("Asc:\n");for (int i = 0; i < n; i++) {printf("Name: %s\t Age: %d\t Score: %d\n", students[i].name, students[i].age, students[i].score);}printf("\n");// 降序排序qsort(students, n, sizeof(Student), cmpDesc);printf("Desc:\n");for (int i = 0; i < n; i++) {printf("Name: %s\t Age: %d\t Score: %d\n", students[i].name, students[i].age, students[i].score);}return 0;
}
// 实现一个自定义的模拟qsort函数
// 在这个程序中,我们首先定义了一个 Person 结构体类型,包含名称和年龄两个成员变量。
// 在比较函数中,我们首先比较名称的大小,如果不同则返回名称的差值;
// 如果名称相同,则比较年龄的大小,从而实现了升序和降序排序。
// 在 bubble_sort 函数中,我们使用冒泡排序的逻辑来实现元素的排序,传入的对象是 void 指针,
// 因此我们需要将其强制转换为 char 指针,然后利用 memcpy 函数以元素的大小 width 为单位进行移动。
// 每次比较都使用传入的函数指针 cmp 来比较元素的大小,如果需要交换则使用 memcpy 函数来实现交换。
// 在 main 函数中,我们首先定义了一个 Person 类型的数组,包含了五个元素。
// 我们先对数组进行升序排序打印输出,然后再进行降序排序打印输出。
// 需要注意的是,在输出时使用了结构体的成员变量 name 和 age,分别代表了名称和年龄
#include <stdio.h>
#include <stdlib.h>
#include <string.h>typedef struct {char name[20];int age;
} Person;int cmp_asc(const void *a, const void *b)
{Person *pa = (Person *)a;Person *pb = (Person *)b;if (strcmp(pa->name, pb->name) != 0) {return strcmp(pa->name, pb->name);} else {return pa->age - pb->age;}
}int cmp_desc(const void *a, const void *b)
{Person *pa = (Person *)a;Person *pb = (Person *)b;if (strcmp(pa->name, pb->name) != 0) {return strcmp(pb->name, pa->name);} else {return pb->age - pa->age;}
}void bubble_sort0(void *base, size_t nel, size_t width, int (*cmp)(const void *, const void *))
{char *array = (char *)base;for (int i = 0; i < nel - 1; i++) {for (int j = i + 1; j < nel; j++) {// > 0 表示升序if (cmp(array + i * width, array + j * width) > 0) {char tmp[width];memcpy(tmp, array + j * width, width);memcpy(array + j * width, array + i * width, width);memcpy(array + i * width, tmp, width);}}}
}void bubble_sort1(void *base, size_t nel, size_t width, int (*cmp)(const void *, const void *))
{char *array = (char *)base;for (int i = 0; i < nel - 1; i++) {for (int j = 0; j < nel - i - 1; j++) {// > 0 表示升序if (cmp(array + j * width, array + (j + 1) * width) > 0) {char tmp[width];memcpy(tmp, array + j * width, width);memcpy(array + j * width, array + (j + 1) * width, width);memcpy(array + (j + 1) * width, tmp, width);}}}
}int main()
{Person people[] = {{"Alice", 18},{"Bob", 20},{"Charlie", 19},{"David", 18},{"Ella", 20}};int n = sizeof(people) / sizeof(Person);// 升序排序bubble_sort0(people, n, sizeof(Person), cmp_asc);printf("Asc:\n");for (int i = 0; i < n; i++) {printf("Name: %s\t Age: %d\n", people[i].name, people[i].age);}printf("\n");// 降序排序bubble_sort1(people, n, sizeof(Person), cmp_desc);printf("Desc:\n");for (int i = 0; i < n; i++) {printf("Name: %s\t Age: %d\n", people[i].name, people[i].age);}return 0;
}
// 实现一个自定义的模拟qsort函数
#include <stdio.h>
#include <stdlib.h>
#include <string.h>typedef struct {char name[20];int age;
} Person;int cmp_asc(const void *a, const void *b)
{Person *pa = (Person *)a;Person *pb = (Person *)b;if (strcmp(pa->name, pb->name) != 0) {return strcmp(pa->name, pb->name);} else {return pa->age - pb->age;}
}int cmp_desc(const void *a, const void *b)
{Person *pa = (Person *)a;Person *pb = (Person *)b;if (strcmp(pa->name, pb->name) != 0) {return strcmp(pb->name, pa->name);} else {return pb->age - pa->age;}
}//交换 --一个字节一个字节的交换,共交换width次
void Swap(char* buf1, char* buf2, size_t width)
{size_t i = 0;for (i = 0; i < width; i++){char tmp = *buf1;*buf1 = *buf2;*buf2 = tmp;buf1++;buf2++;}
}
void my_BubbleSort(void* base, size_t num,size_t width, int(*cmp)(const void* e1, const void* e2))
{//冒泡排序//若要排序n个元素,只需要进行n-1趟//每一趟可以少比较一个元素,每一趟可以使一个元素在确定的位置上//num:要排序元素的个数 类型是size_t //num是无符号数 防止产生警告 所以i和j也定义为size_t// size_t == unsigned int size_t i = 0;size_t j = 0;//共进行num-1趟for (i = 0; i < num; i++){//每一趟for (j = 0; j < num - 1 - i; j++){//比较//传地址 //相邻两个元素比较 width:宽度,每个元素所占字节//排成升序if (cmp((char*)base + j * width, (char*)base + (j + 1) * width) > 0){//交换两数Swap( (char*)base + j * width, (char*)base + (j + 1) * width, width );}}}
}int main()
{Person people[] = {{"Alice", 18},{"Bob", 20},{"Charlie", 19},{"David", 18},{"Ella", 20}};int n = sizeof(people) / sizeof(Person);// 升序排序my_BubbleSort(people, n, sizeof(Person), cmp_asc);printf("Asc:\n");for (int i = 0; i < n; i++) {printf("Name: %s\t Age: %d\n", people[i].name, people[i].age);}printf("\n");// 降序排序my_BubbleSort(people, n, sizeof(Person), cmp_desc);printf("Desc:\n");for (int i = 0; i < n; i++) {printf("Name: %s\t Age: %d\n", people[i].name, people[i].age);}return 0;
}
使用qsort对字符串数组进行排序:
// 使用qsort函数来对字符串数组进行升序和降序排序#include <stdio.h>
#include <stdlib.h>
#include <string.h>#define MAX_STR_NUM 10
#define MAX_STR_LEN 20int cmpAsc(const void *a, const void *b)
{char **pa = (char **)a;char **pb = (char **)b;return strcmp(*pa, *pb);
}int cmpDesc(const void *a, const void *b)
{char **pa = (char **)a;char **pb = (char **)b;return -strcmp(*pa, *pb);return strcmp(*pb, *pa);
}int main()
{int n = 3;int i = 0;char **strs = (char **)malloc(n * sizeof(char *));char *str0 = (char *)malloc(100);for (i = 0; i < 3; ++i) {strs[i] = (char *)malloc(100);}snprintf(strs[0], 100, "ff str0\n");snprintf(strs[1], 100, "dd str1\n");snprintf(strs[2], 100, "aa str2\n");// 升序排序qsort(strs, n, sizeof(char *), cmpAsc);printf("\nAsc: \n");for(int i = 0; i < n; i++) {printf("%s", strs[i]);}printf("\n");// 降序排序qsort(strs, n, sizeof(char *), cmpDesc);printf("\nDesc: \n");for(int i = 0; i < n; i++) {printf("%s", strs[i]);}printf("\n");return 0;
}
// 使用qsort函数对字符串数组进行排序#include <stdio.h>
#include <stdlib.h>
#include <string.h>// 在实际使用时,比较函数的参数应该根据实际情况转换为正确的指针类型。
// 在字符串数组中,每个元素都是指向一个字符串的指针,
// 因此需要将`const void *`类型的指针转换为`char **`类型的指针,即指向指针的指针,然后才能解引用该指针,
// 即使用`*(char **)a`,获取指向的字符串。
// 如果使用`(char *)a`进行强制类型转换,`char *`类型的指针是单层指针,而不是指针的指针。
// 这将导致在解引用该指针时不能得到正确的字符串指针,从而产生错误的答案。
// 因此,在使用指针数组中的字符串进行排序时,
// 必须使用`char **`类型的指针进行指针转换,再解引用该指针获取到正确的字符串指针进行比较,才能保证排序的正确性。
// a和b的值是strs的元素的地址,也就是指针的指针,所以void其实是char*,void*就是char**
// strs的每个元素都是一个指针,每个元素的地址就应该用指针的指针来存储
// 所以a和b就是指针的指针,所以void*就是char**,void想当于char*
int cmp(const void *a, const void *b)
{printf("a : %p, b : %p\n", a, b);char *tmpa = (char *)a;char *tmpb = (char *)b;char **tmpaa = (char **)a;char **tmpbb = (char **)b;printf("*tmpa: %s, **tmpaa:%s\n", tmpa, *tmpaa);printf("tmpa: %p, tmpb: %p, tmpaa: %p, tmpbb: %p\n",tmpa, tmpb, tmpaa, tmpbb);// 调试后发现:// a存放的是strs[0]的地址(char**类型)b存放的是strs[1]的地址(char**类型) // strcmp()会将p地址对应的内容转化成字符串,也就是将strs[0~2]的地址转化成字符串,将得到一个乱码// 因为将(char **类型的数据转换成了char *类型的数据,这样解引用出来的字符串当然是错误的// 因此得先把a,b转化成char**,这样解引用以后才是一个char*的地址// return strcmp(tmpa, tmpb);// return strcmp(*tmpaa, *tmpbb);// 用指针的方式进行排序return strcmp(*(char **)a, *(char **)b);// 不能将二级指针直接解引用,这样借用用后的值为1个一级指针,而不是一个字符串,// 因此需要转换成char **类型后在进行解引用操作// return strcmp((char *)a, (char *)b);
}int main()
{int n = 3;int i = 0;char **strs = (char **)malloc(n * sizeof(char *));char *str0 = (char *)malloc(100);for (i = 0; i < 3; ++i) {strs[i] = (char *)malloc(100);}printf("strs: %p, *strs: %p, strs[0]: %p, strs[1]: %p, strs[2]: %p\n",strs, *strs, strs[0], strs[1], strs[2]);printf("strs: %p, &strs[0]: %p, &strs[1]: %p, &strs[2]: %p\n",strs, &strs[0], &strs[1], &strs[2]);snprintf(strs[0], 100, "ff str0\n");snprintf(strs[1], 100, "dd str1\n");snprintf(strs[2], 100, "aa str2\n");printf("\nbefore sort:\n");for (i = 0; i < n; ++i) {printf("%s", strs[i]);}// 传入的参数为strs[0~2],即指针的指针qsort(strs, n, sizeof(char *), cmp);printf("\nafter sort:\n");for (i = 0; i < n; ++i) {printf("%s", strs[i]);}printf("\n");for (i = 0; i < n; ++i) {free(strs[i]);}free(strs);return 0;
}
通过以上代码可以活得一个经验,在进行字符串数组比时较需要注意如下问题:
不能在自定义的数据比较函数中return strcmp((char *)a, (char *)b);
而是应该return strcmp(*(char **)a, *(char **)b);


strs是一个指针数组,保存3个指针,也就是说&strs[0], &strs[1], &strs[2]都是二级指针,
地址分别为
0x555555757260
0x555555757268
0x555555757270
这3个二级指针分别各自保存1个一级指针,分别为strs[0], strs[1], strs[2]
指针的地址和保存的字串分别为:
0x5555557572f0 "ff str0\n"
0x555555757360 "dd str1\n"
0x5555557573d0 "aa str2\n"
而传入到cmp函数中的指针为二级指针&strs[0], &strs[1], &strs[2]
(用void *类型作为形参类型,并于不同类型数据的转换),
二级指针保存一级指针的地址对应关系为:
&strs[0]: 0x555555757260 -> strs[0]:0x5555557572f0 "ff str0\n"
&strs[1]: 0x555555757268-> strs[0]:0x555555757360 "dd str1\n"
&strs[2]: 0x555555757270-> strs[0]:0x5555557573d0 "aa str2\n"
若将传入的二级指针转换成char *类型,则接应用时去除的字符串是一个乱码,
因为二级指针保存的值为1个一级指针,所以接应用后的值仍然是一个一级指针,
而这个一级指针指向的内容才是需要获取的字符串。
相关文章:
c语言的qsort函数理解与使用
介绍:qsort 函数是 C 标准库中用于排序的快速排序算法函数。它的用法非常灵活,可以对任意类型的元素进行排序,只要提供了比较函数即可。 qsort 函数原型及参数解释: void qsort ( void* base, //指向要排序的数组的首元素…...
Java 语言的起源发展与基本概念(JDK,JRE,JVM)
Java语言的起源 源起 Java语言最初是由Sun Microsystems公司(该公司于2009年被Oracle公司收购)开发的一种编程语言。其创造者是詹姆斯高斯林(James Gosling),他是一位加拿大计算机科学家。其前身名为Oak(橡…...
03_变量
变量 var num 10; 变量的重新赋值 var num10; num 20; 变量提升 JavaScript 引擎的工作方式是,先解析代码,获取所有被声明的变量,然后再一行一行地运行。这造成的结果,就是所有的变量的声明语句,都会被提升到代码的…...
[论文阅读-综述]Supervised Speech Separation Based on Deep Learning: An Overview
基于深度学习的监督语音分离:综述 出版:IEEE 核心:使用语音分离将目标语音信号与噪声混合分离的计算 本文用于对该文章的学习,主要是对内容的理解翻译与笔记 1. 语音分离介绍 语音分离的目标:将目标语音与背景干扰分…...
群控系统服务端开发模式-应用开发-邮箱配置功能开发
邮箱配置主要是将管理员数据做归属。具体见下图: 一、创建表 1、语句 CREATE TABLE cluster_control.nc_param_mail (id int(11) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 编号,title varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT…...
【机器学习】——卷积与循环的交响曲:神经网络模型在现代科技中的协奏
🎼个人主页:【Y小夜】 😎作者简介:一位双非学校的大二学生,编程爱好者, 专注于基础和实战分享,欢迎私信咨询! 🎆入门专栏:🎇【MySQL࿰…...
android studio引用so库
在工程中编译好的so库文件将在原始编译工程对应目录下:build/intermediates/cxx/Debug/xxxxxx/obj/ 其目录结构如上所示,包含生成的四个版本,每个文件夹下均包含c/c源码编译成的Android版本的libnavi.so库和提供应用接口的libnavi-lib.so库。…...
2024年信号处理与神经网络应用(SPNNA 2024)
会议官网:www.spnna.org 会议时间:2024年12月13-15日 会议地点:中国武汉...
wxWidgets-ImageView
wxWidgets实现图片浏览、放大缩小、另存为新的图片格式等 #include "wx/wxprec.h"#ifndef WX_PRECOMP#include "wx/wx.h" #endif#include "wx/filename.h" #include "wx/zstream.h"#include "imageviewctrl.h"class MyFrame…...
第1章-JVM和Java体系架构
虚拟机 虚拟机概念 所谓虚拟机(Virtual Machine),就是一台虚拟的计算机。它是一款软件,用来执行一系列虚拟计算机指令。大体上,虚拟机可以分为系统虚拟机和程序虚拟机。 大名鼎鼎的Virtual Box,VMware就属…...
windows 服务器角色
windows 服务器角色 Active Directory Rights Management Services Active Directory RightsManagement Services (AD RS)帮助保护信息,防止未授权使用。AD RMS 将建立用户标识,并为授权用户提供受保护信息的许可证。 ServicesActive Directory 联合身…...
[OpenHarmony5.0][Docker][环境]OpenHarmony5.0 Docker编译环境镜像下载以及使用方式
T. 已测试目录 主机类型主机版本Docker镜像版本结果WSL2Ubuntu22.04Ubuntu20.04PASSWSL2Ubuntu22.04Ubuntu18.04PASS R. 软硬件要求: 编译硬件需求:做多系统测试,磁盘500GB起步(固态)(机械会卡死),内存3…...
C#中判断两个 List<T> 的内容是否相等
ET实现游戏中邮件系统逻辑思路(服务端)_游戏邮件系统设计-CSDN博客 场景:今天遇到一个BUG,在服务器重启的时候(体验服),玩家之前接收的邮件又重新接收了一次,但是两封邮件的ID是不同…...
Linux环境下配置neo4j图数据库
1.下载安装包 openjdk-11.0.1_linux-x64_bin.tar.gz neo4j-community-4.2.19-unix.tar.gz 2.之前配置好的配置文件 neo4j.conf 3.安装 3.1-jdk11的安装(jdk1.8不够用) 解压缩 tar -zxvf openjdk-11.0.1_linux-x64_bin.tar.gz修改系统环境变量 打开pro…...
Windows 11 搭建 Docker 桌面版详细教程
在当今的软件开发与部署领域,Docker 已成为一项极为重要的容器化技术。它能够让开发者轻松地打包应用及其依赖项,实现跨环境的一致性运行,大大提高了开发效率与部署的便捷性。本教程将详细介绍在 Windows 11 操作系统上搭建 Docker 桌面版的具…...
Pytest-Bdd-Playwright 系列教程(13):钩子(hooks)
Pytest-Bdd-Playwright 系列教程(13):钩子(hooks) 前言一、什么是钩子?二、Pytest-Bdd 提供的钩子一览三、钩子用法详解1. pytest_bdd_before_scenario2. pytest_bdd_after_scenario3. pytest_bdd_before_s…...
dns 服务器简单介绍
dns 服务器分类: 根域名服务器顶级域名服务器权威域名服务器本地域名服务器 dns 的查询过程 国内优秀公共域名 腾讯:DNSPod-免费智能DNS解析服务商-电信_网通_教育网,智能DNS-烟台帝思普网络科技有限公司 119.29.29.29 和 182.254.118.118 阿里…...
Neo4j图形数据库-Cypher中常用指令
一、创建与修改 1.1 create 创建图数据库中的节点、关系等元素: CREATE (:Person {name: "Alice", age: 30}) CREATE (p1:Person {name: "Bob"})-[r:KNOWS]->(p2:Person {name: "Charlie"})批量创建元素 CREATE (n1:Node),(n2…...
linux安全管理-防火墙配置
1. 开启系统防火墙 1、检查内容 检查操作系统是否开启防火墙; 2、配置要求 操作系统开启防火墙; 3、配置方法 systemctl status firewalld ##查看系统防火墙运行状态 systemctl start firewalld ##启动防火墙 systemctl restart firewalld ##重启防火墙…...
什么是BIOS
BIOS(Basic Input/Output System,基本输入输出系统)是计算机启动过程中的一个关键组件,主要负责硬件的初始化和系统的引导。以下是关于 BIOS 的一些详细信息: 1. 基本功能 硬件初始化:当计算机启动时&…...
模型参数、模型存储精度、参数与显存
模型参数量衡量单位 M:百万(Million) B:十亿(Billion) 1 B 1000 M 1B 1000M 1B1000M 参数存储精度 模型参数是固定的,但是一个参数所表示多少字节不一定,需要看这个参数以什么…...
Spring Boot 实现流式响应(兼容 2.7.x)
在实际开发中,我们可能会遇到一些流式数据处理的场景,比如接收来自上游接口的 Server-Sent Events(SSE) 或 流式 JSON 内容,并将其原样中转给前端页面或客户端。这种情况下,传统的 RestTemplate 缓存机制会…...
MySQL 隔离级别:脏读、幻读及不可重复读的原理与示例
一、MySQL 隔离级别 MySQL 提供了四种隔离级别,用于控制事务之间的并发访问以及数据的可见性,不同隔离级别对脏读、幻读、不可重复读这几种并发数据问题有着不同的处理方式,具体如下: 隔离级别脏读不可重复读幻读性能特点及锁机制读未提交(READ UNCOMMITTED)允许出现允许…...
安宝特方案丨XRSOP人员作业标准化管理平台:AR智慧点检验收套件
在选煤厂、化工厂、钢铁厂等过程生产型企业,其生产设备的运行效率和非计划停机对工业制造效益有较大影响。 随着企业自动化和智能化建设的推进,需提前预防假检、错检、漏检,推动智慧生产运维系统数据的流动和现场赋能应用。同时,…...
汽车生产虚拟实训中的技能提升与生产优化
在制造业蓬勃发展的大背景下,虚拟教学实训宛如一颗璀璨的新星,正发挥着不可或缺且日益凸显的关键作用,源源不断地为企业的稳健前行与创新发展注入磅礴强大的动力。就以汽车制造企业这一极具代表性的行业主体为例,汽车生产线上各类…...
Mac软件卸载指南,简单易懂!
刚和Adobe分手,它却总在Library里给你写"回忆录"?卸载的Final Cut Pro像电子幽灵般阴魂不散?总是会有残留文件,别慌!这份Mac软件卸载指南,将用最硬核的方式教你"数字分手术"࿰…...
全面解析各类VPN技术:GRE、IPsec、L2TP、SSL与MPLS VPN对比
目录 引言 VPN技术概述 GRE VPN 3.1 GRE封装结构 3.2 GRE的应用场景 GRE over IPsec 4.1 GRE over IPsec封装结构 4.2 为什么使用GRE over IPsec? IPsec VPN 5.1 IPsec传输模式(Transport Mode) 5.2 IPsec隧道模式(Tunne…...
鸿蒙DevEco Studio HarmonyOS 5跑酷小游戏实现指南
1. 项目概述 本跑酷小游戏基于鸿蒙HarmonyOS 5开发,使用DevEco Studio作为开发工具,采用Java语言实现,包含角色控制、障碍物生成和分数计算系统。 2. 项目结构 /src/main/java/com/example/runner/├── MainAbilitySlice.java // 主界…...
服务器--宝塔命令
一、宝塔面板安装命令 ⚠️ 必须使用 root 用户 或 sudo 权限执行! sudo su - 1. CentOS 系统: yum install -y wget && wget -O install.sh http://download.bt.cn/install/install_6.0.sh && sh install.sh2. Ubuntu / Debian 系统…...
省略号和可变参数模板
本文主要介绍如何展开可变参数的参数包 1.C语言的va_list展开可变参数 #include <iostream> #include <cstdarg>void printNumbers(int count, ...) {// 声明va_list类型的变量va_list args;// 使用va_start将可变参数写入变量argsva_start(args, count);for (in…...
