C++拾趣——使用stl标准库实现排序算法及评测

GESP C++四级最长连续段解题:排序算法与调试技巧全解析 在算法与数据结构的学习中,排序是基础且核心的操作,它通过将无序数据按特定规则排列,为后续处理提供便利。其原理基于比较或非比较策略,旨在提升数据访问与处理的效率。掌握排序算法不仅有助于理解时间复杂度与空间复杂度的权衡,更是解决众多实际问题的关键技术。在编程竞赛和等级认证中,排序常与去重、遍历等操作结合,用于解决如寻找最长连续序列这类经典问题。本文以GESP C++四级考试为背景,深入探讨如何运用排序法高效求解“最长连续段”问题,并分享实用的调试技巧与备考策略,帮助考生巩固基础,提升实战能力。 阅读详情

        今天看了一篇文章,讲各种语言的优势和劣势。其中一个观点:haskell非常适合写算法,因为使用者不用去关心具体的计算机实现,而只要关注于操作语义。这让它在专心研究算法的人中非常受欢迎。所以很多时候,语言的争论没有太多的意义,有意义的是它适不适合某些场景或者某些人。(转载请指明出于breaksoftware的csdn博客)

        目前在网上讨论排序算法更多是C语言实现的。因为C语言可以展现出一些细节。但是从某种角度说,这也让“算法思想的光辉”被计算机操作细节所遮蔽。本文将使用C++的标准库去实现一些排序算法,我们从中将会发现它掩盖了很多计算机操作细节,而让算法的光辉得以显现。

实现

选择排序

template<class ForwardIt>
void selection_sort(ForwardIt begin, ForwardIt end) {
    for (ForwardIt i = begin; i != end; ++i) {
        std::iter_swap(i, std::min_element(i, end));
    }
}

        min_element返回两个索引之间最小元素的索引;iter_swap将最小索引和不停迭代的索引进行交换。

        这就是选择排序:逐位替换之后(包含自身)序列中最小的元素。

合并排序

template<class ForwardIt>
void merge_sort(ForwardIt begin, ForwardIt end)
{
    if (end - begin > 1) {
        ForwardIt middle = begin + (end - begin) / 2;
        merge_sort(begin, middle);
        merge_sort(middle, end);
        std::inplace_merge(begin, middle, end);
    }
}

        inplace_merge会将有序序列[begin,middle)和有序序列[middle,end)合并成一个有序队列[begin,end)。因为merge_sort会递归下去,所以可以从最低粒度开始保证上述是有序的。

插入排序

template<class ForwardIt>
void insertion_sort(ForwardIt begin, ForwardIt end) {
    for (ForwardIt i = begin; i != end; ++i) {
        std::rotate(std::upper_bound(begin, i, *i), i, std::next(i));
    }
}

        upper_bound返回已排序[begin,i)序列中第一个大于i所指向值的迭代器j。rotate把i翻转到j,[j,i)之间的数据往后移动。

        由于i是从begin开始迭代,所以可以保证[begin,i)区间是有序的。

        rotate后两参数——i和std::next(i)构成了[i,i+1)区间,即只有迭代器i。

快速排序

template <class ForwardIt>
void quick_sort(ForwardIt first, ForwardIt last) {
    if (first == last) return;
    auto pivot = *std::next(first, std::distance(first, last) / 2);
    ForwardIt middle1 = std::partition(first, last,
        [pivot](const auto& em) { return em < pivot; });
    ForwardIt middle2 = std::partition(middle1, last,
        [pivot](const auto& em) { return !(pivot < em); });
    quick_sort(first, middle1);
    quick_sort(middle2, last);
}

        pivot指向容器中位置处于中间的迭代器所指向的值。

        partition可以保证按照lambda表达式的结果,将序列分成两个区间,并返回第二个区间的首元素迭代器。

        middlle1的左边元素都是小于pivot,右边的都是大于等于pivot的。

        middle2指向的是大于pivot的元素区间首个迭代器。

        [middle1,middle2)就是所有等于pivot的元素。

        然后递归调用自身,分别处理[first,middle1)和[middle2,last)区间。

        由于partition是不稳定的,如果希望使用稳定的版本,可以使用partition_stable替代。

堆排序

template<class ForwardIt>
void heap_sort(ForwardIt first, ForwardIt last) {
    std::make_heap(first, last);
    std::sort_heap(first, last);
}

        由于C++对此封装太多,所有我们没法从名称上看到其算法光辉。

评测

class UtSort:
    public ::testing::Test
{
protected:
    virtual void SetUp() {
        _data.resize(_data_count);
        std::iota(_data.begin(), _data.end(), 1);

        _orded_data.assign(_data.begin(), _data.end());

        std::random_device rd;
        std::mt19937 g(rd());
        std::shuffle(_data.begin(), _data.end(), g);
    } 

    template<class ForwardIt>
    void test_the_same(ForwardIt begin, ForwardIt end) const {
        auto same_count = std::inner_product(begin, end,
                                            _orded_data.begin(), 0,
                                            std::plus<>(), std::equal_to<>());
        ASSERT_EQ(same_count, std::distance(begin, end));
    }
        
protected:
    std::vector<int> _data;
    decltype(_data) _orded_data;
    size_t _data_count = 1024 * 256;
};  

        我们使用gtest测试框架。

        第7行,我们构建了按1递增的数列_data,它是有序的。第9行将这个排序的数据保存到_orded_data中以供之后比较。第13行,我们将_data中的元素顺序打乱。

       第18行,将计算两个序列中,相同位置的值相等的格式。如果我们算法正确,则个数和传入的迭代器个数一致。

       为了测试每个排序的时间,我还设计了Perform用于统计时间

#include <gtest/gtest.h>
#include <iostream>
#include <algorithm>
#include <functional>
#include <vector>
#include <array>
#include <numeric>
#include <set>
#include <chrono>
#include <random>

using duration_mil = std::chrono::duration<double, std::milli>;

class Perform {
public:
    Perform() {
        _start = std::chrono::high_resolution_clock::now();
    }

    ~Perform() {
        _end = std::chrono::high_resolution_clock::now();
        duration_mil ms = _end - _start;
        std::cout << ms.count() << "ms" << std::endl;
    }
private:
    decltype(std::chrono::high_resolution_clock::now()) _start;
    decltype(std::chrono::high_resolution_clock::now()) _end;
};

        于是之前介绍的几种排序的测试代码是

TEST_F(UtSort, quick_sort) {
    {
        Perform perform;
        quick_sort(_data.begin(), _data.end());
    }
    test_the_same(_data.begin(), _data.end());
}

TEST_F(UtSort, heap_sort) {
    {
        Perform perform;
        heap_sort(_data.begin(), _data.end());
    }
    test_the_same(_data.begin(), _data.end());
}

TEST_F(UtSort, insertion_sort) {
    {
        Perform perform;
        insertion_sort(_data.begin(), _data.end());
    }
    test_the_same(_data.begin(), _data.end());
}

TEST_F(UtSort, merge_sort) {
    {
        Perform perform;
        merge_sort(_data.begin(), _data.end());
    }
    test_the_same(_data.begin(), _data.end());
}

TEST_F(UtSort, selection_sort) {
    {
        Perform perform;
        selection_sort(_data.begin(), _data.end());
    }
    test_the_same(_data.begin(), _data.end());
}

        除了这几种排序外,STL标准库还提供了其他几种方法

  • 使用partial_sort进行局部排序
  • 使用sort函数
  • 使用关系容器,比如set

        这三种的测试代码如下

TEST_F(UtSort, partial_sort) {
    {
        Perform perform;
        std::partial_sort(_data.begin(), _data.end(), _data.end());
    }
    test_the_same(_data.begin(), _data.end());
}

TEST_F(UtSort, stl_sort) {
    {
        Perform perform;
        std::sort(_data.begin(), _data.end());
    }
    test_the_same(_data.begin(), _data.end());
}


TEST_F(UtSort, set_sort) {
    std::set<int> ordered_data;
    {
        Perform perform;
        std::copy(make_move_iterator(_data.begin()), make_move_iterator(_data.end()), std::inserter(ordered_data, ordered_data.begin()));
    }
    test_the_same(ordered_data.begin(), ordered_data.end());
}

        这儿特别提一句,如果我们不需要全排序,只需要前N个元素是排序的,则可以优先考虑partial_sort。因为它的效率很高,比如下面代码测试排序最小的10个元素

TEST_F(UtSort, partial_sort_head_10) {
    {
        Perform perform;
        std::partial_sort(_data.begin(), std::next(_data.begin(), 10), _data.end());
    }
    test_the_same(_data.begin(), std::next(_data.begin(), 10));
}

        我们看下测试结果

[==========] Running 8 tests from 1 test case.
[----------] Global test environment set-up.
[----------] 8 tests from UtSort
[ RUN      ] UtSort.quick_sort
135.274ms
[       OK ] UtSort.quick_sort (168 ms)
[ RUN      ] UtSort.heap_sort
194.824ms
[       OK ] UtSort.heap_sort (225 ms)
[ RUN      ] UtSort.insertion_sort
2637.53ms
[       OK ] UtSort.insertion_sort (2667 ms)
[ RUN      ] UtSort.merge_sort
135.243ms
[       OK ] UtSort.merge_sort (165 ms)
[ RUN      ] UtSort.selection_sort
337051ms
[       OK ] UtSort.selection_sort (337083 ms)
[ RUN      ] UtSort.partial_sort
195.34ms
[       OK ] UtSort.partial_sort (225 ms)
[ RUN      ] UtSort.stl_sort
84.7456ms
[       OK ] UtSort.stl_sort (118 ms)
[ RUN      ] UtSort.set_sort
294.94ms
[       OK ] UtSort.set_sort (456 ms)
[ RUN      ] UtSort.partial_sort_head_10
2.51487ms
[       OK ] UtSort.partial_sort_head_10 (31 ms)
[----------] 8 tests from UtSort (340973 ms total)

[----------] Global test environment tear-down
[==========] 8 tests from 1 test case ran. (340973 ms total)
[  PASSED  ] 8 tests.

        完整排序中,std::sort是最快的,其次是quick_sort和merge_sort。heap_sort和partial_sort差不多。最差的是selection_sort。

        同时,我们看使用partial_sort只选出并排列最小的10个元素的耗时是2.51487毫秒。这比任何一个排序都要快两个数量级。

        所以根据不同场景,选择合适的排序非常重要。

        相关代码见:https://github.com/f304646673/stl_example/tree/master/sort

数据结构与算法入门:7本经典书籍横向评测(附C++/PASCAL语言对比) 本文横向评测了7本经典数据结构与算法教材,重点对比了C++与PASCAL语言在数据结构学习中的优劣势。通过分析各教材特点、语言适配性及适用场景,帮助初学者选择合适的学习路径,掌握排序等核心算法,提升编程能力。 阅读详情

相关推荐

实战指南:用C++估算你的算法会不会超时(附复杂度速查表)

本文提供了用C++估算算法是否会超时的实战指南,重点解析了时间复杂度与数据范围的关系,并附有复杂度速查表。通过详细的时间复杂度分析和优化技巧,帮助开发者避免TLE(Time Limit Exceeded)问题,提升算法竞赛中的表现。

weixin_29216049的博客 429

【C++标准库】std::chrono

C++ 给我们封装好了不同的时间段类型,我们知道typedef作用,给类起别名。类minutes 就是 duration= 29 bits, ratio>。所以创建时间段对象,可以直接用 minutes 对象名//就可以得到一个20分钟的对象。所以,我们除了可以用std::chrono::duration自己指定一个时间段类型,还可以用标准库中内置的 minutes,seconds时间段类型。上面有一些成员属性,以及函数,有C++基础的应该都能看懂。

m0_57168310的博客 3513

C++排序去重算法详解:从数组排序到集合应用实战

排序和去重是数据处理与算法竞赛中的基础核心操作。排序算法通过特定规则(如快速排序、归并排序)将无序数据整理为有序序列,便于后续分析与检索;去重则是在数据集中识别并移除重复项,确保数据的唯一性。这两项技术的工程价值在于能显著提升数据质量与查询效率,是数据库索引、统计分析、日志清洗等场景的基石。在C++中,标准库提供了强大的sort函数与set容器,前者能高效完成通用排序,后者则利用红黑树结构天然实现有序去重。本文以一道经典算法题为例,深入剖析数组排序遍历与集合(Set)两种主流实现方案,详解其原理、代码细节与

weixin_32705179的博客 279

C++11 std::chrono库

chrono是一个time library, 源于boost,现在已经是C++标准。 要使用chrono库,需要 #include<chrono>,其所有实现均在std::chrono namespace下。 chrono是一个模版库,使用简单,功能强大,只需要理解三个概念:duration、time_point、clock 1.Durations std::chrono::duration 表示一段时间,比如两个小时,12.88秒,半个时辰等等,只要能换算成秒即可。 template <

幽冥之花的博客 9169

算法竞赛宝典第一部实战资源包

C++是一种高级编程语言,以其性能优势和灵活性在系统软件开发、游戏开发、实时物理模拟等领域广泛应用。作为C语言的继承者,C++增加了面向对象的编程特性,同时支持泛型编程和低级内存操作。快速排序是C++中常用的一种排序算法,它的基本思想是通过一趟排序将待排记录分隔成独立的两部分,其中一部分记录的关键字均比另一部分的关键字小,则可分别对这两部分记录继续进行排序,以达到整个序列有序。

weixin_35753291的博客 758

精选竞争性编程算法与数据结构资源

本文还有配套的精品资源,点击获取 简介:竞争性编程是一种在线编程竞赛,旨在提高程序员的算法设计、问题解决和编程速度。本资源列表着重于算法和数据结构,提供基础算法、动态规划、贪心算法、回溯法、高效数据结构以及C++编程技巧。此外,还包括预处理、调试技巧、时间与空间复杂度分析,以及竞赛策略。通过实践和经验积累,参与模拟竞赛和在线平台解决问题集,可以提升竞争性编程技能。"comp...

weixin_35920379的博客 725

C++ std::chrono库使用指南 (实现C++ 获取日期,时间戳,计时等功能)

C++ std::chrono库使用指南 (实现C++ 获取日期,时间戳,计时等功能)

探索C++编程的奥秘,分享深入的技术见解和实践,旨在激发读者创造力与解决问题的思维。 1万+

华为OJ解决方案集:编程题源代码大全

华为OJ(Online Judge)平台是面向全球开发者提供的一个在线编程练习和评测服务。该平台旨在通过解决编程题目来提升开发者的算法和编程能力,为华为及其他技术公司选拔优秀人才提供参考。

weixin_33660045的博客 926

C++,std::chrono 详解

std::chrono 是 C++11 引入的一个库,用于处理日期和时间。它提供了一套丰富的类和函数,允许开发者以高精度(通常是纳秒级)来测量时间间隔、表示时间点、以及进行时间的算术运算。下面是对 std::chrono 库中一些关键组件的详细解释。

汽车电子软件领域知识分享 2327

HALCON实战:用两个工业相机实现无缝大视野拼接(附完整代码与避坑指南)

本文详细介绍了使用HALCON软件实现双工业相机图像无缝拼接的完整解决方案,涵盖硬件配置、相机标定、坐标系转换和图像拼接等关键步骤。通过高精度标定和矩阵变换技术,可构建大视野检测系统,适用于液晶面板、PCB等工业检测场景,显著提升检测效率和精度。

weixin_29050513的博客 190

别再到处搜了!高德地图瓦片URL参数(lang、style、ltype)全解析与实战搭配指南

本文全面解析高德地图瓦片URL参数(lang、style、ltype)的核心逻辑与实战应用,提供18种实用参数组合方案,帮助开发者实现从基础到高阶的定制化地图渲染。涵盖语言控制、地图样式、图层类型等关键参数,并分享WebGIS项目中的优化技巧与常见问题解决方案。

weixin_33724046的博客 117

[C++]C++ std::chrono库使用

我们的生活在时间的流逝中不断推进,这个自然的过程在C++中被封装在了这个类中。我们如同航海者使用指南针导航一样,可以借助在编程的海洋中导航。是一个代表系统广泛使用的实时钟的类。它表示当前的墙上时间,从中可以获得当前时间,也可以在时间点上执行算术运算。(时间点)可以被视为一个特殊的"时间戳",它表示自纪元以来的时间量。纪元是指定的起点时间,对于来说,纪元通常是1970年1月1日午夜。在这个定义中,我们可以看出time_point。

FL1768317420的博客 3227

从零构建锂电池主动均衡系统:Simulink仿真中的Buck-Boost拓扑实战指南

本文详细介绍了如何在Simulink中从零构建基于Buck-Boost拓扑的锂电池主动均衡系统。通过仿真环境搭建、参数优化、控制策略设计和性能评估,为工程师提供了完整的实战指南,帮助快速验证和优化均衡算法,提升电池组一致性与寿命。

gitlab7runner的博客 896

跳槽准备之c/c++跳槽充能路线

为换工作准备,会持续更新,嗯!。

qq_44325794的博客 889

【dify】 dify环境变量配置说明

SMTP_SERVER、SMTP_PORT、SMTP_USERNAME、SMTP_PASSWORD、SMTP_USE_TLS、SMTP_OPPORTUNISTIC_TLS:当 MAIL_TYPE 为 smtp 时,SMTP服务器的相关配置。UPLOAD_IMAGE_FILE_SIZE_LIMIT、UPLOAD_VIDEO_FILE_SIZE_LIMIT、UPLOAD_AUDIO_FILE_SIZE_LIMIT:分别为上传图像、视频、音频文件的大小限制(MB)。

tonysh_zds的博客 7355

primetime如何做voltage scaling

存在这样的情况,标准单元库只有ssgnp0p72vm40c和ssgnp0p9vm40c的libs,但是我们希望它工作在ssgnp0p76vm40c,这样的话就需要用ssgnp0p72vm40c和ssgnp0p9vm40c的libs来scaling出ssgnp0p76vm40c的lib。

qq_34326957的博客 1683

从零开始掌握洛谷竞赛排序算法:原理、实现与优化

本文详细介绍了洛谷竞赛中排序算法的原理、实现与优化技巧,包括计数排序、快速排序等基础算法及其在程序设计竞赛中的实际应用。通过具体案例和代码示例,帮助读者掌握如何根据不同题目特性选择合适的排序算法,提升解题效率。

r2s3t4的博客 196

华为OD机试 - 城市聚集度(Python/JS/C/C++ 2025 A卷 200分)

华为OD机试 2025A卷题库疯狂收录中,刷题。

学Java,找哪吒 1129

C++函数模板实战:数组排序输出与泛型编程核心解析

泛型编程是C++中实现代码复用和类型安全的核心范式,其核心机制是函数模板。函数模板通过参数化类型,允许开发者编写与具体数据类型无关的通用算法,其原理是在编译时根据调用处的实际类型进行实例化,生成特定版本的函数代码。这一技术极大地提升了代码的灵活性和可维护性,是标准模板库(STL)的基石。在数据处理领域,排序算法是最基础且高频的操作之一,将函数模板与排序算法结合,可以构建出适用于`int`、`double`、`char`乃至自定义类型的通用排序方案。本文以`PTA 6-1`题目为具体场景,深入探讨如何设计一个

weixin_33755557的博客 480

硬件基础知识-电机知识

步进电机存在空载启动频率,所以步进电机可以低速正常运转,但若高于一定速度时就无法启动,并伴有尖锐的啸叫声;在非超载的情况下,电机的转速、停止的位置只取决于脉冲信号的频率和脉冲数。给电机两根线供电,电机就可以旋转,给正电压,电机正转,给相反电压,电机反转;电压越大,电机转得越快,电压越小,转速也变小。是一种直流电机,有刷电机的定子上安装有固定的主磁极和电刷,转子上安装有电枢绕组和换向器。控制器:使用专用的电子控制器来监测和控制电机的转速、电流和方向。线圈电流方向的交替变化是随电机转动的换相器和电刷来完成的。

weixin_46969363的博客 2294

宇树G1开发实践--PPT汇报(基础版)

本文介绍了一套基于宇树G1人形机器人的PPT自动演示系统,可实现"一键启动、自动演讲"功能。系统通过多线程同步技术,将音频播放与机器人动作完美结合,支持12种预设社交互动动作。硬件依赖宇树G1机器人、外接音响和网络连接,软件采用Python SDK和ALSA音频工具。核心功能包括音频文件自动排序、外接音响播放控制、机器人动作执行及音画同步。使用时需配置网络接口和音频设备号,运行后自动按顺序播放音频并执行随机动作。系统特别强调了安全注意事项,并提供了常见问题解决方案,适用于展会、汇报等需要

m0_47999117的博客 510

c语言程序设计与算法,程序设计与算法(一)C语言程序设计

课程概况C++语言的功能和方便性都强于C语言,只是由于其面向对象的特性比较复杂,因此很少被选为入门语言。实际上,C语言是C++的子集,C++对C语言的扩充可以分为与面向对象无关的新语法特性、面向对象的特性,以及泛型特性三个部分。如果放弃其中复杂的面向对象特性,以及泛型的绝大多数特性(但保留其中极其有用的标准模板库STL中的部分算法和容器),则剩余部分也十分适合做为入门语言来学,而且用这样的“简化”...

weixin_27006759的博客 293

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

C++结构体实战入门:从学生信息管理理解数据建模

结构体是C++中实现数据聚合与对象建模的基础机制,其核心在于将相关字段封装为逻辑整体,解决平行数组导致的数据耦合断裂、语义模糊和扩展困难等问题。原理上,结构体通过连续内存布局与编译器对齐规则保障访问效率与缓存友好性;技术价值体现在提升代码可读性、可维护性及工程一致性——尤其在学生信息管理这类典型实体建模场景中,结构体天然映射现实‘学生’概念,支持批量操作、条件筛选与后续算法扩展。本文以洛谷P5744题为载体,详解结构体定义、内存布局、C/C++风格差异及VSCode实战配置,覆盖从零编码到AC提交的完整闭环

weixin_34357887的博客 590

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

Outlook Express 6 (OE6) for Win7/Win8/Win10

英文版 Outlook Express6.0, 兼容Win7/Win10/WinXP,解压就可用。

HDU 1113 Word Amalgamation

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1113 本题目用map图做的话就很简当了 #include #include #include #include using namespace std; int main() { string s,t; map M;//建一个下标为字符串的,存东西也是字符串的M; whil

u010456428的专栏 550

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

蓝桥杯国赛C++ B组真题解析:算法思维与实战技巧深度剖析

算法竞赛是检验编程与逻辑思维能力的有效途径,其核心在于对基础数据结构和经典算法的灵活运用。从原理上看,它要求参赛者将实际问题抽象为数学模型,并选用或设计合适的算法(如动态规划、搜索、图论算法)进行高效求解。这类竞赛的技术价值在于能系统性提升问题分析、算法设计、边界把控和代码调试等工程实践能力,尤其在时间与资源双重限制下,对思维缜密度和临场应变能力是极佳的锻炼。其应用场景广泛,不仅是各类编程竞赛的备战核心,也是面试选拔和解决实际工程中优化问题的基石。本文以2019年蓝桥杯国赛C++ B组真题为例,深入剖析了其

weixin_30788619的博客 426

超越增长阶:大O符号在算法分析中的辩证思考与现代实践

本文探讨了大O符号在算法分析中的理论价值与实际应用中的局限性。文章指出,大O符号虽然能有效比较算法的渐进效率,但忽略了常数因子、缓存友好性等关键现实因素。通过快速排序与堆排序等实例分析,揭示了低复杂度算法未必总是最优的实践真相。作者建议工程师应辩证看待大O分析,结合具体数据规模、硬件特性和缓存行为进行综合评估,采用混合策略实现最优性能。全文强调理论分析与工程实践的平衡,为算法优化提供了多维度的思考框架。

计算机科学、人工智能、数据分析和大数据方向的研发和教学。 404
上一篇: C++拾趣——使用stl标准库生成等差、等比数列的方法
下一篇: 并行计算——OpenMP加速矩阵相乘
breaksoftware
breaksoftware 领域专家: 操作系统技术领域 领域专家: 操作系统技术领域
博客等级 码龄20年 6901粉丝 724原创
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

breaksoftware

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值