各大排序算法汇总

经典排序算法汇总,从各大网站整理了一下,有什么问题大家可以一起讨论,欢迎转载


(一)基于比较的排序算法:

1.第一类——插入排序法:直接插入排序,希尔。以及不常见的Tree sort、Library sort、Patience sorting 。


①直接插入排序

1算法的伪代码:    

     INSERTION-SORT (A, n)             A[1 . . n]
     for j
2 to n
          do key
A[ j]
          i
j – 1
          while i > 0 and A[i] > key
               do A[i+1]
A[i]
                    i
i – 1
          A[i+1] = key

 2思想将一个记录插入到已排序好的有序表中,从而得到一个新,记录数增1的有序表。即:先将序列的第1个记录看成是一个有序的子序列,然后从第2个记录逐个进行插入,直至整个序列有序为止。

要点:设立哨兵,作为临时存储和判断数组边界之用。

直接插入排序示例:


     3算法时间复杂度。 
       
最好的情况下:正序有序(从小到大),这样只需要比较n次,不需要移动。因此时间复杂度为O(n)  

        最坏的情况下:逆序有序,这样每一个元素就需要比较n次,共有n个元素,因此实际复杂度为O(n­2)  

        平均情况下:O(n­2


   4、稳定性:

插入排序是在一个已经有序的小序列的基础上,一次插入一个元素。当然,刚开始这个有序的小序列只有1个元素,就是第一个元素。比较是从有序序列的末尾开始,也就是想要插入的元素和已经有序的最大者开始比起,如果比它大则直接插入在其后面,否则一直往前找直到找到它该插入的位置。如果碰见一个和插入元素相等的,那么插入元素把想插入的元素放在相等元素的后面。所以,相等元素的前后顺序没有改变,从原无序序列出去的顺序就是排好序后的顺序,所以插入排序是稳定的。

5、C语言代码

void InsertSort(int a[], int n) {

    int i, j, temp;

    for (i = 1; i < n; ++i) {

        temp = a[i]; //先保存当前值

        for (j = i-1; j >= 0 && temp < a[j]; --j) //从后往前移,直到找到适合位置

            a[j+1] = a[j]; //往后移一位,腾出位置

        a[j+1] = temp; //将值放入已找出的适当位置

    }

}








②希尔排序

1思想:希尔排序也是一种插入排序方法,实际上是一种分组插入方法。先取定一个小于n的整数d1作为第一个增量,把表的全部记录分成d1个组,所有距离为d1的倍数的记录放在同一个组中,在各组内进行直接插入排序;然后,取第二个增量d2(d1),重复上述的分组和排序,直至所取的增量dt=1(dt<dt-1<…<d2<d1),即所有记录放在同一组中进行直接插入排序为止。      

     例如:将 n 个记录分成 d 个子序列:
       { R[0]
   R[d]     R[2d]     R[kd] }
       { R[1]
   R[1+d] R[1+2d]R[1+kd] }
         …
       { R[d-1]
R[2d-1]R[3d-1]R[(k+1)d-1] }

    
    
说明:d=5 时,先从A[d]开始向前插入,判断A[d-d],然后A[d+1]A[(d+1)-d]比较,如此类推,这一回合后将原序列分为d个组。<由后向前>


     2时间复杂度。 
    
最好情况:由于希尔排序的好坏和步长d的选择有很多关系,因此,目前还没有得出最好的步长如何选择(现在有些比较好的选择了,但不确定是否是最好的)。所以,不知道最好的情况下的算法时间复杂度。  

     最坏情况下O(N*logN),最坏的情况下和平均情况下差不多。  

     平均情况下O(N*logN)

     3稳定性  

希尔排序是按照不同步长对元素进行插入排序,当刚开始元素很无序的时候,步长最大,所以插入排序的元素个数很少,速度很快;当元素基本有序了,步长很小,插入排序对于有序的序列效率很高。所以,希尔排序的时间复杂度会比o(n^2)好一些。由于多次插入排序,我们知道一次插入排序是稳定的,不会改变相同元素的相对顺序,但在不同的插入排序过程中,相同的元素可能在各自的插入排序中移动,最后其稳定性就会被打乱,所以shell排序是不稳定的。

4、c语言代码

void ShellSort(int a[],int n){    /*希尔排序算法*/

    int d,j;

    int temp;

    d = n / 2;              /*d取初始值n/2*/

    while (d > 0) {

        for (int i = d; i < n; i ++) {

            j = i - d;

             temp = a[i];

            while ( j >= 0 && temp < a[j]) { /*将a[d...n-1]分别插入有序区*/

                a[j+d] = a[j];

                j = j - d;

            }

            a[j + d] = temp;

        }

        d = d / 2;  /*递减增量d*/

    }

}





2.第二类——交换排序法:冒泡、快排(由冒泡改进而来)。以及不常见的鸡尾酒排序、奇偶排序、梳排序、Gnome sort 。

①冒泡排序

1基本思想

在要排序的一组数中,对当前还未排好序的范围内的全部数,自上而下对相邻的两个数依次进行比较和调整,让较大的数往下沉,较小的往上冒。即:每当两相邻的数比较后发现它们的排序与排序要求相反时,就将它们互换。

冒泡排序的示例:

 

      2时间复杂度 
    
最好情况下:正序有序,则只需要比较n次。故,为O(n)  

      最坏情况下逆序有序,则需要比较(n-1)+(n-2)+……+1,故,为O(N*N)

      3稳定性  

冒泡排序就是把小的元素往前调或者把大的元素往后调。比较是相邻的两个元素比较,交换也发生在这两个元素之间。所以,如果两个元素相等,我想你是不会再无聊地把他们俩交换一下的;如果两个相等的元素没有相邻,那么即使通过前面的两两交换把两个相邻起来,这时候也不会交换,所以相同元素的前后顺序并没有改变,所以冒泡排序是一种稳定排序算法。

4、C语言代码

void BubbleSort(int a[], int n) {

    for (int i = 0; i < n; i++) //遍历n次

        for (int j = 1; j < n - i; j++) {

            if (a[j] < a[j-1]) { //当前比较前面键值,使当前总为最小的

                int temp = a[j - 1];//交换

                a[j - 1] = a[j];

                a[j] = temp;

            }

        }

}



②简单快排

 1思想:它是由冒泡排序改进而来的。在待排序的n个记录中任取一个记录(通常取第一个记录),把该记录放入适当位置后,数据序列被此记录划分成两部分。所有关键字比该记录关键字小的记录放置在前一部分,所有比它大的记录放置在后一部分,并把该记录排在这两部分的中间(称为该记录归位),这个过程称作一趟快速排序。

1)选择一个基准元素,通常选择第一个元素或者最后一个元素,

2)通过一趟排序讲待排序的记录分割成独立的两部分,其中一部分记录的元素值均比基准元素值小。另一部分记录的 元素值比基准值大。

3)此时基准元素在其排好序后的正确位置

4)然后分别对这两部分记录用同样的方法继续进行排序,直到整个序列有序。

快速排序的示例:

(a)一趟排序的过程:

(b)排序的全过程


           说明:最核心的思想是将小的部分放在左边,大的部分放到右边,实现分割。        
     2
、算法复杂度 
     
最好的情况下:因为每次都将序列分为两个部分(一般二分都复杂度都和logN相关),故为 O(N*logN)  

      最坏的情况下:基本有序时,退化为冒泡排序,几乎要比较N*N次,故为O(N*N)

      3、稳定性 
     
快速排序有两个方向,左边的i下标一直往右走,当a[i] <= a[center_index],其中center_index是中枢元素的数组下标,一般取为数组第0个元素。而右边的j下标一直往左走,当a[j] > a[center_index]。如果i和j都走不动了,i <= j, 交换a[i]和a[j],重复上面的过程,直到i>j。 交换a[j]和a[center_index],完成一趟快速排序。在中枢元素和a[j]交换的时候,很有可能把前面的元素的稳定性打乱,比如序列为 5 3 3 4 3 8 9 10 11, 现在中枢元素5和3(第5个元素,下标从1开始计)交换就会把元素3的稳定性打乱,所以快速排序是一个不稳定的排序算法,不稳定发生在中枢元素和a[j]交换的时刻。

      4、代码(c


int Partition(int a[], int left, int right) {

    int base = a[left];

    while (left < right) {

        while (left < right && a[right]>base) //从右往左找出第一个比基准小的数据

            --right;

        a[left] = a[right]; //将这个数放到基准的左边

        while (left < right && a[left]<base) //从左往右找出第一个比基准大的数据

            ++left;

        a[right] = a[left]; //放到右边

    }

    a[left] = base;

    return left; //返回基准的位置

}

void  QuickSort(int a[], int left, int right) {

    int i;

    if (left < right) {

        i = Partition(a, left, right);

        QuickSort(a, left, i-1);

        QuickSort(a, i+1, right);

    }

}








3.第三类——选择排序法:简单选择、堆排序。

①简单选择排序

1思想:在要排序的一组数中,选出最小(或者最大)的一个数与第1个位置的数交换;然后在剩下的数当中再找最小(或者最大)的与第2个位置的数交换,依次类推,直到第n-1个元素(倒数第二个数)和第n个元素(最后一个数)比较为止。

简单选择排序的示例:

 

操作方法:

第一趟,从n 个记录中找出关键码最小的记录与第一个记录交换;

第二趟,从第二个记录开始的n-1 个记录中再选出关键码最小的记录与第二个记录交换;

以此类推.....

第i 趟,则从第i 个记录开始的n-i+1 个记录中选出关键码最小的记录与第i 个记录交换,

直到整个序列按关键码有序。      2时间复杂度。
     
最好情况下:交换0次,但是每次都要找到最小的元素,因此大约必须遍历N*N次,因此为O(N*N)。减少了交换次数! 

      最坏情况下,平均情况下O(N*N)

      3稳定性 

选择排序是给每个位置选择当前元素最小的,比如给第一个位置选择最小的,在剩余元素里面给第二个元素选择第二小的,依次类推,直到第n-1个元素,第n个元素不用选择了,因为只剩下它一个最大的元素了。那么,在一趟选择,如果当前元素比一个元素小,而该小的元素又出现在一个和当前元素相等的元素后面,那么交换后稳定性就被破坏了。比较拗口,举个例子,序列5 8 5 2 9, 我们知道第一遍选择第1个元素5会和2交换,那么原序列中2个5的相对前后顺序就被破坏了,所以选择排序不是一个稳定的排序算法。

4代码(c)

void SelectSort(int a[], int n){

    

    for (int i = 0; i < n; i ++) {

        int minIndex = i;

        for (int j = i + 1; j < n; j ++) {

            

            if (a[minIndex] > a[j]) {

                minIndex = j;

            }

        }

        int temp = a[i];

        a[i] = a[minIndex];

        a[minIndex] = temp;

        

    }

    

}







②堆排序

1思想:利用完全二叉树中双亲节点和孩子节点之间的内在关系,在当前无序区中选择关键字最大(或者最小)的记录。也就是说,以最小堆为例,根节点为最小元素,较大的节点偏向于分布在堆底附近。  


      2算法复杂度
        
最坏情况下,接近于最差情况下:O(N*logN),因此它是一种效果不错的排序算法。

      3稳定性
        
我们知道堆的结构是节点i的孩子为2*i和2*i+1节点,大顶堆要求父节点大于等于其2个子节点,小顶堆要求父节点小于等于其2个子节点。在一个长为n的序列,堆排序的过程是从第n/2开始和其子节点共3个值选择最大(大顶堆)或者最小(小顶堆),这3个元素之间的选择当然不会破坏稳定性。但当为n/2-1, n/2-2, ...1这些个父节点选择元素时,就会破坏稳定性。有可能第n/2个父节点交换把后面一个元素交换过去了,而第n/2-1个父节点把后面一个相同的元素没有交换,那么这2个相同的元素之间的稳定性就被破坏了。所以,堆排序不是稳定的排序算法

  4、代码(c

void HeapAdjust(int a[], int s, int n)//构成堆

{

    int j;

    while(2*s + 1 < n) //第s个结点有右子树

    {

        j=2*s + 1 ;

        if((j+1) < n)

        {

            if(a[j] < a[j+1])//右左子树小于右子树,则需要比较右子树

                j++; //序号增加1,指向右子树

        }

        if(a[s] < a[j])//比较s与j为序号的数据

        {

            // swap(a[s], a[j]);

            

            int temp;

            temp = a[s];

            a[s] = a[j];

            a[j] = temp;

            s = j ;//堆被破坏,需要重新调整

        }

        else //比较左右孩子均大则堆未破坏,不再需要调整

            break;

    }

}

void HeapSort(int a[],int n)//堆排序

{

    int i;

    for(i = n/2 - 1; i >= 0; i--)    //将a[0,n-1]建成大根堆

        HeapAdjust(a, i, n);

    for(i = n-1; i > 0; i--)

    {

        //        swap(a[0], a[i]);

        int temp;

        temp = a[0];

        a[0] = a[i];

        a[i] = temp;

        HeapAdjust(a, 0, i);        //将a[0]至a[i]重新调整为堆

    }

}





4.第四类——归并排序法:归并排序。以及不常见的Strand sort。

①归并排序

1思想:多次将两个或两个以上的有序表合并成一个新的有序表。   


       2算法时间复杂度
         
最好的情况下:一趟归并需要n次,总共需要logN次,因此为O(N*logN) 

          最坏的情况下,接近于平均情况下,为O(N*logN) 

          说明:对长度为n的文件,需进行logN 趟二路归并,每趟归并的时间为O(n),故其时间复杂度无论是在最好情况下还是在最坏情况下均是O(nlgn)

      3稳定性
        
归并排序是把序列递归地分成短序列,递归出口是短序列只有1个元素(认为直接有序)或者2个序列(1次比较和交换),然后把各个有序的段序列合并成一个有序的长序列,不断合并直到原序列全部排好序。可以发现,在1个或2个元素时,1个元素不会交换,2个元素如果大小相等也没有人故意交换,这不会破坏稳定性。那么,在短的有序序列合并的过程中,稳定是是否受到破坏?没有,合并过程中我们可以保证如果两个当前元素相等时,我们把处在前面的序列的元素保存在结果序列的前面,这样就保证了稳定性。所以,归并排序也是稳定的排序算法。 

      4、缺点是,它需要O(n)的额外空间。但是很适合于多链表排序。

5c语言代码

//将2个有序数组a[first...mid]和a[mid+1...last]数组和合并

void mergearray(int a[],int first,int mid,int last, int temp[]){

    int i = first,j = mid+1;

    int m = mid,n = last;

    int k = 0;

    

    //通过循环将2个数组比较后有序的放入到临时数组temp中

    while (i<=m && j<=n) {

        if (a[i] <= a[j]) {

            temp[k++] = a[i++];

        } else {

            temp[k++] = a[j++];

        }

    }

    while (i<=m) {

        temp[k++] = a[i++];

    }

    while (j<=n) {

        temp[k++] = a[j++];

    }

    //将排好序的临时数组重新放置到原数组a中

    for (i=0;i<k;i++) {

        a[first+i] = temp[i];

    }


}


//使用递归将数组a变成若干有序的小的数组

void MergedSort(int a[],int first,int last,int temp[])

{

    if(first < last)

    {

        int mid = (first+last)/2;

        MergedSort(a, first, mid, temp); //左边有序

        MergedSort(a, mid+1, last, temp);//右边有序

        mergearray(a, first, mid, last, temp);

    }

}


//使用归并排序

bool MergSort(int a[],int n)

{

//    int *p = new int[n];

//    if(p==NULL) return false;

    int p [n];

    MergedSort(a, 0, n-1, p);

//    delete [] p;

    return true;

}

(二)非基于比较的排序算法:


基数、计数、桶排序。

①基数排序

1思想:它是一种非比较排序。它是根据位的高低进行排序的,也就是先按个位排序,然后依据十位排序……以此类推。示例如下: 



  

        2算法的时间复杂度
      
分配需要O(n),收集为O(r),其中r为分配后链表的个数,以r=10为例,则有09这样10个链表来将原来的序列分类。而d,也就是位数(如最大的数是1234,位数是4,则d=4),即"分配-收集"的趟数。因此时间复杂度为O(d*(n+r))

       3稳定性
         
基数排序过程中不改变元素的相对位置,因此是稳定的!

       4适用情况:如果有一个序列,知道数的范围(比如11000),用快速排序或者堆排序,需要O(N*logN),但是如果采用基数排序,则可以达到O(4*(n+10))=O(n)的时间复杂度。算是这种情况下排序最快的!!

5、c语言代码

/********************************************************

 *函数名称:GetNumInPos

 *参数说明:num 一个整形数据

 *   pos 表示要获得的整形的第pos位数据

 *说明:    找到num的从低到高的第pos位的数据

 *********************************************************/

int GetNumInPos(int num,int pos)

{

    int temp = 1;

    for (int i = 0; i < pos - 1; i++)

        temp *= 10;

    

    return (num / temp) % 10;

}


/********************************************************

 *函数名称:RadixSort

 *参数说明:pDataArray 无序数组;

 *   iDataNum为无序数据个数

 *说明:    基数排序

 *********************************************************/

#define RADIX_10 10    //整形排序

#define KEYNUM_31 10     //关键字个数,这里为整形位数

void RadixSort(int* pDataArray, int iDataNum)

{

    int *radixArrays[RADIX_10];    //分别为0~9的序列空间

    for (int i = 0; i < 10; i++)

    {

        radixArrays[i] = (int *)malloc(sizeof(int) * (iDataNum + 1));

        radixArrays[i][0] = 0;    //index为0处记录这组数据的个数

    }

    

    for (int pos = 1; pos <= KEYNUM_31; pos++)    //从个位开始到31位

    {

        for (int i = 0; i < iDataNum; i++)    //分配过程

        {

            int num = GetNumInPos(pDataArray[i], pos);

            int index = ++radixArrays[num][0];

            radixArrays[num][index] = pDataArray[i];

        }

        

        for (int i = 0, j =0; i < RADIX_10; i++)    //收集

        {

            for (int k = 1; k <= radixArrays[i][0]; k++)

                pDataArray[j++] = radixArrays[i][k];

            radixArrays[i][0] = 0;    //复位

        }

    }

}

②计数排序

void  CountSort(int *arr, int num)

{

    int mindata = arr[0];

    int maxdata = arr[0];

    for (int i = 1; i < num; i++)

    {

        if (arr[i] > maxdata)

            maxdata = arr[i];

        if (arr[i] < mindata)

            mindata = arr[i];

    }

    

    int size = maxdata - mindata + 1;

    //申请空间并初始化为0

    int *pCount = (int *)malloc(sizeof(int) * size);

    memset(pCount, 0, sizeof(int)*size);

    

    //记录排序计数,每出现一次在对应位置加1

    for (int i = 0; i < num; i++)

        ++pCount[arr[i]-mindata];

    

    //确定不比该位置大的数据个数

    for (int i = 1; i < size; i++)

        pCount[i] += pCount[i - 1]; //加上前一个的计数

    

    int *pSort = (int *)malloc(sizeof(int) * num);

    memset((char*)pSort, 0, sizeof(int) * num);

    

    //从末尾开始拷贝是为了重复数据首先出现的排在前面,即稳定排序

    for (int i = num - 1; i >= 0; i--)

    {

        //包含自己需要减1,重复数据循环回来也需要减1

        --pCount[arr[i]-mindata];

        pSort[pCount[arr[i]-mindata]] = arr[i];

    }

    //拷贝到原数组

    for (int i = 0; i < num; i++)

        arr[i] = pSort[i];

    

    free(pCount);

    free(pSort);

    

}









总结

各种排序的稳定性,时间复杂度和空间复杂度总结:



 我们比较时间复杂度函数的情况:

时间复杂度函数O(n)的增长情况



所以对n较大的排序记录。一般的选择都是时间复杂度为O(nlog2n)的排序方法。

时间复杂度来说:

(1)平方阶(O(n2))排序   各类简单排序:直接插入、直接选择和冒泡排序;  (2)线性对数阶(O(nlog2n))排序   快速排序、堆排序和归并排序;  (3)O(n1+§))排序,§是介于0和1之间的常数。

       希尔排序 (4)线性阶(O(n))排序   基数排序,此外还有桶、箱排序。

说明:

当原表有序或基本有序时,直接插入排序和冒泡排序将大大减少比较次数和移动记录的次数,时间复杂度可降至O(n);

而快速排序则相反,当原表基本有序时,将蜕化为冒泡排序,时间复杂度提高为O(n2);

原表是否有序,对简单选择排序、堆排序、归并排序和基数排序的时间复杂度影响不大。

 

稳定性:

排序算法的稳定性:若待排序的序列中,存在多个具有相同关键字的记录,经过排序, 这些记录的相对次序保持不变,则称该算法是稳定的;若经排序后,记录的相对 次序发生了改变,则称该算法是不稳定的。       稳定性的好处:排序算法如果是稳定的,那么从一个键上排序,然后再从另一个键上排序,第一个键排序的结果可以为第二个键排序所用。基数排序就是这样,先按低位排序,逐次按高位排序,低位相同的元素其顺序再高位也相同时是不会改变的。另外,如果排序算法稳定,可以避免多余的比较;

稳定的排序算法:冒泡排序、插入排序、归并排序和基数排序

不是稳定的排序算法:选择排序、快速排序、希尔排序、堆排序

 

选择排序算法准则:

每种排序算法都各有优缺点。因此,在实用时需根据不同情况适当选用,甚至可以将多种方法结合起来使用。

选择排序算法的依据

影响排序的因素有很多,平均时间复杂度低的算法并不一定就是最优的。相反,有时平均时间复杂度高的算法可能更适合某些特殊情况。同时,选择算法时还得考虑它的可读性,以利于软件的维护。一般而言,需要考虑的因素有以下四点:

1.待排序的记录数目n的大小;

2.记录本身数据量的大小,也就是记录中除关键字外的其他信息量的大小;

3.关键字的结构及其分布情况;

4.对排序稳定性的要求。

设待排序元素的个数为n.

1)当n较大,则应采用时间复杂度为O(nlog2n)的排序方法:快速排序、堆排序或归并排序序。

   快速排序:是目前基于比较的内部排序中被认为是最好的方法,当待排序的关键字是随机分布时,快速排序的平均时间最短;        堆排序 :  如果内存空间允许且要求稳定性的,

       归并排序:它有一定数量的数据移动,所以我们可能过与插入排序组合,先获得一定长度的序列,然后再合并,在效率上将有所提高。

2)  当n较大,内存空间允许,且要求稳定性 =》归并排序

3)当n较小,可采用直接插入或直接选择排序。

    直接插入排序:当元素分布有序,直接插入排序将大大减少比较次数和移动记录的次数。

    直接选择排序 :元素分布有序,如果不要求稳定性,选择直接选择排序

5)一般不使用或不直接使用传统的冒泡排序。

6)基数排序 它是一种稳定的排序算法,但有一定的局限性:   1、关键字可分解。   2、记录的关键字位数较少,如果密集更好   3、如果是数字时,最好是无符号的,否则将增加相应的映射复杂度,可先将其正负分开排序。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
排序算法中,时间复杂度是评估算法性能的重要指标。根据引用和引用的内容,下面是一些常见排序算法的时间复杂度汇总: 1. 冒泡排序:冒泡排序是一种简单但效率较低的排序算法。最坏情况下,冒泡排序的时间复杂度是O(n^2),其中n是待排序元素的数量。最好情况下,当数据已经有序时,冒泡排序的时间复杂度是O(n)。 2. 插入排序:插入排序算法根据待排序序列中的元素逐个插入已排序序列的合适位置。最坏情况下,插入排序的时间复杂度也是O(n^2)。最好情况下,当数据已经有序时,插入排序的时间复杂度是O(n)。 3. 选择排序:选择排序是一种简单的排序算法,每次从未排序的部分选择最小(或最大)的元素,然后放到已排序部分的末尾。选择排序的时间复杂度始终为O(n^2),无论数据是否有序。 4. 快速排序:快速排序是一种高效的排序算法,基于分治的思想。最坏情况下,快速排序的时间复杂度是O(n^2),但通常情况下,快速排序的平均时间复杂度是O(nlogn)。 5. 归并排序:归并排序是一种稳定且高效的排序算法,基于分治和合并的思想。归并排序的时间复杂度始终为O(nlogn),无论数据是否有序。 综上所述,不同的排序算法其时间复杂度不同。冒泡排序和插入排序的时间复杂度是O(n^2),选择排序的时间复杂度也是O(n^2),而快速排序和归并排序的时间复杂度是O(nlogn)。请注意,这些时间复杂度都是在最坏情况下估计的。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值