纯Java实现的多路归并快速排序算法

外排序之多路归并的java实现 外排序--基于败者树的多路归并排序算法的java实现 立即下载
package wjw.PreTrans;


import java.io.*;
import java.util.*;
import org.apache.commons.io.*;


public class MergeSort {
  private static FastQSortAlgorithm<String> QQ = new FastQSortAlgorithm<String>(); 
  private MergeSort() {
  }


  /**
   * 得到指定文件的行数
   * @param fileC String
   * @return int
   * @throws IOException
   */
  private static int getFileLineSize(String fileC) throws IOException {
    Reader fC = null;
    try {
      fC = new FileReader(fileC);


      LineIterator it = IOUtils.lineIterator(fC);
      int lineSize = 0;
      while(it.hasNext()) {
        it.nextLine();
        lineSize++;
      }
      return lineSize;
    } finally {
      IOUtils.closeQuietly(fC);
    }
  }


  /**
   * 得到下一行的内容,如果已到文件末尾返回NULL
   * @param iterator LineIterator
   * @return String
   */
  private static String nextLine(LineIterator iterator) {
    if(iterator.hasNext()) {
      return iterator.nextLine();
    } else {
      return null;
    }
  }


  /**
   * 读指定行数的字符串到缓冲区列表里
   * @param iterator LineIterator
   * @param bufList List
   * @param lines int
   */
  private static void readLines(LineIterator iterator, List<String> bufList, int lines) {
    for(int i = 0; i < lines; i++) {
      if(!iterator.hasNext()) {
        break;
      }
      bufList.add(iterator.nextLine());
    }
  }


  /**
   * 扫描fileC中的归并段并把它们交替分别送到文件fileA和fileB中,
   * 本次归并段的大小为k*blockSize
   * @param fileA String
   * @param fileB String
   * @param fileC String
   * @param k int
   * @param blockSize int
   */
  private static void split(String fileA, String fileB, String fileC, int k,
                            int blockSize) throws FileNotFoundException, IOException {
    boolean useA = true;
    int i = 0;


    List<String> bufList = new ArrayList<String>(blockSize); //大小为blockSize的缓冲区
    Writer fA = null;
    Writer fB = null;
    Reader fC = null;
    try {
      fA = new BufferedWriter(new FileWriter(fileA));
      fB = new BufferedWriter(new FileWriter(fileB));
      fC = new FileReader(fileC);


      LineIterator itC = IOUtils.lineIterator(fC);
      while(itC.hasNext()) {
        //->读入数据块
        bufList.clear();
        readLines(itC, bufList, blockSize);
        //<-读入数据块


        if(useA) {
          IOUtils.writeLines(bufList, "\n", fA);
        } else {
          IOUtils.writeLines(bufList, "\n", fB);
        }


        if(++i == k) {
          i = 0;
          useA = !useA;
        }
      }
    } finally {
      bufList.clear();


      IOUtils.closeQuietly(fA);
      IOUtils.closeQuietly(fB);
      IOUtils.closeQuietly(fC);
    }
  }


  /**
   * n为当前归并段大小(k*blockSize);将文件fX的后续归并段拷入到fY,变量currRunPos为当前归并段的索引
   * @param fileX String
   * @param fileY String
   * @param currRunPos int
   * @param n int
   * @return int 当前归并段的索引
   */
  private static int copyTail(LineIterator fileX, Writer fileY, int currRunPos,
                              int n) throws IOException {
    //从当前位置到归并段结束,拷贝每个数据
    while(currRunPos <= n) {
      //若没有更多的数据项,则文件结束且归并段结束
      if(!fileX.hasNext()) {
        break;
      }


      //修改当前归并段位置并将数据项写入fY
      currRunPos++;
      IOUtils.write(fileX.nextLine() + "\n", fileY);
    }


    return currRunPos;
  }


  /**
   * 将文件fA和fB中长度为n(k*blockSize)的归并段合并回fC中
   * @param fileA String
   * @param fileB String
   * @param fileC String
   * @param n int
   * @throws IOException
   */
  private static void merge(String fileA, String fileB, String fileC, int n) throws
      IOException {
    //currA和currB表示在当前归并段中的位置
    int currA = 1;
    int currB = 1;


    //分别从fA和fB中读出的数据项
    String dataA, dataB;


    Reader fA = null;
    Reader fB = null;
    Writer fC = null;
    try {
      fA = new FileReader(fileA);
      fB = new FileReader(fileB);
      fC = new BufferedWriter(new FileWriter(fileC));


      LineIterator itA = IOUtils.lineIterator(fA);
      LineIterator itB = IOUtils.lineIterator(fB);


      dataA = nextLine(itA);
      dataB = nextLine(itB);
      for(; ; ) {
        //若(dataA<=dataB),则将dataA拷贝到fC并修改当前归并段的位置
        if(dataA.compareTo(dataB) <= 0) {
          IOUtils.write(dataA + "\n", fC);


          //从fA中取下一归并段,若不存在,则已到文件尾,应将fB的后续归并段拷入到fC;
          //若当前位置>n,则已将所有fA的归并段拷完,应拷贝fB的后续归并段
          dataA = nextLine(itA);
          currA++;
          if(dataA == null || currA > n) {
            IOUtils.write(dataB + "\n", fC);
            currB++;
            currB = copyTail(itB, fC, currB, n);


            //fA的大小>=fB的大小;若在fA的文件尾,则结束
            if(dataA == null) {
              break;
            } else { //否则,应在新的归并段中,重置当前位置
              currA = 1;
            }


            //取fB中的下一项.若不存在,则只有fA中剩余的部分要拷贝到fC,
            //退出循环前将当前归并段写入fC
            dataB = nextLine(itB);
            if(dataB == null) {
              IOUtils.write(dataA + "\n", fC);
              currA = 2;
              break;
            } else { //否则,重置fB中当前归并段
              currB = 1;
            }
          }
        } else { //否则(dataA>dataB)
          IOUtils.write(dataB + "\n", fC);


          //从fB中取下一归并段,若不存在,则已到文件尾,应将fA的后续归并段拷入到fC;
          //若当前位置>n,则已将所有fB的归并段拷完,应拷贝fA的后续归并段
          dataB = nextLine(itB);
          currB++;
          if(dataB == null || currB > n) {
            IOUtils.write(dataA + "\n", fC);
            currA++;
            currA = copyTail(itA, fC, currA, n);


            //若fB中没有更多项,则置fA的当前位置,准备拷贝fA中的最后归并段到fC中
            if(dataB == null) {
              currA = 1;
              break;
            } else { //否则,置fB的当前位置,并从fA中读入数据
              currB = 1;
              if((dataA = nextLine(itA)) == null) {
                break;
              } else {
                currA = 1;
              }
            }
          }
        }
      } //<- end for(; ;)


      //将fA中可能存在的剩余的归并段写入fC中(注:fA的长度时>=fB的)
      if(dataA != null && dataB == null) {
        currA = copyTail(itA, fC, currA, n);
      }
    } finally {
      IOUtils.closeQuietly(fA);
      IOUtils.closeQuietly(fB);
      IOUtils.closeQuietly(fC);
    }
  }


  /**
   * 用指定的blockSize块大小,排序指定的文件fileC
   * @param fileC String
   * @param blockSize int
   * @throws IOException
   */


  /**
   * 用指定的blockSize块大小,排序指定的文件fileSource,排序后的文件是fileOut
   * @param fileSource String
   * @param fileOut String
   * @param blockSize int
   * @param removeDuple
   * @throws IOException
   */
  public static void sort(String fileSource,String fileOut, int blockSize,boolean removeDuple) throws IOException {
    String fileA = File.createTempFile("wjw", null).getAbsolutePath();
    String fileB = File.createTempFile("wjw", null).getAbsolutePath();
    
    int mergeIndex = 1;
    int lineSize = getFileLineSize(fileSource);
    int k = 1;
    int n = k * blockSize;
    boolean useA = true;
    List<String> list = new ArrayList<String>(blockSize);


    Writer fA = null;
    Writer fB = null;
    Reader fC = null;
    try {
      fA = new BufferedWriter(new FileWriter(fileA));
      fB = new BufferedWriter(new FileWriter(fileB));
      fC = new FileReader(fileSource);


      LineIterator itC = IOUtils.lineIterator(fC);
      if(lineSize <= blockSize) { //对于小文件,从fC读入数据,直接排序后写回文件中
        readLines(itC, list, lineSize);
        Collections.sort(list);
        IOUtils.closeQuietly(fC);
        FileUtils.writeLines(new File(fileOut), "GBK", list, "\n");


        list.clear();
        
        if(removeDuple) {
          removeDuple(fileOut);
        }
        return;
      }


      //->第一次分割,合并
      System.out.println("第:"+mergeIndex+"分割,合并");
      while(itC.hasNext()) {
        list.clear();
        readLines(itC, list, blockSize);


        Collections.sort(list);
        if(useA) {
          IOUtils.writeLines(list, "\n", fA);
        } else {
          IOUtils.writeLines(list, "\n", fB);
        }


        useA = !useA;
      }
      list.clear();


      IOUtils.closeQuietly(fA);
      IOUtils.closeQuietly(fB);
      IOUtils.closeQuietly(fC);
      merge(fileA, fileB, fileOut, blockSize);
      mergeIndex++;
      //<-第一次分割,合并


      //->将当前归并段大小加倍,循环进行
      k = k * 2;
      n = k * blockSize;
      while(n < lineSize) { //当n>=文件大小时,fC仅剩一个已排好序的归并段
        System.out.println("第:"+mergeIndex+"分割,合并");
        split(fileA, fileB, fileOut, k, blockSize);
        merge(fileA, fileB, fileOut, n);
        mergeIndex++;
        k = k * 2;
        n = k * blockSize;
      }
      //->将当前归并段大小加倍,循环进行


    } finally {
      IOUtils.closeQuietly(fA);
      IOUtils.closeQuietly(fB);
      IOUtils.closeQuietly(fC);


      (new File(fileA)).delete();
      (new File(fileB)).delete();
    }
    
    if(removeDuple) {
      removeDuple(fileOut);
    }
  }


  /**
   * 删除已经排好序的文件中重复的数据
   * @param fileC String
   * @throws IOException
   */
  private static void removeDuple(String fileC) throws IOException {
    System.out.println("去重");
    Reader fC = null;
    Writer fTemp = null;
    File tempFile = File.createTempFile("wjw", null);
    try {
      fC = new FileReader(fileC);
      fTemp = new BufferedWriter(new FileWriter(tempFile));


      String tmpA = "";
      String tmpB = "";
      LineIterator itC = IOUtils.lineIterator(fC);
      while(itC.hasNext()) {
        tmpB = itC.nextLine();
        if(tmpB.compareTo(tmpA) != 0) {
          IOUtils.write(tmpB + "\n", fTemp);
          tmpA = tmpB;
        }
      }
    } finally {
      IOUtils.closeQuietly(fTemp);
      IOUtils.closeQuietly(fC);
    }


    File cFile = new File(fileC);
    if(cFile.delete()) {
      if(tempFile.renameTo(cFile)) {
        tempFile.delete();
      }
    }
  }


  public static String formatSecond(long seconds) {
    long h = seconds /(60*60);
    StringBuffer sb = new StringBuffer();
    
    sb.append(h+"小时");
    
    seconds = seconds%(60*60);


    long c = seconds /60;
    sb.append(c+"分");


    sb.append(seconds %60+"秒");
    
    return sb.toString();
  }


  public static void main(String args[]) {
    try {
      String fileName = "d:/ESort.txt";
      int blockSize = 100000;


      long c1 = System.currentTimeMillis();
      MergeSort.sort(fileName,fileName + "_SORT", blockSize,true);
      long c2 = (System.currentTimeMillis() - c1) / 1000;
      System.out.println("耗时:"+formatSecond(c2));
    } catch(IOException ex) {
      ex.printStackTrace();
    }
  }


} 
多路归并算法 对文件里的数据(默认100个)用多路归并算法进行排序并将排序结果转移到新文件中。 立即下载

相关推荐

快速排序的六种实现,单轴快排,双轴快排JAVA实现

http://blog.youkuaiyun.com/Holmofy/article/details/71168530 这篇文章的实现代码

自定义一个简单的迭代器(line_iterator)

STL是容器、迭代器、算法三位一体的好东西,使用STL编写的程序看起来非常简洁。比如从cin输入若干字符串,每一字符串占一行,然后将这些字符串按字典序排序并输出到cout中,相关的代码如下所示: /* 迭代器的使用 * created: ume * date: 2011-12-17 * */ #include&lt;iostream&gt; #include&lt;vector&gt; ...

tempsitegoogle 317

java归并外排序

java归并外排序

Java实现快速排序、以及双路,三路快排(图解)

在《算法》第四版这本书当中有提到: 快速排序可能是现在应用最为广泛的排序算法 基本设计思想 快速排序先选择出一个元素作为标准来作为划分的依据: 一般来说这个元素时随机的选择出这个区间里的某一个元素。 快速排序与归并排序都采用的是分而治之的算法思想来完成排序的。 只不过归并排序我们是不管怎么样,都是将数组一分为二,然后不停地合并两个有序的数据。 而快速排序是在划分数组这件事上下足了文章,但是它没有合并的过程。快速排序这种特殊的分而治之的思想也可以称为减而治之的算法思想。就是将问题

古城的博客 1882

Zemax单模光纤耦合仿真避坑指南:数值孔径、模式匹配与镀膜影响详解

本文详细解析了Zemax单模光纤耦合仿真中的关键避坑要点,包括数值孔径的多重定义与换算、模式匹配度评估及镀膜影响分析。通过实际案例和技术公式,帮助工程师避免常见仿真误差,提升激光通信和光纤传感系统的设计精度。特别针对OpticStudio用户提供了实用的参数设置建议和优化策略。

weixin_30836759的博客 465

从Arduino IDE到Atmel Studio:ATmega328P开发的进阶之路

本文探讨了从Arduino IDE转向Atmel Studio进行ATmega328P开发的进阶路径。通过对比两者差异,详细介绍了Atmel Studio的环境配置、寄存器操作思维、烧录方法及高级调试功能,帮助开发者突破Arduino的封装限制,实现对单片机底层硬件的精细控制与性能优化,提升嵌入式开发的专业能力。

weixin_29193259的博客 122

Java快速排序算法、三路快排(Java算法和数据结构总结笔记)[7/20]

快速排序算法代码实现、三路快排代码实现、快速排序算法和三路快排的关系

川子的博客 1133

stm32f407等芯片(HAL库)时钟频率修改(乱码)

其他片子及库文件未知、未验证,只是在使用stm32f407ZG配置串口打印的时候,出现乱码,就从以下几方面定位问题: 1. 确认串口GPIO相关配置; 2. 确认波特率等参数; 3. 确认时钟频率; 结果这次使用YH的串口打印程序在ZDYZ的开发板调试项目工程(有点另类...),做功能验证,就出现了以上问题,出于好奇开始调试,最终发现是时钟频率问题。 看到下图这个配置,因为ZDYZ开发板使用的是8MHz外部晶振(好像默认的是25MHz,如图2),所以他这里PLL_M是25,不是推荐值,感...

bulefire2009的博客 5516

归并排序 java_Java实现归并排序

归并排序 (merge sort) 是一类与插入排序、交换排序、选择排序不同的另一种排序方法。归并的含义是将两个或两个以上的有序表合并成一个新的有序表。归并排序有多路归并排序、两路归并排序 , 可用于内排序,也可以用于外排序。这里仅对内排序的两路归并方法进行讨论。一、两路归并排序算法思路分而治之(divide - conquer);每个递归过程涉及三个步骤第一, 分解: 把待排序的 n 个元素的序...

weixin_35688459的博客 568

ADS124S08配置避坑指南:从SPI时序到寄存器设置,手把手教你调通24位ADC

本文详细解析了ADS124S08 24位ADC的SPI时序配置、寄存器设置及外围电路设计中的关键细节,帮助工程师避开常见陷阱。从SPI通信模式选择到DRDY引脚读取优化,再到基准电压启动时间调整,提供了实战验证的解决方案,确保高精度数据采集的稳定性。

weixin_29192365的博客 286

kettle实验十一:没有数据流入时停止操作

【实验目的】 1.利用Kettle的“阻塞数据直到步骤都完成”,“检测空流”,“中止”等组件,实现Kettle转换流程的控制。 2.熟练掌握“阻塞数据直到步骤都完成”,“检测空流”,“中止”等组件的使用,实现Kettle转换流程的控制。 【实验原理】 “检测空流”组件可以检测所在转换的输入数据,如果整个转换没有输入数据,通过“中止”组件终止整个转换的流程。在存在数据输入的情况,为了能让数据输出,需要和“阻塞数据直到步骤都完成”配合使用。当所有数据都已经从上个步骤“字段选择”读取完毕后,通过“阻塞数据直到步骤

weixin_44727274的博客 3848

java经典算法_JAVA十大经典排序算法

0、排序算法说明0.1 排序的定义对一序列对象根据某个关键字进行排序。0.2 术语说明稳定:如果a原本在b前面,而a=b,排序之后a仍然在b的前面;不稳定:如果a原本在b的前面,而a=b,排序之后a可能会出现在b的后面;内排序:所有排序操作都在内存中完成;外排序:由于数据太大,因此把数据放在磁盘中,而排序通过磁盘和内存的数据传输才能进行;时间复杂度: 一个算法执行所耗费的时间。空间复杂度:运行完一...

weixin_39645268的博客 401

CRMEB开源电商系统 /api/products SQL注入漏洞复现(CVE-2024-36837)

2024年6月,CRMEB开源电商系统发布了新补丁,修复了一处SQL注入漏洞(CVE-2024-36837)。经分析,该漏洞可以通过请求api的路径接口来进行SQL注入,进而可能导致敏感信息泄露,该注入可暴露后台web绝对路径,深入利用可获取服务器权限,该漏洞无前置条件且利用简单,建议受影响的用户尽快修复漏洞。

0xSec 2882

多路归并 java_纯Java实现的多路归并快速排序算法

[代码]纯Java实现的多路归并快速排序算法package wjw.PreTrans;import java.io.*;import java.util.*;import org.apache.commons.io.*;public class MergeSort {private static FastQSortAlgorithm QQ = new FastQSortAlgorithm();pr...

weixin_42439808的博客 372

基于Simulink的占空比调制DTC降低转矩脉动

修改传统SVPWM模块,输入占空比d和有效矢量索引,计算Ton​=d∗Tc​、Toff​=(1−d)∗Tc​,生成对称PWM波形(替代开关表直接输出)。:低速时(n<500rpm)减小dmax​=0.6(避免磁链畸变),高速时(n>2000rpm)增大dmax​=0.8(提升动态响应);kT​/kψ​:转矩/磁链误差增益(需整定,如kT​=0.02/(N⋅m),kψ​=0.1/Wb);(θ为电压矢量与磁链夹角)。② SVM-DTC(占空比计算模块启用,d0​=0.5,kT​=0.02,kψ​=0.1)。

amy_mhd的博客 87

matplotlib保存图片设置分辨率总是96dpi,好烦躁,教你一招轻松解决

matplotlib保存图片设置分辨率总是96dpi,好烦躁,教你一招轻松解决 目录 matplotlib保存图片设置分辨率总是96dpi,好烦躁,教你一招轻松解决 #使用plt.savefig("cm.png",dpi = 300)为什么不管用 #plt.rcParams也不管用 #解决方案 在做论文的过程中,许多期刊或者会议对图片的分辨率有明确的要求,例如,dpi=300。 之前画曲线图都是采取保存方式为savefig(dpi=300),然后查看保存图片的属性信息,然而你看到的现象是

data+scenario+science+insight 8800

多路归并排序_Java实现排序

排序通常来说, 排序是为了进行快速排序衡量排序算法的优劣方式时间复杂度: 关键字的比较次数 与 记录的移动次数空间复杂度: 排序算法中需要多少辅助内存稳定性: 如果a原本在b前面, 且a=b, 排序之后a仍然在b的前面排序前: [1, 2, 5, 3, 2]排序后: [1, 2, 2, 3, 5]可以看到第一个数组中有两个2, 如果排序后, 第一个2还是在前面, 第二个2在其后面, 称这个排序算法...

weixin_39576149的博客 724

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

数据结构与算法 - 面试手撕:归并排序的分治实现

摘要 归并排序是一种基于分治思想的高效排序算法,通过递归分解数组并合并有序子数组实现排序。其核心特性包括: 稳定时间复杂度:始终为O(n log n) 排序稳定性:保持相等元素的原始顺序 非原地排序:需O(n)额外空间 本文详解了归并排序的递归与迭代实现,提供完整的Java代码示例,并通过流程图展示分治过程。还探讨了空间优化可能性及工程实践中的取舍,帮助开发者深入理解这一经典算法。 (字数:150)

千淘万漉虽辛苦,吹尽狂沙始到金 2万+

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

排序算法--归并排序、快速排序

归并排序和快速排序都适合大规模的数据排序,它们的平均时间复杂度都是O()。这两种排序方式解决问题的方式都是将一个大问题分解成若干个小问题来解决的,小问题解决了。大问题自然也就解决了。 归并排序 归并排序的核心思想:对于一个要排序的数组,先把数组从中间分解为前后两部分,然后对前后两部分进行排序,再将排序好的数组合并在一起,这样的数组就有序了。(摘自:数据结构之美) 归并排序的主要思想:把待排序的记录序列分成若干个子序列,先将每一个子序列的记录进行排序,再将已排序的子序列合并,得到一个完全排序的记录.

铭 1314

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

java 多路归并_归并排序(Java)

选择排序的升级版本归并排序, 归并排序有二路归并,三路归并和多路归并,我这次只分析下二路归并,有机会在分析下别的。归并排序的思想是这样的:设数组a中存放了n个数据元素,初始时我们把它们看成是n个长度为1的有序子数组,然后从第一个子数组开始,把相临的子数组两两合并,得到n/2个(若n/2为小数则上取整)长度为2的新的有序子数组(当n为奇数时最后一个新的有序子数组的长度为1);对这些新的有序子数组再两...

weixin_39932344的博客 759

java 排序_快速排序java

0. 说明在计算机中,算法是很重要的一部分,前几天遇到一个面试题,快速排序的问题,今天我们就来简单的讲讲快速排序的问题。其实算法在计算机中的位置举足轻重,几乎是每一个CSer都知道的,但是个人理解的就是,所有的算法,真的是逃不出最基本的算法,那就是查找和排序。而其他所有的业务中或者是实际应用中的算法,基本上都是这些基本算法的变形或者是结合,所以我们学习算法的时候,要学会最基本的算法,并融会贯通,那...

weixin_39657521的博客 427

Java实现冒泡排序、快速排序算法

文章目录一、排序算法1.1 概念 一、排序算法 1.1 概念 排序:假设含有n个记录的序列为{R1,R2,…,Rn},其相应的关键字序列为{K1,K2,…,Kn}。将这些记录重新排序为{Ri1,Ri2,…,Rin},使得相应的关键字值满足条Ki1<=Ki2<=…<=Kin,这样的一种操作称为排序。 通常来说,排序的目的是快速查找。 ...

Charles_ZengYC的博客 980

Java归并排序

归并排序原理 归并排序(MERGE-SORT)是利用归并的思想实现的排序方法,该算法采用经典的分治(divide-and-conquer)策略(分治法将问题分(divide)成一些小的问题然后递归求解,而治(conquer)的阶段则将分的阶段得到的各答案&amp;amp;quot;修补&amp;amp;quot;在一起,即分而治之)。 网上找到的两张图片:  归并排序代码: import java.util.Arrays; /** * 归并排...

qichangjian的博客 3422
上一篇: java.util.logging.Logger使用详解
下一篇: 如何将System.out的内容重定向输出到一个界面上的文本框中
Hack_Bug
博客等级 码龄15年 34粉丝 25原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值