快速排序,归并排序,堆排序,冒泡排序
属于比较排序。在排序的最终结果里,元素之间的次序依赖于他们之间的比较,每个数都必须和其他数进行比较才能确定自己的位置。
比较排序的优势是,适用于各种规模的数据,也不在乎数据的分布,都能进行排序
。
计数排序、基数排序、桶排序
则属于非比较排序。**非比较排序是通过确定每个元素之前,应该有多少个元素来排序。**针对数组arr,计算arr[i]之前有多少个元素,则唯一确定了arr[i]在排序后数组中的位置。
非比较排序只要确定每个元素之前的已有的元素个数即可,所有一次遍历即可解决
。
冒泡排序
这个算法的名字由来是因为越小的元素会经由交换慢慢“浮”到数列的顶端。
public static int[] bubble(int[] arr){
for(int i = 0;i < arr.length;i++){
for(int j = 0;j<arr.length-1-i;j++){
if(arr[j] > arr[j+1]){
int tmp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = tmp;
}
}
}
return arr;
}
选择排序
表现最稳定的排序算法之一,因为无论什么数据进去都是O(n2)的时间复杂度。所以用到它的时候,数据规模越小越好。
它的工作原理:首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。
public static int[] selectionSort(int[] arr){
for(int i = 0;i < arr.length;i++){
int minInex = i;
for(int j = i;j<arr.length;j++){
if(arr[j] < arr[minInex]){
minInex = j;
}
}
if(minInex != i){
int tmp = arr[i];
arr[i] = arr[minInex];
arr[minInex] = tmp;
}
}
return arr;
}
插入排序
工作原理是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。
在从后向前扫描过程中,需要反复把已排序元素逐步向后挪位,为最新元素提供插入空间。
public static int[] insertSort(int[] arr){
for(int i = 0;i < arr.length-1;i++){
int current = arr[i+1];
int index = i;
while(index >=0 && current < arr[index]){
arr[index+1] = arr[index];
index--;
}
}
return arr;
}
希尔排序
希尔排序也是一种插入排序,它是简单插入排序经过改进之后的一个更高效的版本。
它与插入排序的不同之处在于,它会优先比较距离较远的元素。
public static int[] shellSort(int[] arr){
//!!!
int len = arr.length;
int gap = len/2;
while(gap > 0){
for(int i = gap;i < len;i++){
int tmp = arr[i];
int index = i - gap;
while(index >= 0 && arr[index] > tmp){
arr[index + gap] = arr[index];
index -= gap;
}
arr[index+gap] = tmp;
}
gap/=2;
}
return arr;
}
归并排序
和选择排序一样,归并排序的性能不受输入数据的影响,但表现比选择排序好的多,代价是需要额外的内存空间。
代价是需要额外的内存空间。
将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表。
public static int[] MergeSort(int[] arr){
if(arr.length < 2)return arr;
int mid = arr.length/2;
int[] left = Arrays.copyOfRange(arr,0,mid);
int[] right = Arrays.copyOfRange(arr,mid,arr.length);
return merge(MergeSort(left),MergeSort(right));
}
public static int[] merge(int[] left,int[] right){
int[] ans = new int[left.length+right.length];
for(int index = 0,i = 0,j = 0;index < ans.length;index++){
if(i >= left.length){
ans[index] = right[j++];
}else if(j >= right.length){
ans[index] = left[i++];
}else if(left[i] >right[j]){
ans[index] = right[j++];
}else{
ans[index] = left[i++];
}
}
return ans;
}
快速排序
通过一趟排序将待排记录分隔成独立的两部分,其中一部分记录的关键字均比另一部分的关键字小,则可分别对这两部分记录继续进行排序
public static void QuickSort(int[] arr,int low ,int high){
//if(arr.length < 1 || low < 0 || high > arr.length || low > high )return null;
if(low <high){
int pos = partion(arr,low,high);
QuickSort(arr,low,pos-1);
QuickSort(arr,pos+1,high);
}
}
public static int partion(int[] arr,int low,int high){
int poss = arr[low];
while(low < high){
while(low < high && arr[high] >= poss)high--;
arr[low] = arr[high];
while(low < high && arr[low] <= poss)low++;
arr[high] = arr[low];
}
arr[low] = poss;
return low;
}
堆排序
public static void heapAdjust(int[] arr,int index,int length){
int maxx = index;//保存当前结点下标
int lchild = 2*index;
int rchild = 2*index+1;
if(length > lchild && arr[maxx] < arr[lchild]){
maxx = lchild;
}
if(lchild > rchild && arr[maxx] < arr[rchild]){
maxx = rchild;
}
if(maxx != index){
int tmp = arr[index];
arr[index] = arr[maxx];
arr[maxx] = tmp;
heapAdjust(arr,maxx,length);
}
}
public static int[] heapSort(int[] arr){
int len = arr.length;
for(int i = (len/2-1);i>=0;i--){
heapAdjust(arr,i,len);
}
for(int i = len-1;i > 0;i--){
int tmp = arr[i];
arr[i] = arr[0];
arr[0] = tmp;
heapAdjust(arr,0,i);
}
return arr;
}
计数排序
计数排序的核心在于将输入的数据值转化为键存储在额外开辟的数组空间中。
计数排序要求输入的数据必须是有确定范围的整数。
是一种稳定的排序算法。计数排序使用一个额外的数组C,其中第i个元素是待排序数组A中值等于i的元素的个数,然后根据数组C来将A中的元素排到正确的位置。它只能对整数进行排序。
public static int[] countingSort(int[] arr){
if(arr.length == 0){
return arr;
}
int min = arr[0],max = arr[0];
int bias;
for(int i = 0;i < arr.length;i++){
if(arr[i] < min){
min = arr[i];
}
if(arr[i] > max){
max = arr[i];
}
}
bias = 0 - min;
int[] bucket = new int[max-min+1];
Arrays.fill(bucket,0);
for(int i = 0;i < arr.length;i++){
bucket[arr[i]+bias] += 1;
}
int index = 0;
for(int i = 0;i< bucket.length;i++){
int len = bucket[i];
while(len > 0){
arr[index++] = i - bias;
len--;
}
}
return arr;
}
桶排序
桶排序是计数排序的升级版。它利用了函数的映射关系.
工作的原理:假设输入数据服从均匀分布,将数据分到有限数量的桶里,每个桶再分别排序(有可能再使用别的排序算法或是以递归方式继续使用桶排序进行排
/**
*
* @param arr
* @param bucketSize 桶中可以放多少种元素
* @return
*/
public static ArrayList<Integer> BucketSort(ArrayList<Integer> arr,int bucketSize){
if(arr == null || arr.size() < 2){
return arr;
}
int max = arr.get(0),min = arr.get(0);
for(int i = 0 ;i < arr.size();i++){
int cuurent = arr.get(i);
if(cuurent > max){
max = cuurent;
}
if(cuurent < min){
min = cuurent;
}
}
int bucketCount = (max-min)/bucketSize + 1; //范围 (最大值-最小值)/桶的个数+1;
ArrayList<ArrayList<Integer>> bucketArr = new ArrayList<>(bucketCount);
ArrayList<Integer> resultArr = new ArrayList<>();
//构造桶
for(int i = 0;i < bucketCount;i++){
bucketArr.add(new ArrayList<Integer>());
}
for(int i = 0;i < arr.size();i++){
bucketArr.get((arr.get(i)-min)/bucketSize).add(arr.get(i));
}
for(int i = 0;i < bucketCount;i++){
if(bucketSize == 1){
for(int j = 0;j < bucketArr.get(i).size();j++){
resultArr.add(bucketArr.get(i).get(j));
}
}else{
if(bucketCount == 1) {
bucketSize--;
}
ArrayList<Integer> tmp = BucketSort(bucketArr.get(i),bucketSize);
for(int j = 0;j < tmp.size();j++){
resultArr.add(tmp.get(j));
}
}
}
return resultArr;
}
基数排序
基数排序也是非比较的排序算法,基数排序是按照低位先排序,然后收集;再按照高位排序,然后再收集;依次类推,直到最高位。有时候有些属性是有优先级顺序的,先按低优先级排序,再按高优先级排序。
基数排序基于分别排序,分别收集,所以是稳定的
public static int[] RadixSort(int[] arr){
if(arr == null || arr.length < 2){
return arr;
}
int max = arr[0];
for(int i = 1;i< arr.length;i++){
max = Math.max(max,arr[i]);
}
int maxDigit = 0;
while(max != 0){
max/=0;
maxDigit++;
}
int mod = 10,div = 1;
ArrayList<ArrayList<Integer>> bucketList = new ArrayList<ArrayList<Integer>>();
for(int i = 0; i <10 ;i++){
bucketList.add(new ArrayList<Integer>());
}
for(int i = 0;i < maxDigit;i++,mod*=10,div*=10){
for(int j = 0;j <arr.length;j++){
int num = (arr[j]%mod)/div;
bucketList.get(num).add(arr[j]);
}
int index = 0;
for(int j = 0;j <bucketList.size();j++){
for(int k = 0;k < bucketList.get(j).size();k++){
arr[index++] = bucketList.get(j).get(k);
}
bucketList.get(j).clear();;
}
}
return arr;
}