C++如何在STL中使用自定义排序规则

自定义排序规则通过提供满足严格弱序的比较器实现,可应用于std::sort、std::set、std::map、std::priority_queue等STL容器和算法,支持按多条件、对象属性或非标准逻辑排序,提升数据处理灵活性。

c++如何在stl中使用自定义排序规则

在C++的STL中,如果你想让数据按照非默认的、你自己的逻辑来排列,核心思路就是提供一个自定义的比较规则。这通常通过一个函数对象(functor)、一个lambda表达式,或者一个普通函数指针来实现,将其作为参数传递给需要排序的算法或容器。这样,STL算法就不会用它内置的

<

操作符来比较元素,而是用你给出的规则。

解决方案

在C++标准库中,自定义排序规则主要围绕着“比较器”(Comparator)的概念展开。无论你处理的是

std::sort

这样的算法,还是

std::set

、

std::map

、

std::priority_queue

这类有序容器,其原理都是一致的:提供一个可调用的实体,它接受两个元素作为参数,并返回一个

bool

值,指示第一个元素是否“小于”第二个元素(按照你的自定义规则)。这个“小于”必须满足严格弱序(Strict Weak Ordering)的要求。

1. 使用Lambda表达式(推荐方式)

这是现代C++中最灵活、最简洁的方式,特别适合于比较规则不复杂,或者只在特定位置使用一次的情况。

立即学习“C++免费学习笔记(深入)”;

#include #include #include #include struct Person {    std::string name;    int age;};int main() {    std::vector people = {        {"Alice", 30},        {"Bob", 25},        {"Charlie", 35},        {"David", 25}    };    // 按年龄升序排序    std::sort(people.begin(), people.end(), [](const Person& a, const Person& b) {        return a.age < b.age;    });    std::cout << "Sorted by age (ascending):" << std::endl;    for (const auto& p : people) {        std::cout << p.name << " (" << p.age << ")" << std::endl;    }    // 如果年龄相同,按姓名降序排序    std::sort(people.begin(), people.end(), [](const Person& a, const Person& b) {        if (a.age != b.age) {            return a.age  b.name; // 年龄相同时,按姓名降序    });    std::cout << "nSorted by age (asc), then name (desc):" << std::endl;    for (const auto& p : people) {        std::cout << p.name << " (" << p.age << ")" << std::endl;    }    return 0;}

2. 使用函数对象(Functor)

当比较规则比较复杂,或者需要在多个地方复用,甚至需要比较器本身维护一些状态时,函数对象是一个非常好的选择。它是一个重载了

operator()

的类。

#include #include #include #include struct Person {    std::string name;    int age;};// 按年龄降序排序的函数对象struct ComparePersonByAgeDesc {    bool operator()(const Person& a, const Person& b) const {        return a.age > b.age; // 注意这里是 >    }};// 另一个例子:按姓名长度升序struct ComparePersonByNameLength {    bool operator()(const Person& a, const Person& b) const {        return a.name.length() < b.name.length();    }};int main() {    std::vector people = {        {"Alice", 30},        {"Bob", 25},        {"Charlie", 35},        {"David", 25}    };    std::sort(people.begin(), people.end(), ComparePersonByAgeDesc());    std::cout << "Sorted by age (desc) using functor:" << std::endl;    for (const auto& p : people) {        std::cout << p.name << " (" << p.age << ")" << std::endl;    }    std::sort(people.begin(), people.end(), ComparePersonByNameLength());    std::cout << "nSorted by name length (asc) using functor:" << std::endl;    for (const auto& p : people) {        std::cout << p.name << " (" << p.age << ")" << std::endl;    }    return 0;}

3. 使用普通函数指针

虽然不如lambda和函数对象灵活,但对于简单的、无状态的比较逻辑,也可以使用普通函数。

#include #include #include #include struct Person {    std::string name;    int age;};// 普通函数作为比较器bool comparePeopleByNameAsc(const Person& a, const Person& b) {    return a.name < b.name;}int main() {    std::vector people = {        {"Alice", 30},        {"Bob", 25},        {"Charlie", 35},        {"David", 25}    };    std::sort(people.begin(), people.end(), comparePeopleByNameAsc);    std::cout << "Sorted by name (asc) using function pointer:" << std::endl;    for (const auto& p : people) {        std::cout << p.name << " (" << p.age << ")" << std::endl;    }    return 0;}

这三种方式都殊途同归,都是为了提供一个满足严格弱序的二元谓词(binary predicate),让STL算法或容器知道如何比较两个元素。

C++自定义排序规则的实际应用场景是什么?

自定义排序规则在实际开发中几乎无处不在,远不止是把数字从小到大排那么简单。我个人觉得,它真正解放了我们处理复杂数据结构的能力,让数据组织变得更加灵活和富有表现力。

想象一下,你有一个包含用户信息的列表,每个用户有ID、姓名、注册日期、活跃度等多个字段。你可能需要:

  • 按注册日期排序:最新的用户排在前面,方便查看新用户增长。
  • 按活跃度排序:最活跃的用户排在前面,用于奖励或特殊推荐。
  • 多条件复合排序:比如,先按会员等级降序,如果等级相同,再按消费金额降序,如果金额也相同,最后按注册时间升序。这种多级排序是自定义比较器最常见的应用之一,用默认的
    <

    操作符根本无法实现。

  • 自定义对象排序:你的
    struct

    或

    class

    对象通常没有默认的

    <

    操作符,或者默认的比较逻辑不符合你的需求。比如一个

    Point

    类,你可能想按距离原点的远近排序,而不是按X坐标或Y坐标。

  • 非标准顺序排序:比如,对字符串进行不区分大小写的排序,或者按照特定的字母表顺序(例如,某些语言的特殊字符排序规则)。
  • 优先级队列的自定义:
    std::priority_queue

    默认是最大堆,如果你想要一个最小堆,或者基于某个复杂逻辑的优先级队列,就必须提供自定义比较器。

  • std::set

    和

    std::map

    的键值排序:如果你想用自定义对象作为

    std::set

    的元素或

    std::map

    的键,并且希望它们按照特定规则排序,那么自定义比较器是必不可少的。

  • 性能优化或特定算法需求:在某些情况下,你可能需要一个更高效的比较函数,或者某个算法(如
    std::nth_element

    )需要一个非标准的比较逻辑来找到第k个元素。

从我的经验来看,一旦你的数据结构稍微复杂一点,或者排序需求超出了简单的升序/降序,自定义比较器就会成为你的得力助手。它让代码更清晰,意图更明确,避免了为了排序而修改原始数据结构或创建临时数据结构的麻烦。

C++自定义比较函数中的常见错误有哪些?

自定义比较函数虽然强大,但它有一个非常严格的要求:必须满足“严格弱序”(Strict Weak Ordering, SWO)。这是STL算法和容器能够正确工作的基础。违反SWO是自定义比较器最常见的错误来源,而且往往会导致程序行为异常,从错误结果到崩溃,甚至无限循环都有可能。

1. 严格弱序(SWO)的核心原则

一个比较函数

comp(a, b)

返回

true

表示

a

在排序上“小于”

b

,它必须满足:

X-Node企业快速建站1.0.6.0801

X-Node企业快速建站1.0.6.0801

特色介绍: 1、ASP+XML+XSLT开发,代码、界面、样式全分离,可快速开发 2、支持语言包,支持多模板,ASP文件中无任何HTML or 中文 3、无限级分类,无限级菜单,自由排序 4、自定义版头(用于不规则页面) 5、自动查找无用的上传文件与空目录,并有回收站,可删除、还原、永久删除 6、增强的Cache管理,可单独管理单个Cache 7、以内存和XML做为Cache,兼顾性能与消耗 8、

X-Node企业快速建站1.0.6.0801 0

查看详情 X-Node企业快速建站1.0.6.0801

  • 非自反性(Irreflexivity):
    comp(a, a)

    必须始终为

    false

    。一个元素不能“小于”它自己。

  • 非对称性(Asymmetry):如果
    comp(a, b)

    为

    true

    ,那么

    comp(b, a)

    必须为

    false

    。

  • 传递性(Transitivity):如果
    comp(a, b)

    为

    true

    且

    comp(b, c)

    为

    true

    ,那么

    comp(a, c)

    也必须为

    true

    。

  • 等价性(Equivalence):如果
    comp(a, b)

    为

    false

    且

    comp(b, a)

    也为

    false

    ,那么

    a

    和

    b

    被认为是等价的。这种等价关系也必须是传递的:如果

    a

    等价于

    b

    且

    b

    等价于

    c

    ,那么

    a

    也必须等价于

    c

    。

常见的SWO违反错误:

  • 使用
    <=

    而不是

    <

    (或

    >=

    而不是

    >

    ):这是最典型的错误。例如,如果你写

    return a.value <= b.value;

    。

    • comp(a, a)

      会返回

      true

      (因为

      a.value <= a.value

      ),违反了非自反性。

    • 结果:程序可能崩溃,或者进入无限循环,或者排序结果不正确。
  • 不一致的比较逻辑:当比较逻辑涉及多个字段时,很容易出错。例如,你可能想先按年龄排序,年龄相同再按姓名排序。
    // 错误示例:可能违反SWO[](const Person& a, const Person& b) {    if (a.age < b.age) return true;    if (a.name < b.name) return true; // 这里可能导致问题    return false;}

    这个例子的问题在于,如果

    a.age == b.age

    但

    a.name > b.name

    ,它会返回

    false

    。如果

    b.age == c.age

    但

    b.name > c.name

    ,它也会返回

    false

    。但如果

    a.age < c.age

    ,那么

    a

    应该小于

    c

    。但如果

    a.age == b.age

    且

    a.name > b.name

    ,同时

    b.age == c.age

    且

    b.name > c.name

    ,那么

    a

    和

    b

    、

    b

    和

    c

    都被认为是等价的。但

    a

    和

    c

    可能并非等价。正确的写法是:

    [](const Person& a, const Person& b) {    if (a.age != b.age) {        return a.age < b.age;    }    return a.name < b.name; // 只有当年龄完全相等时才比较姓名}

    这种分层比较的逻辑,确保了只有在更高优先级字段相等时,才进入下一级比较。

  • 比较器捕获了不稳定的状态(针对Lambda或Functor):如果你的Lambda通过引用捕获了外部变量,而这个变量在排序过程中被修改了,或者在Lambda被调用时已经失效,那么比较结果就会变得不稳定和不可预测。
    int sort_direction = 1; // 1 for asc, -1 for descstd::sort(vec.begin(), vec.end(), [&](int a, int b) {    return (a * sort_direction) < (b * sort_direction); // 错误:sort_direction可能被修改});

    应该使用按值捕获

    [=]

    或者将

    sort_direction

    作为

    const

    引用捕获。

  • 性能问题:比较函数如果执行了复杂的操作(如字符串拷贝、大量计算、IO操作),会显著拖慢排序速度,因为比较操作在排序算法中会被频繁调用。尽量保持比较函数简洁高效。
  • 对
    const

    的误解:函数对象中的

    operator()

    通常应该声明为

    const

    ,因为它不应该修改对象的状态。如果它修改了,并且这个函数对象被拷贝(例如在

    std::set

    或

    std::map

    中),那么每个拷贝可能都有不同的状态,导致行为异常。

我个人在调试这类问题时,通常会先检查比较函数是否满足

comp(a, a)

为

false

。如果不是,那几乎可以肯定就是

<=

之类的符号用错了。然后,对于复杂的多条件排序,我会仔细检查每一层逻辑,确保它们是互斥且递进的。一旦SWO被破坏,STL的行为是未定义的,任何奇怪的事情都可能发生。

除了std::sort,哪些C++ STL容器和算法支持自定义排序?

STL的强大之处在于其一致性和通用性。一旦你理解了自定义比较器的概念,你会发现它在许多地方都能派上用场,远不止

std::sort

。它允许我们对STL的各种组件进行精细控制,使其适应我们独特的数据组织需求。

1. 有序关联容器:

std::set

和

std::map

这些容器内部使用红黑树实现,它们的元素或键是自动排序的。默认情况下,它们使用

std::less

(也就是

<

操作符)来比较键。如果你想改变这个排序规则,就需要在模板参数中提供你的自定义比较器。

  • std::set

    :存储唯一且已排序的元素。

    #include #include #include struct CustomStringCompare {    bool operator()(const std::string& a, const std::string& b) const {        // 按字符串长度降序,长度相同则按字典序升序        if (a.length() != b.length()) {            return a.length() > b.length(); // 注意这里是 >        }        return a < b;    }};int main() {    std::set mySet;    mySet.insert("apple");    mySet.insert("banana");    mySet.insert("cat");    mySet.insert("dog");    mySet.insert("elephant");    for (const auto& s : mySet) {        std::cout << s << std::endl;    }    // 输出可能为:elephant, banana, apple, dog, cat (长度降序,同长度字典序)    return 0;}
  • std::map

    :存储键值对,键是唯一的且已排序的。

    #include #include #include // 使用上面定义的 CustomStringCompareint main() {    std::map myMap;    myMap["apple"] = 1;    myMap["banana"] = 2;    myMap["cat"] = 3;    myMap["dog"] = 4;    myMap["elephant"] = 5;    for (const auto& pair : myMap) {        std::cout << pair.first << ": " << pair.second << std::endl;    }    return 0;}

    需要注意的是,对于

    std::set

    和

    std::map

    ,比较器是作为模板参数传递的,这意味着它在编译时就确定了,并且通常是无状态的(或者状态在构造时确定)。

2. 优先级队列:

std::priority_queue

std::priority_queue

默认是一个最大堆,也就是说,队首元素是最大的。如果你想要一个最小堆,或者基于自定义优先级的队列,同样需要提供比较器。它的比较器参数是

Compare

,表示“less than”的关系,但实际上它用于构建一个堆,使得“最大”的元素在顶部。所以,如果你想让“最小”的元素在顶部(最小堆),你的比较器应该定义“大于”的关系。

#include #include #include struct Task {    std::string name;    int priority; // 越小优先级越高};// 自定义比较器:让优先级小的元素排在前面(即“更大”),实现最小堆struct CompareTasks {    bool operator()(const Task& a, const Task& b) const {        return a.priority > b.priority; // 如果 a 的优先级数字更大,那么 a 优先级更低,排在后面    }};int main() {    std::priority_queue<Task, std::vector, CompareTasks> taskQueue;    taskQueue.push({"High importance", 1});    taskQueue.push({"Medium importance", 2});    taskQueue.push({"Low importance", 3});    taskQueue.push({"Urgent", 0});    while (!taskQueue.empty()) {        std::cout << "Processing task: " << taskQueue.top().name                  << " (Priority: " << taskQueue.top().priority << ")" << std::endl;        taskQueue.pop();    }    // 输出顺序:Urgent, High importance, Medium importance, Low importance    return 0;}

3. 其他算法

除了

std::sort

,许多其他STL算法也接受自定义比较器,例如:

  • std::min_element

    ,

    std::max_element

    :查找序列中的最小/最大元素。

    // 查找年龄最大的Personauto oldest = std::max_element(people.begin(), people.end(),                               [](const Person& a, const Person& b) {                                   return a.age < b.age; // 返回年龄较小的那个                               });std::cout << "Oldest person: " <name << std::endl;
  • std::nth_element

    :将序列重新排列,使得第n个元素是如果整个序列被排序后,它将位于的位置。它也会把所有“小于”它的元素放在它前面,所有“大于”它的元素放在它后面。

    // 找到年龄第三大的Person(即按年龄降序排列后的第3个)// 注意:这里的比较器和std::sort一样,是定义“小于”的关系// 所以要找第三大,相当于找按升序排列后的倒数第三个,或者写一个降序比较器std::nth_element(people.begin(), people.begin() + 2, people.end(),                 [](const Person& a, const Person& b) {                     return a.age > b.age; // 降序比较器,找第3大的                 });std::cout << "Third oldest person: " << people[2].name << std::endl;
  • std::stable_sort

    :与

    std::sort

    类似,但保证相等元素的相对顺序不变。同样接受自定义比较器。

  • std::partial_sort

    :对序列的一部分进行排序。

  • std::is_sorted

    :检查序列是否已排序。

  • std::merge

    :合并两个已排序的序列。

可以说,任何涉及“比较”操作的STL算法或容器,都有可能提供自定义比较器的接口。掌握了这一核心模式,你就能更灵活、更高效地利用C++标准库来解决各种实际问题。它确实是C++泛型编程思想的一个绝佳体现。

以上就是C++如何在STL中使用自定义排序规则的详细内容,更多请关注创想鸟其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/1475839.html

赞 (0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
C++数组指针与引用结合使用方法
上一篇 2025年12月18日 23:44:12
C++数组与指针实现函数参数可变长度
下一篇 2025年12月18日 23:44:21

相关推荐

  • 百度极速版如何查看历史记录_百度极速版浏览历史的查找方法

    百度极速版如何查看历史记录_百度极速版浏览历史的查找方法百度极速版如何查看历史记录_百度极速版浏览历史的查找方法百度极速版如何查看历史记录_百度极速版浏览历史的查找方法百度极速版如何查看历史记录_百度极速版浏览历史的查找方法

    打开百度极速版APP,点击底部“我的”进入个人中心;2. 点击“历史”查看阅读浏览记录;3. 切换至“搜索浏览”查看搜索记录;4. 若无记录需检查设置中历史记录功能是否开启。 在百度极速版里查看历史记录很简单,主要通过“我的”页面进入。下面介绍具体查找方法。 如何进入历史记录页面 打开手机上的百度极…

    2026年9月26日 • 用户投稿
    200
  • 夸克怎么把网页添加到桌面_夸克网页快捷方式创建方法

    夸克怎么把网页添加到桌面_夸克网页快捷方式创建方法夸克怎么把网页添加到桌面_夸克网页快捷方式创建方法夸克怎么把网页添加到桌面_夸克网页快捷方式创建方法夸克怎么把网页添加到桌面_夸克网页快捷方式创建方法

    通过夸克浏览器可将常用网页添加到iPhone桌面,实现一键访问。首先在夸克中打开目标页面,点击底部更多选项(三个点),选择“添加到桌面”并确认,系统自动创建快捷方式;若无法直接添加,可点击分享图标,在分享列表中选择“添加到主屏幕”,按提示完成命名与放置;对于需自定义的用户,可在创建过程中修改默认标题…

    2026年9月26日 • 用户投稿
    000
  • 《生化危机:代号维罗妮卡》重制版或成为主系列大作 规格高

    《生化危机:代号维罗妮卡》重制版或成为主系列大作 规格高《生化危机:代号维罗妮卡》重制版或成为主系列大作 规格高《生化危机:代号维罗妮卡》重制版或成为主系列大作 规格高《生化危机:代号维罗妮卡》重制版或成为主系列大作 规格高

    近日,知名爆料人dusk golem透露,《生化危机:代号维罗妮卡》重制版不仅由参与过《生化危机2:重制版》和《生化危机4:重制版》的核心开发人员担纲,更在制作规格上被定位为高预算、高规格的正统主系列作品,而非普通的重制项目。 据悉,卡普空将该项目视为系列未来的重要一环,投入资源堪比全新正统续作。本…

    2026年9月26日 • 用户投稿
    000
  • 服务发现组件 Eureka 和 Nacos 有什么区别?

    服务发现组件 Eureka 和 Nacos 有什么区别?服务发现组件 Eureka 和 Nacos 有什么区别?服务发现组件 Eureka 和 Nacos 有什么区别?服务发现组件 Eureka 和 Nacos 有什么区别?

    Eureka 侧重服务注册与发现,适合简单场景;Nacos 功能更全,支持配置管理、动态更新与高扩展性,适用于复杂微服务架构。选择需根据技术栈、项目规模及未来扩展需求权衡,Nacos 在大型项目中更具优势。 Eureka 和 Nacos 都是服务发现组件,核心作用都是让服务能够被其他服务找到并调用。…

    2026年9月26日 • 用户投稿
    000
  • sublime怎么在状态栏显示文件大小和修改日期_sublime状态栏显示文件大小与修改时间

    sublime怎么在状态栏显示文件大小和修改日期_sublime状态栏显示文件大小与修改时间sublime怎么在状态栏显示文件大小和修改日期_sublime状态栏显示文件大小与修改时间sublime怎么在状态栏显示文件大小和修改日期_sublime状态栏显示文件大小与修改时间sublime怎么在状态栏显示文件大小和修改日期_sublime状态栏显示文件大小与修改时间

    Sublime Text默认不显示文件大小和修改时间,可通过安装Status Bar Enhancements等插件或自定义插件实现,手动查看则可用系统属性或控制台脚本。 Sublime Text 默认状态下不会在状态栏显示文件大小和修改日期,但可以通过启用内置功能或安装插件来实现。以下方法可以帮助…

    2026年9月26日 • 用户投稿
    000
  • 剪映创作者交流会:全面引入AI能力,打造一站式创作工具

    剪映创作者交流会:全面引入AI能力,打造一站式创作工具剪映创作者交流会:全面引入AI能力,打造一站式创作工具剪映创作者交流会:全面引入AI能力,打造一站式创作工具剪映创作者交流会:全面引入AI能力,打造一站式创作工具

    日前,剪映在2025创作者交流大会上以“all in ai,all in one,创作,无限新可能”为主题,全面展示了其在ai领域的最新进展,并与众多内容创作者深入探讨了人工智能如何重构视频创作流程、降低技术门槛,激发更广泛的创意潜能。 剪映产品负责人在会上表示,剪映的愿景是成为每一位创作者的“全能…

    2026年9月26日 • 用户投稿
    900
  • linux常用命令查看内存方法

    linux常用命令查看内存方法linux常用命令查看内存方法linux常用命令查看内存方法linux常用命令查看内存方法

    Linux 提供多种方法查看内存使用情况,包括:free:显示总内存、已用内存、空闲内存和缓冲/缓存;top:实时显示正在运行进程的内存使用情况;ps:显示所有正在运行进程及其内存占用;vmstat:显示虚拟内存统计信息,包括内存使用、分页和交换活动;grep:可与其他命令结合使用,过滤特定内存使用…

    2026年9月26日 • 用户投稿
    000
  • 京东3C品类商家必读:智能客服如何提升高客单价转化(晓多案例分享)3C高客单价转化不再难!「破局之道」最高提升15%转化率!

    京东3C品类商家必读:智能客服如何提升高客单价转化(晓多案例分享)3C高客单价转化不再难!「破局之道」最高提升15%转化率!京东3C品类商家必读:智能客服如何提升高客单价转化(晓多案例分享)3C高客单价转化不再难!「破局之道」最高提升15%转化率!京东3C品类商家必读:智能客服如何提升高客单价转化(晓多案例分享)3C高客单价转化不再难!「破局之道」最高提升15%转化率!京东3C品类商家必读:智能客服如何提升高客单价转化(晓多案例分享)3C高客单价转化不再难!「破局之道」最高提升15%转化率!

    在京东平台运营手机、电脑等高价值3c数码产品的商家,普遍遭遇转化率难以提升的挑战。由于消费者在选购这类高价商品时决策周期较长、咨询频次高、服务期望值也更高,传统的客服模式往往难以应对。晓多科技与京东的联合实践表明,通过智能客服系统全面优化服务流程的商家,其咨询转化率最高可实现超过15%的增长。本文将…

    2026年9月26日 • 用户投稿
    200
  • Gemini生成内容能导出吗 Gemini结果保存与导出技巧分享

    Gemini生成内容能导出吗 Gemini结果保存与导出技巧分享Gemini生成内容能导出吗 Gemini结果保存与导出技巧分享Gemini生成内容能导出吗 Gemini结果保存与导出技巧分享Gemini生成内容能导出吗 Gemini结果保存与导出技巧分享

    关于Gemini生成内容能否导出或保存的问题,答案是肯定的。Gemini作为一款强大的AI工具,其生成的结果通常可以通过多种方式进行保存和导出,以便您后续查阅、编辑或分享。本文旨在分享一些实用的技巧,帮助您轻松保存Gemini的输出内容。我们将分步骤讲解如何通过几种主要方式实现这一目标,方便您学习和…

    2026年9月26日 • 用户投稿
    000
  • 浅谈 Windows 桌面端触摸架构演进

    浅谈 Windows 桌面端触摸架构演进浅谈 Windows 桌面端触摸架构演进浅谈 Windows 桌面端触摸架构演进浅谈 Windows 桌面端触摸架构演进

    我在和小伙伴水触摸相关的坑,说到了上古的触摸,很难和小伙伴统一知识,于是就写了本文用于告诉大家,桌面端的触摸架构是如何一步步演进的 所有触摸架构都建立在系统之上,和系统版本相关。所以可以通过系统划分。虽然说是触摸架构,但是我能知道的也就是应用层面的接口和编程方法,如果是小伙伴被标题吸引过来的,想看触…

    2026年9月26日 • 用户投稿
    100
  • pr如何把文字置于背景图片下方

    pr如何把文字置于背景图片下方pr如何把文字置于背景图片下方pr如何把文字置于背景图片下方pr如何把文字置于背景图片下方

    在使用premiere pro(pr)进行视频编辑时,将文字放在背景图片下方是一个常见的需求。以下为你详细介绍操作方法。 首先,在pr中导入背景图片和准备添加的文字素材。将背景图片拖入时间轴的视频轨道。 接下来添加文字。点击“字幕”工具,在节目监视器中创建文字。你可以设置文字的字体、大小、颜色等属性…

    2026年9月26日 • 用户投稿
    100
  • sublime怎么搭建go语言开发环境_sublime Go语言开发环境配置

    sublime怎么搭建go语言开发环境_sublime Go语言开发环境配置sublime怎么搭建go语言开发环境_sublime Go语言开发环境配置sublime怎么搭建go语言开发环境_sublime Go语言开发环境配置sublime怎么搭建go语言开发环境_sublime Go语言开发环境配置

    首先安装Go环境并配置GOPATH、GOROOT和PATH,验证go version和go env;接着安装Sublime Text及其包管理工具Package Control;然后通过Ctrl+Shift+P安装GoSublime、GoFmt和SideBarGo插件;再进入GoSublime Pr…

    2026年9月26日 • 用户投稿
    200
  • linux必学常用命令有哪些

    linux必学常用命令有哪些linux必学常用命令有哪些linux必学常用命令有哪些linux必学常用命令有哪些

    Linux 入门必学的常用命令包括:文件与目录管理:列出、创建、移动、复制和删除文件与目录。文件内容操作:查看、逐页查看、搜索和按行显示文件内容。系统信息:查看系统版本、运行时间、磁盘和内存使用情况。用户与权限:显示当前用户、添加用户和组、更改密码。网络:测试连接、显示网络接口信息、查询 DNS 记…

    2026年9月26日 • 用户投稿
    000
  • 实现搜索结果按字母排序:PHP结合Ajax的专业教程

    本文档旨在提供一种使用PHP和Ajax对通过POST方法获取的搜索结果进行A-Z排序的解决方案。我们将创建一个表单,保存POST数据,并利用PHP函数对医生列表进行排序,最终通过Ajax实现无需刷新页面的排序功能。 1. 修改 search.php 文件 首先,我们需要在 search.php 文件…

    2026年9月26日
    000
  • 一篇文章带你深入了解Flink SQL流处理中的特殊概念

    一篇文章带你深入了解Flink SQL流处理中的特殊概念一篇文章带你深入了解Flink SQL流处理中的特殊概念一篇文章带你深入了解Flink SQL流处理中的特殊概念一篇文章带你深入了解Flink SQL流处理中的特殊概念

    本文深入探讨了flink sql流处理中的特殊概念,主要包括表与流处理的区别、动态表的概念以及流式持续查询的过程。以下是详细介绍。 一、流处理和关系代数(表,及 SQL)的区别 可以看出,关系代数(主要指关系型数据库中的表)和 SQL 主要针对批处理,这与流处理存在天然的差异。 二、动态表(Dyna…

    2026年9月26日 • 用户投稿
    100
  • QQ好友动态无法查看怎么办

    QQ好友动态无法查看怎么办QQ好友动态无法查看怎么办QQ好友动态无法查看怎么办QQ好友动态无法查看怎么办

    首先检查好友动态权限,确认是否被限制访问;再核实自身账号状态,排除被拉黑可能;接着清除QQ缓存并更新至最新版本;最后尝试切换网络或使用网页端查看。 QQ好友动态无法查看,通常和权限设置、网络问题或软件异常有关。先别着急,可以按以下方法逐一排查解决。 检查好友的动态权限设置 有些好友设置了动态访问权限…

    2026年9月26日 • 用户投稿
    000
  • NVIDIA仍占67% 5年后AMD能抢4%的AI显卡市场

    NVIDIA仍占67% 5年后AMD能抢4%的AI显卡市场NVIDIA仍占67% 5年后AMD能抢4%的AI显卡市场NVIDIA仍占67% 5年后AMD能抢4%的AI显卡市场NVIDIA仍占67% 5年后AMD能抢4%的AI显卡市场

    英伟达总市值逼近4.5万亿美元#英伟达 这两年来ai领域最大的赢家并非微软、谷歌或openai,而是nvidia。凭借在ai gpu领域的绝对主导地位,nvidia不仅实现了业绩的爆发式增长,更在近期将公司市值推向了约4.5万亿美元的历史新高。 在AI显卡市场,NVIDIA几乎处于垄断地位。尽管不同…

    2026年9月26日 • 用户投稿
    1100
  • CountDownLatch, CyclicBarrier, Semaphore 的使用场景与区别

    CountDownLatch, CyclicBarrier, Semaphore 的使用场景与区别CountDownLatch, CyclicBarrier, Semaphore 的使用场景与区别CountDownLatch, CyclicBarrier, Semaphore 的使用场景与区别CountDownLatch, CyclicBarrier, Semaphore 的使用场景与区别

    CountDownLatch用于主线程等待其他线程完成操作,CyclicBarrier用于多线程相互等待至屏障点后集体执行,Semaphore用于控制并发访问资源的线程数量。 CountDownLatch, CyclicBarrier, Semaphore 都是并发编程中用于线程同步的工具,但它们的…

    2026年9月26日 • 用户投稿
    500
  • DDR5内存超频指南:芝奇幻锋戟6400MHz稳定性测试

    DDR5内存超频指南:芝奇幻锋戟6400MHz稳定性测试DDR5内存超频指南:芝奇幻锋戟6400MHz稳定性测试DDR5内存超频指南:芝奇幻锋戟6400MHz稳定性测试DDR5内存超频指南:芝奇幻锋戟6400MHz稳定性测试

    ddr5内存可以超频到6400mhz,但需要仔细调整和测试以确保稳定性。1.选择适合超频的ddr5内存条时,优先考虑芝奇幻锋戟系列,选择标有“oc”标签且规格接近目标频率的产品。2.在bios中将频率设为6400mhz,从宽松时序如cl36-36-36-76开始调整,并设定电压在1.25v到1.35…

    2026年9月26日 • 用户投稿
    000
  • 基于Quarkus的云原生Java开发:启动时间低于0.5秒的实践方案

    基于Quarkus的云原生Java开发:启动时间低于0.5秒的实践方案基于Quarkus的云原生Java开发:启动时间低于0.5秒的实践方案基于Quarkus的云原生Java开发:启动时间低于0.5秒的实践方案基于Quarkus的云原生Java开发:启动时间低于0.5秒的实践方案

    Quarkus通过GraalVM Native Image预编译实现启动时间低于0.5秒,需配置pom.xml插件、优化依赖、使用Quarkus CLI并监控调优。 Quarkus通过预编译和GraalVM Native Image等技术,让Java应用在云原生环境中拥有极低的启动时间和内存占用。本…

    2026年9月26日 • 用户投稿
    500

发表回复

登录后才能评论
关注微信