数据结构之排序专题 —— 快速排序原理以及改进方法(添加随机,三路快排)

news2024/11/27 6:11:37

内容概述

尽管此类博客已经非常非常多,而且也有很多写得很好,但还是想记录一下,用最容易理解的方式,并且多补充了一些例子。

整理云盘的时候发现大一时候的笔记,用的是 txt 文本文件记录的,格式之丑陋可想而知。周六有时间便整理了一下,多少有点怀念那段时光,特记录于此。

快速排序基础核心版

一句话概述:快速排序是一种基于分治策略的排序算法,通过选择一个基准元素将数组分为两个子数组,并递归地对子数组进行排序,最终实现整个数组的排序。

先看例子,再去理解原理

“一句话概述” 中提到选一个基准元素,我们记作 key,接下来的每次排序都会基于 key 而展开,并且根据 key 划分为两个子数组,大于等于 key 的为一组,小于 key 的为一组。

例子1: {3, 5, 1, 6, 2, 9, 5, 7, 8}

开始排序前:     3 5 1 6 2 9 5 7 8 
第1次排序 key = 3       排序前  3 5 1 6 2 9 5 7 8 排序后: 2 1 3 6 5 9 5 7 8 
第2次排序 key = 2       排序前  2 1               排序后: 1 2 
第3次排序 key = 6       排序前  6 5 9 5 7 8       排序后: 5 5 6 9 7 8 
第4次排序 key = 5       排序前  5 5               排序后: 5 5 
第5次排序 key = 9       排序前  9 7 8             排序后: 8 7 9 
第6次排序 key = 8       排序前  8 7               排序后: 7 8 
排序完成后:     1 2 3 5 5 6 7 8 9 

例子2: {4, 4, 1, 1, 2, 2, 3, 3, 5}

开始排序前:     4 4 1 1 2 2 3 3 5 
第1次排序 key = 4       排序前  4 4 1 1 2 2 3 3 5 排序后: 3 4 1 1 2 2 3 4 5 
第2次排序 key = 3       排序前  3 4 1 1 2 2 3     排序后: 2 2 1 1 3 4 3 
第3次排序 key = 2       排序前  2 2 1 1           排序后: 1 2 1 2 
第4次排序 key = 1       排序前  1 2 1             排序后: 1 2 1 
第5次排序 key = 2       排序前  2 1               排序后: 1 2 
第6次排序 key = 4       排序前  4 3               排序后: 3 4 
排序完成后:     1 1 2 2 3 3 4 4 5 

例子3: {1, 2, 3, 4, 5, 6, 7, 8, 1}

开始排序前:     1 2 3 4 5 6 7 8 1 
第1次排序 key = 1       排序前  1 2 3 4 5 6 7 8 1 排序后: 1 2 3 4 5 6 7 8 1 
第2次排序 key = 2       排序前  2 3 4 5 6 7 8 1   排序后: 1 2 4 5 6 7 8 3 
第3次排序 key = 4       排序前  4 5 6 7 8 3       排序后: 3 4 6 7 8 5 
第4次排序 key = 6       排序前  6 7 8 5           排序后: 5 6 8 7 
第5次排序 key = 8       排序前  8 7               排序后: 7 8 
排序完成后:     1 1 2 3 4 5 6 7 8 

基本原理介绍

一句话概述:快速排序是一种基于分治策略的排序算法,通过选择一个基准元素将数组分为两个子数组,并递归地对子数组进行排序,最终实现整个数组的排序。

在这里插入图片描述
在这里插入图片描述

代码实现 1 —— 不带打印中间结果

#include <iostream>
#include <algorithm>
#include <cstdlib>
using namespace std;


/**
 * 根据 nums[low] 作为参考,将数组划分为两组
 * @param nums 原数组
 * @param low 需要排序的子数组的索引开始
 * @param high 需要排序的子数组的索引结束
 * @return low 或者 high 因为二者相等,以后将会根据这个索引将原数组分为两个子数组
 */
int partition(vector<int>& nums, int low, int high) {
    int key = nums[low];
    while (low < high) {
        // 如果 nums[high] 一直大于等于 key,左移
        while (low < high && nums[high] >= key) {
            high--;
        }
        // 遇到了不符合条件的,交换
        swap(nums[low], nums[high]);
        while (low < high && nums[low] <= key) {
            low++;
        }
        swap(nums[low], nums[high]);
    }
    return low;
}

/**
 * 快速排序
 * @param nums 待排序的数组
 * @param low 待排序的数组的开始索引
 * @param high 待排序的数组的结束索引
 */
void quickSort(vector<int>& nums, int low, int high) {
    if (low < high) {
        int key = partition(nums, low, high);
        quickSort(nums, low, key - 1);
        quickSort(nums, key + 1, high);
    }
}

/**
 * 快速排序
 * @param nums 待排序的数组
 */
void quickSort(vector<int>& nums) {
    quickSort(nums, 0, nums.size() - 1);
}

int main() {
    vector<int> nums = {3, 5, 1, 6, 2, 9, 5, 7, 8};
    quickSort(nums);
    for (auto num : nums) {
        cout<<num<<" ";
    }
    cout<<endl;
    return 0;
}

代码实现 2 —— 打印中间结果

#include <iostream>
#include <algorithm>
#include <cstdlib>
using namespace std;

// 用来记录排序的序号
int sortNum = 1;

/**
 * 打印数组当前状态
 * @param nums 数组
 */
void printNums(vector<int> nums, int low, int high) {
    for (int i = low; i <= high; i++) {
        cout<<nums[i]<<" ";
    }
}

/**
 * 根据 nums[low] 作为参考,将数组划分为两组
 * @param nums 原数组
 * @param low 需要排序的子数组的索引开始
 * @param high 需要排序的子数组的索引结束
 * @return low 或者 high 因为二者相等,以后将会根据这个索引将原数组分为两个子数组
 */
int partition(vector<int>& nums, int low, int high) {
    int start = low, end = high;
    int key = nums[low];
    cout<<"第"<<sortNum++<<"次排序 key = "<<key<<"\t排序前\t";
    printNums(nums, start, end);
    while (low < high) {
        // 如果 nums[high] 一直大于等于 key,左移
        while (low < high && nums[high] >= key) {
            high--;
        }
        // 遇到了不符合条件的,交换
        swap(nums[low], nums[high]);
        while (low < high && nums[low] <= key) {
            low++;
        }
        swap(nums[low], nums[high]);
    }
    cout<<"\t\t排序后:\t";
    printNums(nums, start, end);
    cout<<endl;
    return low;
}

/**
 * 快速排序
 * @param nums 待排序的数组
 * @param low 待排序的数组的开始索引
 * @param high 待排序的数组的结束索引
 */
void quickSort(vector<int>& nums, int low, int high) {
    if (low < high) {
        int key = partition(nums, low, high);
        quickSort(nums, low, key - 1);
        quickSort(nums, key + 1, high);
    }
}

/**
 * 快速排序
 * @param nums 待排序的数组
 */
void quickSort(vector<int>& nums) {
    quickSort(nums, 0, nums.size() - 1);
}

int main() {
    vector<int> nums = {3, 5, 1, 6, 2, 9, 5, 7, 8};
    cout<<"开始排序前:\t";
    printNums(nums, 0, nums.size() - 1);
    cout<<endl;
    quickSort(nums);
    cout<<"排序完成后:\t";
    printNums(nums, 0, nums.size() - 1);

    return 0;
}
#include <iostream>
#include <algorithm>
#include <cstdlib>
using namespace std;

// 用来记录排序的序号
int sortNum = 1;

/**
 * 打印数组当前状态
 * @param nums 数组
 */
void printNums(vector<int> nums) {
    for (auto num : nums) {
        cout<<num<<" ";
    }
}

/**
 * 根据 nums[low] 作为参考,将数组划分为两组
 * @param nums 原数组
 * @param low 需要排序的子数组的索引开始
 * @param high 需要排序的子数组的索引结束
 * @return low 或者 high 因为二者相等,以后将会根据这个索引将原数组分为两个子数组
 */
int partition(vector<int>& nums, int low, int high) {
    int key = nums[low];
    while (low < high) {
        // 如果 nums[high] 一直大于等于 key,左移
        while (low < high && nums[high] >= key) {
            high--;
        }
        // 遇到了不符合条件的,交换
        swap(nums[high], nums[low]);
        while (low < high && nums[low] <= key) {
            low++;
        }
        swap(nums[low], nums[high]);
    }
    cout<<"第"<<sortNum++<<"次排序后:\t";
    printNums(nums);
    cout<<"\t本次排序的key为"<<key<<endl;
    return low;
}

/**
 * 快速排序
 * @param nums 待排序的数组
 * @param low 待排序的数组的开始索引
 * @param high 待排序的数组的结束索引
 */
void quickSort(vector<int>& nums, int low, int high) {
    if (low < high) {
        int key = partition(nums, low, high);
        quickSort(nums, low, key - 1);
        quickSort(nums, key + 1, high);
    }
}

/**
 * 快速排序
 * @param nums 待排序的数组
 */
void quickSort(vector<int>& nums) {
    quickSort(nums, 0, nums.size() - 1);
}

int main() {
    vector<int> nums = {3, 5, 1, 6, 2, 9, 5, 7, 8};
    cout<<"开始排序前:\t";
    printNums(nums);
    cout<<endl;
    quickSort(nums);
    return 0;
}

最终输出结果为:

开始排序前:     3 5 1 6 2 9 5 7 8 
第1次排序 key = 3       排序前  3 5 1 6 2 9 5 7 8 排序后: 2 1 3 6 5 9 5 7 8 
第2次排序 key = 2       排序前  2 1               排序后: 1 2 
第3次排序 key = 6       排序前  6 5 9 5 7 8       排序后: 5 5 6 9 7 8 
第4次排序 key = 5       排序前  5 5               排序后: 5 5 
第5次排序 key = 9       排序前  9 7 8             排序后: 8 7 9 
第6次排序 key = 8       排序前  8 7               排序后: 7 8 
排序完成后:     1 2 3 5 5 6 7 8 9 

添加随机选择 key

因为每次排序从待排序的数组中 low 选取很有可能影响性能,可能出现每次都选择数组中的 “第二大值” 或 “第二小值” 等等,而我们期望的是每次都能选中间值,分而治之的效率才最高。

这里我们添加随机选择 key 的方法来达到这个目的。就是在之前的基础上增加两行代码如下

int index = rand() % (high - low) + low;
swap(nums[index], nums[low]);

全部代码如下:

#include <iostream>
#include <algorithm>
#include <cstdlib>
using namespace std;


/**
 * 根据 nums[low] 作为参考,将数组划分为两组
 * @param nums 原数组
 * @param low 需要排序的子数组的索引开始
 * @param high 需要排序的子数组的索引结束
 * @return low 或者 high 因为二者相等,以后将会根据这个索引将原数组分为两个子数组
 */
int partition(vector<int>& nums, int low, int high) {
    int index = rand() % (high - low) + low;
    swap(nums[index], nums[low]);
    int key = nums[low];
    while (low < high) {
        // 如果 nums[high] 一直大于等于 key,左移
        while (low < high && nums[high] >= key) {
            high--;
        }
        // 遇到了不符合条件的,交换
        swap(nums[low], nums[high]);
        while (low < high && nums[low] <= key) {
            low++;
        }
        swap(nums[low], nums[high]);
    }
    return low;
}

/**
 * 快速排序
 * @param nums 待排序的数组
 * @param low 待排序的数组的开始索引
 * @param high 待排序的数组的结束索引
 */
void quickSort(vector<int>& nums, int low, int high) {
    if (low < high) {
        int key = partition(nums, low, high);
        quickSort(nums, low, key - 1);
        quickSort(nums, key + 1, high);
    }
}

/**
 * 快速排序
 * @param nums 待排序的数组
 */
void quickSort(vector<int>& nums) {
    quickSort(nums, 0, nums.size() - 1);
}

int main() {
    vector<int> nums = {3, 5, 1, 6, 2, 9, 5, 7, 8};
    quickSort(nums);
    for (auto num : nums) {
        cout<<num<<" ";
    }
    cout<<endl;
    return 0;
}

三路快排

三路快排其实也很简单,前面提到的快排每次排序根据 key 将数组划分为 大于等于 key 的和小于 key 的,三路快排的思路就是将 等于 key 的单独处理一下,不再和前面提到的合到了 “大于等于” 这一类中。

那如何实现这个效果呢 ?

基本思路为:除了 low 与 high,添加第3个指针 mid,mid 与 low 同时出发一起去寻找 high,并且 mid 走得更快 —— nums[low] < key 时二者都走,nums[low] == key 时只有 mid 往前走,当 mid 找到 high 时停止本次循环。

这个地方不做PPT详细描述了,跟前面的方法基本是一致的,改进的地方即前面提到的 “基本思路”。

#include <iostream>
#include <algorithm>
#include <cstdlib>
using namespace std;


/**
 * 根据 nums[low] 作为参考,将数组划分为两组
 * @param nums 原数组
 * @param low 需要排序的子数组的索引开始
 * @param high 需要排序的子数组的索引结束
 * @return low 或者 high 因为二者相等,以后将会根据这个索引将原数组分为两个子数组
 */
pair<int,int> partition(vector<int>& nums, int low, int high) {
    int index = rand() % (high - low) + low;
    swap(nums[index], nums[low]);
    // 作为比较的对象,接下根据大小关系把数组分为三类
    int key = nums[low];
    // 记录一下开始的位置,最后需要用到
    int start = low;
    // mid 指针走的比 low 快,会更快找到 high 然后停止
    int mid = low + 1;
    // 注意这里的停止条件是 mid 找到 high
    while (mid <= high) {
        // 如果 nums[mid] 小于 key,就放到左边 的 low + 1 的位置
        if (nums[mid] < key) {
            swap(nums[++low], nums[mid++]);
        } else if (nums[mid] > key) {
            // 如果大于 key 的话这里和两路排序没有区别,但是之前的low换成了现在的mid,注意mid指针不需要移动
            swap(nums[mid], nums[high--]);
        } else {
            // 如果相等的话,那么只需要移动mid指针,因为其他的两端已经基本有序,本地的移动跟它们没有关系
            mid++;
        }
    }
    // 最后一定要把最开始选择的 key 移动中间去,换完成后
    swap(nums[start], nums[low]);
    return {low, high};
}

/**
 * 快速排序
 * @param nums 待排序的数组
 * @param low 待排序的数组的开始索引
 * @param high 待排序的数组的结束索引
 */
void quickSort(vector<int>& nums, int low, int high) {
    if (low < high) {
        pair<int, int> part = partition(nums, low, high);
        quickSort(nums, low, part.first - 1);
        quickSort(nums, part.second + 1, high);
    }
}

/**
 * 快速排序
 * @param nums 待排序的数组
 */
void quickSort(vector<int>& nums) {
    quickSort(nums, 0, nums.size() - 1);
}

int main() {
    vector<int> nums = {3, 5, 1, 6, 2, 9, 5, 7, 8};
    quickSort(nums);
    for (auto num : nums) {
        cout<<num<<" ";
    }
    cout<<endl;
    return 0;
}

这里补充几个例子:

例子1:{5, 1, 5, 6, 5, 9, 5, 7, 8}

本例子比较特殊,因为第一个元素就是我们期望的,也就是数组中出现次数最多的,本次排序只需要4次。如果我们将前两个元素的位置调换,结果就有些不一样了(参看例子2)。

开始排序前:     5 1 5 6 5 9 5 7 8 
第1次排序:     1 5 5 5 5 9 7 8 6        key = 5        low = 1 high=4
第2次排序:     6 7 8 9          key = 9        low = 8 high=8
第3次排序:     6 8 7    key = 6        low = 5 high=5
第4次排序:     7 8      key = 8        low = 7 high=7
排序完成后:     1 5 5 5 5 6 7 8 9 

例子2:{1, 5, 5, 6, 5, 9, 5, 7, 8};

由于第一个key不是出现次数最多的5,所以第一次排序后只是单纯地确定了 1 的位置。

开始排序前:     1 5 5 6 5 9 5 7 8 
第1次排序:     1 5 6 5 9 5 7 8 5        key = 1        low = 0 high=0
第2次排序:     5 5 5 5 7 8 9 6          key = 5        low = 1 high=4
第3次排序:     6 7 9 8                  key = 7        low = 6 high=6
第4次排序:     8 9                      key = 9        low = 8 high=8
排序完成后:     1 5 5 5 5 6 7 8 9 

例子3:{7, 5, 5, 6, 5, 9, 5, 7, 8}

这个例子不同之处在于出现重复的不只是 5 了,还有 7 也重复过两次,所以排序更快(3次)。

开始排序前:     7 5 5 6 5 9 5 7 8 
第1次排序:     5 5 5 6 5 7 7 8 9        key = 7        low = 5 high=6
第2次排序:     5 5 5 5 6                key = 5        low = 0 high=3
第3次排序:     8 9                      key = 8        low = 7 high=7
排序完成后:     5 5 5 5 6 7 7 8 9 

例子4:{7, 5, 5, 5, 5, 5, 5, 5, 5}

开始排序前:     7 5 5 5 5 5 5 5 5 
第1次排序:     5 5 5 5 5 5 5 5 7        key = 7        low = 8 high=8
第2次排序:     5 5 5 5 5 5 5 5          key = 5        low = 0 high=7
排序完成后:     5 5 5 5 5 5 5 5 7 

例子5:{5, 7, 5, 5, 5, 5, 5, 5, 5}

开始排序前:     5 7 5 5 5 5 5 5 5 
第1次排序:     5 5 5 5 5 5 5 5 7        key = 5        low = 0 high=7
排序完成后:     5 5 5 5 5 5 5 5 7 

例子6:{5, 5, 5, 5, 5, 5, 5, 5, 5}

开始排序前:     5 5 5 5 5 5 5 5 5 
第1次排序:     5 5 5 5 5 5 5 5 5        key = 5        low = 0 high=8
排序完成后:     5 5 5 5 5 5 5 5 5 

例子6:{3, 1, 2, 4, 2, 2, 2, 1, 5}

开始排序前:     3 1 2 4 2 2 2 1 5 
第1次排序:     2 1 2 1 2 2 3 5 4        key = 3        low = 6 high=6
第2次排序:     1 1 2 2 2 2              key = 2        low = 2 high=5
第3次排序:     1 1                      key = 1        low = 0 high=1
第4次排序:     4 5                      key = 5        low = 8 high=8
排序完成后:     1 1 2 2 2 2 3 4 5 

总结

回想一下当初学习排序算法的时候,最头疼的地方应该在于那段 “似懂非懂” 的状态,能够看懂例子,大致能够明白基本原理,但是别说写源码实现算法,就连读懂源码都比较困难,因为很多源码注释太少了,看起来很舒服但对初学者非常不友好。

所以这里决定放弃代码的美观而决定写很多注释的方式,记录一下当初遇到的困难。并且给出例子,记录每次排序的基本过程。因为快排分而治之的思想理解容易但应用起来却不那么直观了,所以可以考虑把各个过程打印出来,给自己分析,也方便别人理解。

历史是个轮回不一定成立,但学习应该是这样的。古人诚不欺我,温故而知新。

Smileyan
2023.05.27 23:41

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

SAP-MM-采购申请审批那些事!

1、ME55不能审批删除行项目的PR 采购申请审批可以设置行项目审批或抬头审批。如果设置为抬头审批时&#xff0c;ME55集中审批时&#xff0c;就会发现有些采购申请时不能审批的&#xff0c; 那么这些采购申请时真的不需要审批么&#xff1f;不是的&#xff0c;经过核对这些采购申…

solr快速上手:managed-schema标签详解(三)

0. 引言 core核心是solr中的重中之重&#xff0c;类似数据库中的表&#xff0c;在搜索引擎中也叫做索引&#xff0c;在solr中索引的建立&#xff0c;要先创建基础的数据结构&#xff0c;即schema的相关配置&#xff0c;今天继续来学习solr的核心知识&#xff1a; solr快速上手…

chatgpt赋能python:Python绑定CPU:提高性能的利器

Python 绑定 CPU&#xff1a;提高性能的利器 介绍 Python 作为一门通用编程语言&#xff0c;具有易学易用、开发效率高等优点&#xff0c;但由于其解释型的特性&#xff0c;执行效率相对较低&#xff0c;尤其是在处理大量计算时&#xff0c;性能瓶颈更为明显。在这种情况下&a…

chatgpt赋能python:用Python发送短信的简单方法

用Python发送短信的简单方法 在今天的数字时代&#xff0c;没有任何事情比即时通讯更方便。然而&#xff0c;短信仍然是一种极为有用的通信方式。 实际上&#xff0c;正如您所看到的&#xff0c;本文将告诉您如何使用Python在几步内轻松地发送短信。 发送短信的三种方法 要发…

Unity之TileMap

1、创建瓦片资源 教程中老师在Asset---Create---Tile创建&#xff0c;但是新版本Unity不能这样创建 新版本是在Asset---Create---2D--Tile里面选择&#xff0c;跟老师的不太一样&#xff0c;暂时也不懂怎么解决 所以我们可以用方法二创建&#xff1a; 在Window---2D---Tile…

Linux---phy外设调试(二)

文章目录 一、mdio与rmii/sgmii二、主控mac控制器配置三、phy driver与device的匹配规则 一、mdio与rmii/sgmii 接上一篇文章《Linux—phy外设调试&#xff08;一&#xff09;》&#xff0c;在上一篇中我们说到我们还遗留了几个问题没有解释&#xff0c;其中提到的有mdio总线和…

海量数据中找出前k大数(topk问题),一篇文章教会你

&#x1f4af; 博客内容&#xff1a;【数据结构】向上调整建堆和向下调整建堆的天壤之别以及堆排序算法 &#x1f600; 作  者&#xff1a;陈大大陈 &#x1f680; 个人简介&#xff1a;一个正在努力学技术的准前端&#xff0c;专注基础和实战分享 &#xff0c;欢迎私信&…

[极客大挑战 2019]PHP1

既然提到了备份网站估计也是存在着网站备份文件&#xff0c;可以先用御剑扫一下 啥都没扫出来&#xff0c;但是上回做文件备份的题目时收集了一些关于常用备份文件的文件名和后缀&#xff0c;可以直接使用burp抓包爆破&#xff0c;果然爆破出一个www.zip文件 访问下载好文件就有…

电子科技大学编译原理复习笔记(四):程序语言的设计

目录 前言 重点一览 语言的定义 比较&#xff1a;生成观点与识别观点 语义又该怎么描述&#xff1f; 符号串 符号串集合 ⭐文法&#xff08;超重点&#xff09; 定义 组成 表示 ⭐分类&#xff08;重点&#xff09; 文法产生的语言 ⭐短语、直接短语和句柄&…

幂等问题解决

什么是幂等性&#xff1f; 幂等&#xff08;idempotent、idempotence&#xff09;是一个数学与计算机学概念&#xff0c;常见于抽象代数中。 在数学中&#xff0c;主要有两个定义 如果在一元运算中&#xff0c;x 为某集合中的任意数&#xff0c;如果满足 f(f(x))f(x)&#xff0…

软件质量测试笔记-合工大

第一章 软件质量和测试背景 应从以下几个方面考虑软件质量&#xff1a; 软件结构功能与性能开发标准与文档 IEEE关于软件质量的定义&#xff1a; 系统&#xff0c;部件&#xff0c;过程满足规定需求的程度系统&#xff0c;部件&#xff0c;过程满足顾客或者用户需要的期望程…

vue css变量实现多主题皮肤切换

实现方式 多主题皮肤切换有很多种实现方式&#xff0c;可以用css预处理器实现&#xff0c;可以用js实现&#xff0c;其实最近简单的一种方式是用css变量(css variable)实现 单页面应用中&#xff0c;可以通过设置body的css变量爱控制整个系统的颜色&#xff0c;body添加一个属…

chatgpt赋能python:Python中的绝对值函数简介

Python中的绝对值函数简介 绝对值是数学中一个基本的概念&#xff0c;在Python中也有相应的函数来实现求绝对值&#xff0c;本文将为大家介绍Python中的绝对值函数及其使用方法。 什么是绝对值 绝对值是一个数的大小&#xff0c;与数本身的符号无关。即如果一个数为正数&…

chatgpt赋能python:自动填写在SEO中的作用

自动填写在SEO中的作用 在SEO中&#xff0c;关键词的密度是非常重要的一项指标。然而&#xff0c;如果手动填写关键词&#xff0c;不仅费时费力&#xff0c;还很容易出现错误。这时候&#xff0c;一款自动填写工具就能够提高效率&#xff0c;减少出错率&#xff0c;从而提高网…

chatgpt赋能python:Python生成Pyd文件的全面指南

Python生成Pyd文件的全面指南 介绍 在Python编程中&#xff0c;我们会发现在某些情况下需要使用C或其他高效语言来提高代码执行速度。在这种情况下&#xff0c;将Python和其他语言混合编程是一个不错的选择。 本指南将介绍如何使用Python生成Python定义的C扩展程序文件 (.py…

[论文分享] jTrans: Jump-Aware Transformer for Binary Code Similarity

jTrans: Jump-Aware Transformer for Binary Code Similarity [ISSTA 2022] 二进制代码相似性检测(Binary code similarity detection, BCSD)在漏洞检测、软件构件分析、逆向工程等领域具有重要应用。最近的研究表明&#xff0c;深度神经网络(DNNs)可以理解二进制代码的指令或…

Solidity基础四

あなたもきっと、誰かの奇跡 &#xff08;你也一定会是某个人的奇迹&#xff09; 目录 一、Solidity的结构体 1.结构体的实例化 2.结构体的基本使用 访问和修改结构体成员 3.结构体的修饰符 二、Solidity的映射 1.映射的基本使用 查询和修改某个value值 三、Solidit…

Jmeter下载安装---Windows系统

Jmeter下载安装---Windows系统 jmeter是什么Jmeter下载安装安装jmeter前置必须jdk8Jmeter下载 jmeter插件环境变量配置 jmeter是什么 Apache JMeter 是 Apache 组织基于 Java 开发的压力测试工具&#xff0c;用于对软件做压力测试&#xff1b;在接口及性能测试中广泛使用&…

如何使用JQuery实现Js二级联动和三级联动

前言&#xff1a;使用JQuery封装好的js方法来实现二级三级联动要比直接使用js来实现二级三级联动要简洁很多。所以说JQuery是个非常强大的、简单易用的、兼容性好的JavaScript库&#xff0c;已经成为前端开发人员不可缺少的一部分&#xff0c;是Web开发中最流行的JavaScript库之…

《Spring Guides系列学习》guide61 - guide65

要想全面快速学习Spring的内容&#xff0c;最好的方法肯定是先去Spring官网去查阅文档&#xff0c;在Spring官网中找到了适合新手了解的官网Guides&#xff0c;一共68篇&#xff0c;打算全部过一遍&#xff0c;能尽量全面的了解Spring框架的每个特性和功能。 接着上篇看过的gui…