Java排序算法以及算法改进总结(计数排序、基数排序、桶排序)
2017-10-16 20:17
836 查看
算法复习,代码是最好的说明!
从前向后,使数组C中的每个值等于其与前一项相加,这样数组C[A[i]]就变成了代表数组A中小于等于A[i]的元素个数
从后向前,填充目标数组B:将数组元素A[i]放在数组B的第C[A[i]]个位置(下标为C[A[i]] - 1),每放一个元素就将C[A[i]]递减
最后将各个子序列连接起来,便可得到一个有序的序列
d为关键字个数,n为待排序元素个数,r为关键字取值基数
再对各组按k2 排序分成子组,之后,对后面的关键码继续这样的排序分组,直到按最次位关键码kd 对各子组排序后。
再将各组连接起来,便得到一个有序序列。
d为关键码个数,n为待排序元素个数,r为关键字取值基数
d为关键码个数,n为待排序元素个数,r为关键字取值基数
参考链接: http://www.cnblogs.com/eniac12/p/5332117.html#s1 http://blog.csdn.net/simongeek/article/details/45202173
如有错误,欢迎指出!
一、计数排序:
算法:
统计数组A中每个值A[i]出现的次数,存入C[A[i]]从前向后,使数组C中的每个值等于其与前一项相加,这样数组C[A[i]]就变成了代表数组A中小于等于A[i]的元素个数
从后向前,填充目标数组B:将数组元素A[i]放在数组B的第C[A[i]]个位置(下标为C[A[i]] - 1),每放一个元素就将C[A[i]]递减
分析:
平均 | 最好 | 最坏 | 辅助存储 | 稳定性 |
O(n+k) | O(n+k) | O(n+k) | O(n+k) | 稳定 |
代码:
/** * 计数排序 * @param array * @param */ void countingSort_1(int[] array){ int max = array[array.length-1]; for (int i = 0; i < array.length-1; i++) { if (array[i]>max) max = array[i]; } int[] B = new int[array.length]; int[] C = new int[max+1]; for (int i = 0; i < array.length; i++) { C[array[i]]++; } for (int i = 1; i < C.length; i++) { C[i] += C[i-1]; } for (int i = array.length-1; i >=0; i--) { B[--C[array[i]]] = array[i]; } System.arraycopy(B,0,array,0,array.length); } /** * 计数排序改进,缩小C,归并法处理前后项相加 * @param array */ void countingSort_2(int[] array){ int[] B = new int[array.length]; int max = 0; int min = 0 ; for (int i : array) { if (i>max) max = i; if (i<min) min = i; } int[] C = new int[max - min + 1]; for (int i = 0; i < array.length; i++) { C[array[i]-min]++; } // for (int i = 1; i < C.length; i++) { // C[i] += C[i-1]; // } mergeAdd(C); for (int i = array.length-1; i >=0; i--) { B[--C[array[i]]] =array[i]; } System.arraycopy(B,0,array,0,array.length); } /** * logn比n * @param array */ void mergeAdd(int[] array){ for (int i = 1; i < array.length; i*=2) { for (int j = 0; j < array.length; j+=2*i) { for (int k = j+i; k <j+2*i; k++) { if (k >= array.length) break; array[k] += array[j+i-1]; } } } }
二、基数排序:
LSD(Least significant digital):
算法:
先从kd 开始排序,再对kd-1进行排序,依次重复,直到按k1排序分组分成最小的子序列后。最后将各个子序列连接起来,便可得到一个有序的序列
分析:
平均 | 最好 | 最坏 | 辅助存储 | 稳定性 |
O(d*(n+r)) | O(d*(n+r)) | O(d*(n+r)) | O(n+r) | 稳定 |
代码:
/** * lsd * @param array * @param d */ void radixSort_LSD(int[] array,int d){ int k = 0,m = 1,n = 1; int[][] temp = new int[10][array.length]; int[] order = new int[10]; while (m<=d){ for (int i = 0; i < array.length; i++) { int lsd = (array[i]/n)%10; temp[lsd][order[lsd]++] = array[i]; } for (int i = 0; i < 10; i++) { if (order[i] == 0) continue; for (int j = 0; j < order[i]; j++) { array[k++] = temp[i][j]; } order[i] = 0; } n *= 10; k = 0; m++; } } /** * lsd from baidu * @param data */ public void radixSort_LSD_2(int data[])//data为待排序数组 { int n=data.length; int bask[][]=new int[10] ; int index[]=new int[10]; int max=Integer.MIN_VALUE; for(int i=0;i<n;i++) { max=max>(Integer.toString(data[i]).length())?max:(Integer.toString(data[i]).length()); } String str; for(int i=max-1;i>=0;i--) { for(int j=0;j<n;j++) { str=""; if(Integer.toString(data[j]).length()<max) { for(int k=0;k<max-Integer.toString(data[j]).length();k++) str+="0"; } str+=Integer.toString(data[j]); bask[str.charAt(i)-'0'][index[str.charAt(i)-'0']++]=data[j]; } int pos=0; for(int j=0;j<10;j++) { for(int k=0;k<index[j];k++) { data[pos++]=bask[j][k]; } } for(int x=0;x<10;x++)index[x]=0; } }
MSD(Most significant digital):
算法:
先按k1 排序分组,将序列分成若干子序列,同一组序列的记录中,关键码k1相等。再对各组按k2 排序分成子组,之后,对后面的关键码继续这样的排序分组,直到按最次位关键码kd 对各子组排序后。
再将各组连接起来,便得到一个有序序列。
分析:
平均 | 最好 | 最坏 | 辅助存储 | 稳定性 |
O(d*(n+r)) | O(d*(n+r)) | O(d*(n+r)) | O(n+r) | 稳定 |
代码:
/** * msd * @param array * @param begin * @param end * @param d */ void radixSort_MSD_1(int[] array,int begin,int end,int d){ if (d==0||begin==end) return; int[][] temp = new int[10][array.length]; int[] order = new int[10]; int k = begin; for (int i = begin; i <= end; i++) { int lsd = d!=1?array[i]/(int) Math.pow(10,d-1):array[i]%10; temp[lsd][order[lsd]++] = array[i]; } for (int i = 0; i < 10; i++) { if (order[i] == 0) continue; for (int j = 0; j < order[i]; j++) { array[k++] = temp[i][j]; } // radixSort_MSD_1(array,k - order[i],k-1,d-1); } }
三、桶排序:
算法:
将数组分到有限数量的桶子里。每个桶子再个别排序(有可能再使用别的排序算法或是以递归方式继续使用桶排序进行排序)注意:
很多文章对于桶排序的理解是不到位的,比如百度百科中桶排序中的java代码是基数排序lsd的代码,我认为桶排序与计数和基数排序更像是父类和子类的关系,计数排序是仅一次分桶,适合数据分布集中的场景,而基数排序增加分桶次数,适合数据数据分散的场景。那么为什么会把三者归位一类呢?我认为计数和基数排序已经能够完成“桶排序父类”的大部分工作,桶排序也就被人们当作一种独立的能内嵌比较排序的非比较排序算法,应用于实践中。分析:
平均 | 最好 | 最坏 | 辅助存储 | 稳定性 |
O(n+c) c=n*(logn-logm) | O(n) | O(n+c) | O(n+m) | 稳定 |
代码:
/** * * @param array * @param left * @param right */ private void insertionSort(int array[], int left, int right) { for (int i = left; i < right-1 ; i++) { for (int j = i+1; j < right; j++) { if (array[i]>array[j]){ int temp = array[i]; array[i] = array[j]; array[j] = temp; } } } } /** * * @param array * @param c */ private void countingSort(int array[],int c[]){ int b[] = new int[array.length]; for (int i = 0; i < array.length; i++) { c[array[i]/10]++; } for (int i = 1; i < c.length; i++) { c[i] += c[i-1]; } for (int i = 0; i < array.length; i++) { b[--c[array[i]/10]]=array[i]; } System.arraycopy(b,0,array,0,array.length); } /** * * @param array * @param c */ private void bucketSort(int array[],int c[]){ countingSort(array,c); insertionSort(array,0,c[0]); for (int i = 1; i < c.length; i++) { insertionSort(array,c[i-1],c[i]); } }
参考链接: http://www.cnblogs.com/eniac12/p/5332117.html#s1 http://blog.csdn.net/simongeek/article/details/45202173
如有错误,欢迎指出!
相关文章推荐
- 易解排序算法 - 空间换取时间(java写:基数排序,计数排序,桶排序,排序全部源代码)
- 程序猿找工作必练内功:排序算法大总结(五)——线性时间排序算法(计数排序,基数排序,桶排序)
- 线性排序算法-- 计数排序,基数排序,桶排序
- JAVA整型数组排序算法以及改进算法
- 排序算法之线性排序(计数排序和桶排序)--Java语言
- 排序算法(插入排序、shell排序、冒泡排序、选择排序、合并排序、堆排序、快速排序、计数排序、基数排序、桶排序)
- 【算法导论】第8章线性时间排序_计数排序、基数排序、桶排序
- 《算法导论》学习总结 — 8.第八章(2) 计数排序 && 基数排序 && 桶排序
- 数据结构与算法——计数排序、桶排序、基数排序
- Java排序算法总结(八):基数排序
- 算法导论 第8章 线性时间排序(计数排序、基数排序、桶排序)
- java必须知道的八大种排序算法:冒泡排序、 选择排序、插入排序、快速排序、希尔算法、归并排序算法、基数排序、堆排序算法
- 算法导论之排序:快速排序、归并排序、计数排序、基数排序、桶排序
- 笔试面试最常涉及到的12种排序算法(包括插入排序、二分插入排序、希尔排序、选择排序、冒泡排序、鸡尾酒排序、快速排序、堆排序、归并排序、桶排序、计数排序和基数排序)进行了详解。每一种算法都有基本介绍、算
- 基础数据结构算法_计数排序,基数排序,桶排序
- 算法学习之排序学习之基数排序,计数排序及java实现
- 排序算法(计数排序,基数排序,桶排序)
- 【更新】排序算法比较:插入排序,冒泡排序,归并排序,堆排序,快速排序,计数排序,基数排序,桶排序
- 常见的五类排序算法图解和实现(多关键字排序:基数排序以及各个排序算法的总结)
- 经典内部排序算法学习总结(算法思想、可视化、Java代码实现、改进、复杂度分析、稳定性分析)