排序
1.交换排序
1.1冒泡排序
冒泡排序的时间复杂度是O(n^2)。基本思路是,未排序元素两两比较并交换,选出最大(小)的元素放到已排序元素区的头部。
冒泡排序有两个可以优化的点:
1)在某轮排序中,如果一次交换都没有发生,说明序列已经排好序,可以直接退出排序了;
2)在某轮排序中,如果某次交换后(设交换发生在array[boundIndex]和array[boundIndex+1]),后面的一系列比较都没有发生交换,则说明下标大于boundIndex的元素都排好序了,下轮排序只需要排下标为0-boundIndex的元素。
1.2快速排序
快速排序的时间复杂度为O(nlogn)。因为每轮比较都需要遍历n个元素,比较的总轮数是logn(n/2^{logn}=1)。
快速排序每一轮的步骤是:
1)选出数组的第一个元素为pivot,第二个元素为leftPointer,最后一个元素为rightPointer;
2)两个指针依次向中间遍历,如果rightPointer发现异常的元素(小于等于pivot)指针就停下来,和另一个指针发现的异常元素(大于pivot)进行交换。
3)当两个指针指向同一个元素,遍历结束。将pivot设置为两个指针指向的同一个元素,然后递归排序pivot左边的元素和右边的元素,重复步骤1)。
1.3堆排序
1)将数组重整为一个二叉堆。如果需要升序就重整成最大二叉堆,需要降序就重整成最小二叉堆;
2)堆顶元素和二叉堆的最后一个元素交换位置,同时对二叉堆进行下降操作(下降范围不包括原来的堆顶元素)。
3)重复2)N-1次。
2.计数排序
计数排序的时间复杂度是O(n),具体步骤分以下4个:
1)找出数组array的最大值max和最小值min;
2)创建一个统计数组countArray,countArray的长度为max-min+1,countArray[i]存储array中的满足value-min=i的元素;
3)将countArray的第i(i>=2)个元素依次重新赋值为第i-1个元素值+第i个元素值。完成这个步骤之后,countArray[i]-1就代表了array中满足value-min=i的最后一个元素在排好序的数组中存放的下标。
4)从后往前遍历array(这是保证稳定排序的关键),countArray[array[i]-min]-1就代表array[i]在sortedArray中的下标。
计数排序虽然时间复杂度很低,但是应用的很少,因为它在以下两个场景中无法使用:
1)当原始数组的排布过于稀疏,例如:原始数组总共100个元素,但最大值为一百万,最小值却只有1。这时如果用计数排序,将浪费大量空间,而且也很耗时;
2)当原始数组的元素不是整数。
public class CountSort { public int[] countSort(int[] array){ //1.先求出原始数组的最大值和最小值 int max = array[0]; int min = array[0]; int len = array.length; for(int i=1;i<len;i++){ if(array[i]>max){ max = array[i]; } if(array[i]<min){ min = array[i]; } } //2.计算countArray的元素值 int[] countArray = new int[max-min+1]; for(int i=0;i<len;i++){ countArray[array[i]-min]++; } //3.将countArray中的元素值变为原始数组中元素在排序后的位次 for(int i=1;i<(max-min+1);i++){ countArray[i] += countArray[i-1]; } //4.将原始数组中的值放到它应该去的位置,注意从后往前遍历是保证稳定排序的关键 int[] sortedArray = new int[len]; for(int i=len-1;i>=0;i--){ sortedArray[countArray[array[i]-min]-1] = array[i]; countArray[array[i]-min]--; } return sortedArray; } }
3. 桶排序
桶排序是为了解决计数排序不能处理非整数序列的缺点。桶排序的时间复杂度为O(n),具体步骤如下:
1)设置一个arrayList,元素类型为链表,这个arrayList的长度为原始数组的长度。arrayList的最后一个桶只存放最大值;
2)获取原始数组的最大值max和最小值min,求除最后一个桶之外的其他桶的区间长度:d=(max-min)/(arrayList.lenth-1);
3)遍历原始数组array,将array[i]存放进第(array[i]-min)/d+1个桶;
4)对每个桶进行归并排序,时间复杂度为O(nlogn);
5)从前往后依次遍历每个桶,得到升序数组,也可以从后往前依次遍历每个桶,得到降序数组。

浙公网安备 33010602011771号