常见的八种经典排序方法
十大经典排序算法总结

⼗⼤经典排序算法总结最近⼏天在研究算法,将⼏种排序算法整理了⼀下,便于对这些排序算法进⾏⽐较,若有错误的地⽅,还请⼤家指正0、排序算法说明0.1 排序术语稳定:如果a=b,且a原本排在b前⾯,排序之后a仍排在b的前⾯不稳定:如果a=b,且a原本排在b前⾯,排序之后排在b的后⾯时间复杂度:⼀个算法执⾏所耗费的时间空间复杂度:⼀个算法执⾏完所需内存的⼤⼩内排序:所有排序操作都在内存中完成外排序:由于数据太⼤,因此把数据放在磁盘中,⽽排序通过磁盘和内存的数据传输才能进⾏0.2算法时间复杂度、空间复杂度⽐较0.3名词解释n:数据规模k:桶的个数In-place:占⽤常数内存,不占⽤额外内存Out-place:占⽤额外内存0.4算法分类1.冒泡排序冒泡排序是⼀种简单的排序算法。
它重复地⾛访过要排序的数列,⼀次⽐较两个元素,如果它们的顺序错误就把它们交换过来。
⾛访数列的⼯作是重复地进⾏直到没有再需要交换,也就是说该数列已经排序完成。
这个算法的名字由来是因为越⼩的元素会经由交换慢慢“浮”到数列的顶端1.1算法描述⽐较相邻的元素,如果前⼀个⽐后⼀个打,就交换对每⼀对相邻元素做同样的⼯作,从开始第⼀对到结尾最后⼀对,这样在最后的元素应该会是最⼤的数针对所有的元素重复以上的步骤,除了最后⼀个重复步骤1-3,知道排序完成1.2动图演⽰1.3代码实现public static int[] bubbleSort(int[] array) {if (array.length == 0)return array;for (int i = 0; i < array.length; i++)for (int j = 0; j < array.length - 1 - i; j++)if (array[j + 1] < array[j]) {int temp = array[j + 1];array[j + 1] = array[j];array[j] = temp;}return array;}1.4算法分析最佳情况:T(n) = O(n) 最差情况:T(n) = O(n2) 平均情况:T(n) = O(n2)2.选择排序表现简单直观的最稳定的排序算法之⼀,因为⽆论什么数据都是O(n2)的时间复杂度,⾸先在未排序序列中找到最⼩(⼤)元素,与数组中第⼀个元素交换位置,作为排序序列的起始位置,然后再从剩余未排序元素中继续寻找最⼩(⼤)的元素,与数组中的下⼀个元素交换位置,也就是放在已排序序列的末尾2.1算法描述1.初始状态:⽆序区为R[1..n],有序区为空2.第i躺排序开始时,当前有序区和⽆序区R[1..i-1]、R[i..n]3.n-1趟结束,数组有序化2.2动图演⽰2.3代码实现public static int[] selectionSort(int[] array) {if (array.length == 0)return array;for (int i = 0; i < array.length; i++) {int minIndex = i;for (int j = i; j < array.length; j++) {if (array[j] < array[minIndex]) //找到最⼩的数minIndex = j; //将最⼩数的索引保存}int temp = array[minIndex];array[minIndex] = array[i];array[i] = temp;}return array;}2.4算法分析最佳情况:T(n) = O(n2) 最差情况:T(n) = O(n2) 平均情况:T(n) = O(n2)3、插⼊排序是⼀种简单直观的排序算法,通过构建有序序列,对于未排序序列,在已排序序列中从后向前扫描,找到相应位置并插⼊,需要反复把已排序元素逐步向后挪位,为最新元素腾出插⼊空间3.1算法描述1.从第⼀个元素开始,该元素可以认为已经被排序2.取出下⼀个元素(h),在已排序的元素序列中从后往前扫描3.如果当前元素⼤于h,将当前元素移到下⼀位置4.重复步骤3,直到找到已排序的元素⼩于等于h的位置5.将h插⼊到该位置6.重复步骤2-53.2动图演⽰3.3代码实现public static int[] insertionSort(int[] array) {if (array.length == 0)return array;int current;for (int i = 0; i < array.length - 1; i++) {current = array[i + 1];int preIndex = i;while (preIndex >= 0 && current < array[preIndex]) {array[preIndex + 1] = array[preIndex];preIndex--;}array[preIndex + 1] = current;}return array;}3.4算法分析最佳情况:T(n) = O(n) 最坏情况:T(n) = O(n2) 平均情况:T(n) = O(n2)4、希尔排序是简单插⼊排序经过改进之后的⼀个更⾼效的版本,也称为缩⼩增量排序,同时该算法是冲破O(n2)的第⼀批算法之⼀。
浅析八大排序的方法有哪些

浅析八大排序的方法有哪些
八大排序方法有以下几种:
1. 冒泡排序(Bubble Sort):重复比较相邻的两个元素,查看是否需要交换,每次将最大(或最小)的元素“冒泡”到顶部(或底部)。
2. 选择排序(Selection Sort):每次从待排序的数据中选出最小(或最大)的元素,放置到已排序位置的最后,直到所有元素排序完成。
3. 插入排序(Insertion Sort):将待排序数据分为已排序和未排序两部分,每次将未排序中第一个元素插入到已排序的合适位置。
4. 希尔排序(Shell Sort):是插入排序的一种改进,先将数据按照一定的步长进行分组,对每组进行插入排序,再逐渐缩小步长,最终步长为1,完成排序。
5. 归并排序(Merge Sort):将待排序的数据递归地分割成较小的子序列,然后再将子序列归并排序,最终得到有序的结果。
6. 快速排序(Quick Sort):选取基准值(一般为待排序数据的第一个元素),将数据分割成两部分,在基准值左边的数据都小于基准值,在右边的数据都大于基准值,然后对左右两部分数据递归地进行快速排序。
7. 堆排序(Heap Sort):将待排序数据构建成一个大(或小)根堆,将堆顶的元素与末尾元素交换,然后对剩余未排序部分进行堆调整,继续交换堆顶与末尾元素,重复上述步骤,直到完成排序。
8. 计数排序(Counting Sort):对于给定的输入序列中的每个元素x,确定小于x的元素个数。
利用这一信息,可以直接确定x在输出序列中的位置,最后按照确定的位置输出元素,即得到有序序列。
以上就是八大排序方法的简要介绍。
不同的排序算法具有不同的时间复杂度和适用场景,具体选择哪种排序算法应根据实际情况进行评估和选择。
各种排序方法总结

选择排序、快速排序、希尔排序、堆排序不是稳定的排序算法,冒泡排序、插入排序、归并排序和基数排序是稳定的排序算法。
冒泡法:这是最原始,也是众所周知的最慢的算法了。
他的名字的由来因为它的工作看来象是冒泡:复杂度为O(n*n)。
当数据为正序,将不会有交换。
复杂度为O(0)。
直接插入排序:O(n*n)选择排序:O(n*n)快速排序:平均时间复杂度log2(n)*n,所有内部排序方法中最高好的,大多数情况下总是最好的。
归并排序:l og2(n)*n堆排序:l og2(n)*n希尔排序:算法的复杂度为n的1.2次幂这里我没有给出行为的分析,因为这个很简单,我们直接来分析算法:首先我们考虑最理想的情况1.数组的大小是2的幂,这样分下去始终可以被2整除。
假设为2的k次方,即k=log2(n)。
2.每次我们选择的值刚好是中间值,这样,数组才可以被等分。
第一层递归,循环n次,第二层循环2*(n/2)......所以共有n+2(n/2)+4(n/4)+...+n*(n/n) = n+n+n+...+n=k*n=log2(n)*n所以算法复杂度为O(lo g2(n)*n) 其他的情况只会比这种情况差,最差的情况是每次选择到的midd le都是最小值或最大值,那么他将变成交换法(由于使用了递归,情况更糟)。
但是你认为这种情况发生的几率有多大??呵呵,你完全不必担心这个问题。
实践证明,大多数的情况,快速排序总是最好的。
如果你担心这个问题,你可以使用堆排序,这是一种稳定的O(log2(n)*n)算法,但是通常情况下速度要慢于快速排序(因为要重组堆)。
最简单的排序

最简单的排序排序是一种常见的操作,可以将一组元素按照一定的规则重新排列,使其达到某种有序的状态。
排序在生活中随处可见,比如我们买菜时,需要将菜按照大小、种类进行整理;在图书馆,图书也是按照编号或者分类进行排序的。
下面我们来介绍几种最简单的排序算法。
1. 冒泡排序冒泡排序是一种简单直观的排序算法,它重复地遍历要排序的元素,比较相邻的两个元素,如果它们的顺序错误就交换位置,直到没有需要交换的元素为止。
这样最大(或最小)的元素就会像气泡一样逐渐升(或降)到最后的位置。
2. 选择排序选择排序是一种简单直观的排序算法,它的工作原理如下:首先在未排序序列中找到最小(或最大)元素,存放到排序序列的起始位置,然后再从剩余未排序元素中继续寻找最小(或最大)元素,放到已排序序列的末尾。
以此类推,直到所有元素均排序完毕。
3. 插入排序插入排序是一种简单直观的排序算法,它的工作原理如下:将数组分成已排序部分和未排序部分,初始时已排序部分只有一个元素,然后将未排序部分的元素逐个插入到已排序部分的合适位置,直到所有元素都被插入到已排序部分为止。
4. 快速排序快速排序是一种高效的排序算法,它的工作原理如下:选择一个基准元素,将大于基准元素的元素放到右边,小于基准元素的元素放到左边,然后再对左右两个子序列分别进行快速排序,直到整个序列有序。
以上是几种最简单的排序算法,它们都有各自的特点和适用场景。
在实际应用中,我们可以根据问题的具体需求选择合适的排序算法。
排序算法的效率也是我们需要考虑的一个重要因素,通常来说,快速排序是效率最高的排序算法之一。
排序是一种常见的操作,可以帮助我们将一组元素按照一定的规则重新排列,使其达到某种有序的状态。
冒泡排序、选择排序、插入排序和快速排序是几种最简单的排序算法,它们都有各自的特点和适用场景。
在实际应用中,我们可以根据问题的具体需求选择合适的排序算法,以提高效率和准确性。
通过学习和掌握这些排序算法,我们可以更好地理解和应用排序的原理和方法。
排序算法十大经典方法

排序算法十大经典方法
排序算法是计算机科学中的经典问题之一,它们用于将一组元素按照一定规则排序。
以下是十大经典排序算法:
1. 冒泡排序:比较相邻元素并交换,每一轮将最大的元素移动到最后。
2. 选择排序:每一轮选出未排序部分中最小的元素,并将其放在已排序部分的末尾。
3. 插入排序:将未排序部分的第一个元素插入到已排序部分的合适位置。
4. 希尔排序:改进的插入排序,将数据分组排序,最终合并排序。
5. 归并排序:将序列拆分成子序列,分别排序后合并,递归完成。
6. 快速排序:选定一个基准值,将小于基准值的元素放在左边,大于基准值的元素放在右边,递归排序。
7. 堆排序:将序列构建成一个堆,然后一次将堆顶元素取出并调整堆。
8. 计数排序:统计每个元素出现的次数,再按照元素大小输出。
9. 桶排序:将数据分到一个或多个桶中,对每个桶进行排序,最后输出。
10. 基数排序:按照元素的位数从低到高进行排序,每次排序只考虑一位。
以上是十大经典排序算法,每个算法都有其优缺点和适用场景,选择合适的算法可以提高排序效率。
【十大经典排序算法(动图演示)】 必学十大经典排序算法

【十大经典排序算法(动图演示)】必学十大经典排序算法0.1 算法分类十种常见排序算法可以分为两大类:比较类排序:通过比较来决定元素间的相对次序,由于其时间复杂度不能突破O(nlogn),因此也称为非线性时间比较类排序。
非比较类排序:不通过比较来决定元素间的相对次序,它可以突破基于比较排序的时间下界,以线性时间运行,因此也称为线性时间非比较类排序。
0.2 算法复杂度0.3 相关概念稳定:如果a原本在b前面,而a=b,排序之后a仍然在b的前面。
不稳定:如果a原本在b的前面,而a=b,排序之后a 可能会出现在b 的后面。
时间复杂度:对排序数据的总的操作次数。
反映当n变化时,操作次数呈现什么规律。
空间复杂度:是指算法在计算机内执行时所需存储空间的度量,它也是数据规模n的函数。
1、冒泡排序(Bubble Sort)冒泡排序是一种简单的排序算法。
它重复地走访过要排序的数列,一次比较两个元素,如果它们的顺序错误就把它们交换过来。
走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。
这个算法的名字由来是因为越小的元素会经由交换慢慢“浮”到数列的顶端。
1.1 算法描述比较相邻的元素。
如果第一个比第二个大,就交换它们两个;对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对,这样在最后的元素应该会是最大的数;针对所有的元素重复以上的步骤,除了最后一个;重复步骤1~3,直到排序完成。
1.2 动图演示1.3 代码实现1.unction bubbleSort(arr) {2. varlen = arr.length;3. for(vari = 0; i arr[j+1]) {// 相邻元素两两对比6. vartemp = arr[j+1];// 元素交换7. arr[j+1] = arr[j];8. arr[j] = temp;9. }10. }11. }12. returnarr;13.}2、选择排序(Selection Sort)选择排序(Selection-sort)是一种简单直观的排序算法。
经典十大排序算法

经典⼗⼤排序算法前⾔排序种类繁多,⼤致可以分为两⼤类:⽐较类排序:属于⾮线性时间排序,时间复杂度不能突破下界O(nlogn);⾮⽐较类排序:能达到线性时间O(n),不是通过⽐较来排序,有基数排序、计数排序、桶排序。
了解⼀个概念:排序的稳定性稳定是指相同⼤⼩的元素多次排序能保证其先后顺序保持不变。
假设有⼀些学⽣的信息,我们先根据他们的姓名进⾏排序,然后我们还想根据班级再进⾏排序,如果这时使⽤的时不稳定的排序算法,那么第⼀次的排序结果可能会被打乱,这样的场景需要使⽤稳定的算法。
堆排序、快速排序、希尔排序、选择排序是不稳定的排序算法,⽽冒泡排序、插⼊排序、归并排序、基数排序是稳定的排序算法。
1、冒泡排序⼤多数⼈学编程接触的第⼀种排序,名称很形象。
每次遍历排出⼀个最⼤的元素,将⼀个最⼤的⽓泡冒出⽔⾯。
时间复杂度:平均:O(n2);最好:O(n);最坏:O(n2)空间复杂度:O(1)public static void bubbleSort(int[] arr) {/*** 总共⾛len-1趟即可,每趟排出⼀个最⼤值放在最后*/for (int i = 0; i < arr.length - 1; i++) {for (int j = 0; j < arr.length - i - 1; j++) {if (arr[j] > arr[j + 1]) {int tp = arr[j];arr[j] = arr[j + 1];arr[j + 1] = tp;}}}}2、选择排序最直观易理解的排序算法,每次排出⼀个最⼩的元素。
也是最稳定的算法,时间复杂度稳定为O(n^2)。
需要⼀个变量记录每次遍历最⼩元素的位置。
时间复杂度:O(n2)空间复杂度:O(1)public static void selectSort(int[] arr){int n = arr.length;for (int i = 0; i < n; i++) {int maxIdx = 0;for(int j = 1; j < n - i; j++){if(arr[maxIdx] < arr[j]){maxIdx = j;}}int tp = arr[maxIdx];arr[maxIdx] = arr[n - 1 - i];arr[n - 1 - i] = tp;}}3、插⼊排序⼀种直观的排序算法,从第⼆个元素开始,每次往前⾯遍历找到⾃⼰该在的位置。
排序方法有哪些

排序方法有哪些在日常生活和工作中,我们经常需要对一些事物或者数据进行排序。
排序是将一组数据按照一定的规则进行排列的过程,它可以帮助我们更清晰地了解事物之间的关系,找到最合适的解决方案。
在实际操作中,有许多不同的排序方法可以使用,每种方法都有其特点和适用场景。
下面将介绍一些常见的排序方法。
1. 冒泡排序。
冒泡排序是一种简单的排序算法,它重复地走访过要排序的数列,一次比较两个元素,如果它们的顺序错误就把它们交换过来。
重复这个过程直到整个数列有序。
冒泡排序的时间复杂度为O(n^2),在数据量较小的情况下比较实用。
2. 选择排序。
选择排序是一种简单直观的排序算法,它的工作原理是每一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,直到全部待排序的数据元素排完。
选择排序的时间复杂度也为O(n^2),但由于不涉及交换操作,所以相对于冒泡排序来说性能上会更好一些。
3. 插入排序。
插入排序的工作原理是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。
插入排序的时间复杂度也为O(n^2),但是在实际应用中,当数据规模较小时,插入排序会比选择排序和冒泡排序更加高效。
4. 快速排序。
快速排序是一种分治的排序算法,它的基本思想是通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。
快速排序的时间复杂度为O(nlogn),在大多数情况下都比前面介绍的排序方法要快。
5. 归并排序。
归并排序是一种稳定的排序算法,它的基本思想是将两个有序的子序列合并成一个有序序列。
归并排序的时间复杂度也为O(nlogn),并且由于其稳定性和适用于大规模数据的特点,因此在实际应用中得到了广泛的应用。
6. 堆排序。
堆排序是一种树形选择排序,它的基本思想是利用堆这种数据结构来进行排序。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
*置移到数组最后一个元素时排序结束(此时基准左边所有元素
*均递增有序,而基准为最后一个元素,故完成排序)。
*/
void Selectsort(int A[],int n)
{
int i,j,min,temp;
for(i=0;i<n;i++)
data[1]=data[i];
data[i]=temp;
HeapAdjust(data,1,i-1);
}
}
void HeapAdjust(int data[],int s,int m) /*排列成堆的形式*/
{
int j,rc;
rc=data[s]; /*保存处理元素*/
for(j=2*s;j<=m;j*=2) /*处理父亲元素*/
{
if(j<m && data[j]<data[j+1]) ++j; /*取较大的孩子节点*/
{
int mid;
data[0]=data[low];
mid=data[low];
while(low < high)
{
while((low < high) && (data[high] >= mid))
{
--high;
}
data[low]=data[high]; /*从high的位置开始往low的方向找,找到比data[low]小的元素,存到data[low]中*/
常见经典排序算法
1.希尔排序
2.二分插入法
3.直接插入法
4.带哨兵的直接排序法
5.冒泡排序
6.选择排序
7.快速排序
8.堆排序
一.希尔(Shell)排序法(又称宿小增量排序,是1959年由D.L.Shell提出来的)
/* Shell排序法*/
#include <stdio.h>
void sort(int v[],int n)
*堆的定义n个元素的序列{k1,k2,...,kn}当且仅当满足下列关系时,
*称为堆:
* ki<=k2i ki<=k2i+1 (i=1,2,...,n/2)
*或
* ki>=k2i ki>=k2i+1 (i=1,2,...,n/2)
*堆排序思路:
*建立在树形选择排序基础上;
*将待排序列建成堆(初始堆生成)后,序列的第一个元素(堆顶元素)就一定是序列中的最大元素;
*自身进行比较,很明显这个时候说明位置i之前的数字都比input[i]小
*位置i上的数字不需要移动,直接进入下一轮的插入比较。
*
*/
void InsertionSortWithPiquet(int input[],int len)
{
int i,j;
for (i = 2; i < len; i++) /*保证数组input第一元素的存储数据无效,从第二个数据开始与它前面的元素比较*/
{
temp = a[i];/*保存但前元素*/
low = 0;
high = i-1;
while (low <= high) /*在a[low...high]中折半查找有序插入的位置*/
{
mid = (low + high) / 2; /*找到中间元素*/
if (a[mid] > temp) /*如果中间元素比但前元素大,当前元素要插入到中间元素的左侧*/
*最后将这个刚空出来的位置装入中间值(data[low]=data[0]),
*这样一来比mid大的都会跑到mid的右侧,小于mid的会在左侧,
*最后一行,返回的low是中间元素的位置,左右分别递归就可以排好序了。
*/
int Partition(int data[],int low,int high)
*从a[0:n-1]中选择一个元素作为middle,
,使得left中的元素都小于
*等于支点,而right中的元素都大于等于支点
*递归地使用快速排序方法对left进行排序
*递归地使用快速排序方法对right进行排序
*所得结果为left+middle+right
*将其与序列的最后一个元素交换,将序列长度减一;
*再将序列建成堆(堆调整)后,堆顶元素仍是序列中的最大元素,再次将其与序列最后一个元素交换并缩短序列长度;
*反复此过程,直至序列长度为一,所得序列即为排序后结果。
**************************************************************/
{
min=i;
for(j=i+1;j<=n;j++) /*从j往前的数据都是排好的,所以从j开始往下找剩下的元素中最小的*/
{
if(A[min]>A[j]) /*把剩下元素中最小的那个放到A[i]中*/
{
temp=A[i];
A[i]=A[j];
A[j]=temp;
}
}
}
}
七.快速排序
/*快速排序(quick sort)。在这种方法中,
void Bublesort(int a[],int n)
{
int i,j,k;
for(j=0;j<n;j++) /*气泡法要排序n次*/
{
for(i=0;i<n-j;i++) /*值比较大的元素沉下去后,只把剩下的元素中的最大值再沉下去就可以啦*/
{
if(a[i]>a[i+1]) /*把值比较大的元素沉到底*/
}
}
/*要注意看清楚下面的数据之间是如何替换的,
*首先选一个中间值,就是第一个元素data[low],
*然后从该元素的最右侧开始找到比它小的元素,把
*该元素复制到它中间值原来的位置(data[low]=data[high]),
*然后从该元素的最左侧开始找到比它大的元素,把
*该元素复制到上边刚刚找到的那个元素的位置(data[high]=data[low]),
{
input[j + 1] = input[j]; /*一边找一边移动元素*/
input[j] = temp;
}
}
}
四.带哨兵的直接排序法
/**
*带哨兵的直接插入排序,数组的第一个元素不用于存储有效数据
*将input[0]作为哨兵,可以避免判定input[j]中,数组是否越界
*因为在j--的过程中,当j减小到0时,变成了input[0]与input[0]
{
high = mid-1;
}
else /*如果中间元素比当前元素小,但前元素要插入到中间元素的右侧*/
{
low = mid+1;
}
} /*找到当前元素的位置,在low和high之间*/
for (j=i-1; j>high; j--)/*元素后移*/
{
a[j+1] = a[j];
}
a[high+1] = temp; /*插入*/
}
}
三.直接插入法
/*直接插入法*/
void InsertionSort(int input[],int len)
{
int i,j,temp;
for (i = 1; i < len; i++)
{
temp = input[i]; /*操作当前元素,先保存在其它变量中*/
for (j = i - 1;j>-1&&input[j] > temp ; j--) /*从当前元素的上一个元素开始查找合适的位置*/
* n个元素被分成三段(组):左段left,
*右段right和中段middle。中段
*仅包含一个元素。左段中各元素都小于等
*于中段元素,右段中各元素都大于等于中
*段元素。因此left和right中的元
*素可以独立排序,并且不必对left和
* right的排序结果进行合并。
*使用快速排序方法对a[0:n-1]排序
while((low < high) && (data[low] < mid)) /*新得到的data[low]肯定小于原来的data[low]即mid */
{
++low;
}
data[high]=data[low]; /*从low的位置开始往high的方向找,找到比data[high]大的元素,存在data[high]中*/
{
input[0] = input[i];
for (j = i - 1; input[j] > input[0] ; j--)
{
input[j + 1] = input[j];
input[j] = input[0]; /* input[j]一直都是排序的元素中最大的那一个*/
}
}
}
五.冒泡法
/*冒泡排序法*/
{
int gap,i,j,temp;
for(gap=n/2;gap>0;gap /= 2) /*设置排序的步长,步长gap每次减半,直到减到1 */
{
for(i=gap;i<n;i++) /*定位到每一个元素*/
{
for(j=i-gap;(j >= 0) && (v[j] > v[j+gap]);j -= gap ) /*比较相距gap远的两个元素的大小,根据排序方向决定如何调换*/