归并排序
归并排序是一种利用分治递归思想排序的算法。这个算法的基本操作就是将两个有序表合并。因此在设计算法时要先将原数组划分到每组只有一个元素,这时就可以将每组都看成有序表,再将其依次合并,这里使用递归方法就能巧妙的解决。
在做合并操作的时候需要三个指针 leftPos,rightPos,和tempIndex分别指向左有序表首位置,右有序表首位置,和零时数组首位置。
import java.util.Arrays;
public class MergeSort {
public static void main(String[] args) {
int[] arr = new int[20];
for(int i=0;i<20;i++){
arr[i]=(int)(Math.random()*100);
}
System.out.println("排序前数组");
System.out.println(Arrays.toString(arr));
int[] temp =new int[arr.length];
mergeSort(arr,temp,0,arr.length-1);
System.out.println("排序后数组");
System.out.println(Arrays.toString(arr));
}
//无序数组分解部分
private static void mergeSort(int[] arr,int[] temp,int left,int right){
int center =(left+right)/2;
if(left<right){
mergeSort(arr,temp,left,center);
mergeSort(arr,temp,center+1,right);
merge(arr,temp,left,center+1,right);
}
}
//两个有序表合并部分
private static void merge(int[]arr,int[] temp,int leftPos,int rightPos,int rightEnd ){
int tempIndex = leftPos;
int leftEnd = rightPos-1;
int num = rightEnd-leftPos+1;
//左侧有序数组,与右侧有序数组从各自首索引位置开始比较
//小数存入temp数组,并将其索引和temp索引后移
while (leftPos<=leftEnd && rightPos<=rightEnd){
if(arr[leftPos]<=arr[rightPos]){
temp[tempIndex]=arr[leftPos];
leftPos++;
tempIndex++;
}else {
temp[tempIndex]=arr[rightPos];
rightPos++;
tempIndex++;
}
}
// 剩下的一侧直接复制到temp数组中
while (leftPos<=leftEnd){
temp[tempIndex]=arr[leftPos];
leftPos++;
tempIndex++;
}
while (rightPos<=rightEnd){
temp[tempIndex]=arr[rightPos];
rightPos++;
tempIndex++;
}
//最后将temp数组拷贝回原数组中
for(int i=0;i<num;i++,rightEnd--){
arr[rightEnd]=temp[rightEnd];
}
}
}
结果:
排序前数组
[81, 90, 31, 79, 33, 2, 64, 98, 45, 13, 40, 54, 81, 47, 18, 91, 33, 15, 25, 14]
排序后数组
[2, 13, 14, 15, 18, 25, 31, 33, 33, 40, 45, 47, 54, 64, 79, 81, 81, 90, 91, 98]
基数排序
基数排序属于分配式排序,它是通过键值的各个位的值将要排序的元素分配至某些桶中,达到排序的作用。它是桶排序的扩展。
排序思路: 找出数组中最大数的长度,也就是位数,如arr={10,24,1,3,890,124,1111}最大数是1111,即要进行4轮排序。每轮排序按照个位,十位,百位,千位依次进行。创建10个桶,可以用二维数组实现bucket[10][arr.length],存储排序数组中的元素。再建立一个一维数组bucketCount【10] 记录每个桶中存放的元素个数。个位是1就放入bucket[1][bucketCount[k] ] 中。将所有元素放入桶中后,再将桶中元素按桶的顺序,依次取出,就得到第一轮排序后的数组。第二轮排序按照十位的数放入桶中,再取出,第三轮排序按照百位的数放入桶中再取出,直到所有轮排序结束,就得到最后的结果。
import java.util.Arrays;
public class RadixSort {
public static void main(String[] args) {
int[] arr = new int[10];
for(int i=0;i<10;i++){
arr[i]=(int)(Math.random()*100000);
}
System.out.println("排序前数组");
System.out.println(Arrays.toString(arr));
RadixSort(arr);
System.out.println("排序后数组");
System.out.println(Arrays.toString(arr));
}
private static void RadixSort(int[] arr){
int max = arr[0];
for(int i=1;i<arr.length;i++){
if(max<arr[i]){
max=arr[i];
}
}
int maxLength = (max+"").length();
int bucket[][] =new int[10][arr.length];
int bucketCount[] = new int[10];
//外循环控制排序轮数,等于最大数的长度
for(int i=0, n=1;i<maxLength;i++,n*=10){
//将数组元素按位数放入桶中
for(int j=0;j<arr.length;j++){
int digitOffElement = arr[j] /n %10;
bucket[digitOffElement][bucketCount[digitOffElement]]=arr[j];
bucketCount[digitOffElement]++;
}
//将桶中元素取出
int index = 0;
for(int k=0;k<bucket.length;k++){
if(bucketCount[k]!=0){
for (int j=0;j<bucketCount[k];j++){
arr[index++]=bucket[k][j];
}
}
bucketCount[k]=0;
}
}
}
}
排序前数组
[69653, 68330, 46350, 95244, 48707, 46300, 69834, 21745, 86273, 73735]
排序后数组
[21745, 46300, 46350, 48707, 68330, 69653, 69834, 73735, 86273, 95244]
基数排序是典型的用空间换时间的排序方法,它需要开辟额外的空间(桶)存储数据。上述的基数排序代码还不能解决有负数的情况。
本文深入解析归并排序与基数排序算法,详细阐述了归并排序的分治递归思想及其实现过程,同时介绍了基数排序作为桶排序的扩展,如何通过键值的位值进行高效排序。
4865

被折叠的 条评论
为什么被折叠?



