D7-排序算法[Java数据结构和算法]
Posted erfishing
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了D7-排序算法[Java数据结构和算法]相关的知识,希望对你有一定的参考价值。
1.快速排序(QuickSort)
1.1 快速排序是对冒泡排序的一种改进。通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另一部分的所有数据都要小,然后再按照此方法对这两部分数据进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。
package cn.atguigu.sort; import java.text.SimpleDateFormat; import java.util.Arrays; import java.util.Date; public class QuickSort public static void main(String[] args) // TODO Auto-generated method stub // int[] arr= -9,78,0,23,-567,70; int[] arr = new int[80000]; for (int i = 0; i < arr.length; i++) arr[i] = (int) (Math.random() * 8000); Date date1 = new Date(); SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); String date1Str = simpleDateFormat.format(date1); System.out.println("排序前时间" + date1Str); quickSort(arr, 0, arr.length - 1); Date date2 = new Date(); String date2Str = simpleDateFormat.format(date2); System.out.println("排序后时间" + date2Str); // System.out.println(Arrays.toString(arr)); public static void quickSort(int[] arr, int left, int right) int l = left;// 左下标 int r = right;// 右下标 int pivot = arr[(left + right) / 2]; int temp = 0; // while循环的目的是让比pivot小的值放左边,大的值放右边 while (l < r) // 在pivot的左边一直找,找到大于pivot的数 while (arr[l] < pivot) l += 1; // 在pivot的右边一直找,找到小于pivot的数 while (arr[r] > pivot) r -= 1; // 如果l>=r说明pivot的左右两的值,已将按照左边全部小于pivot值,右边全部大于pivot的值 if (l >= r) break; // 交换 temp = arr[l]; arr[l] = arr[r]; arr[r] = temp; // 交换完后,发现arr[l]==pivot,r--,前移 if (arr[l] == pivot) r -= 1; if (arr[r] == pivot) l += 1; // 如果l==r,必须l++,r--,否则必须栈溢出 if (l == r) l += 1; r -= 1; // 向左递归 if (left < r) quickSort(arr, left, r); // 向右递归 if (right > l) quickSort(arr, l, right);
2.归并排序(MergeSort)
2.1 利用归并的思想实现排序,该算法采用经典的分治策略(divide-and-conquer)
2.2 源代码
package cn.atguigu.sort; import java.text.SimpleDateFormat; import java.util.Arrays; import java.util.Date; public class MergeSort public static void main(String[] args) // int[] arr= 8,4,5,7,1,3,6,2; int[] arr = new int[80000]; for (int i = 0; i < arr.length; i++) arr[i] = (int) (Math.random() * 8000); int temp[]=new int[arr.length];//归并排序需要额外的空间 Date date1 = new Date(); SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); String date1Str = simpleDateFormat.format(date1); System.out.println("排序前时间" + date1Str); mergeSort(arr, 0, arr.length-1, temp); Date date2 = new Date(); String date2Str = simpleDateFormat.format(date2); System.out.println("排序后时间" + date2Str); // System.out.println("归并排序后:"+Arrays.toString(arr)); //分+合的方法 public static void mergeSort(int[] arr,int left,int right,int[] temp) if(left<right) int mid=(left+right)/2;//中间索引 //向左进行分解 mergeSort(arr, left, mid, temp); //向右进行分解 mergeSort(arr, mid+1, right, temp); //到合并 merge(arr, left, mid, right, temp); //合并的方法 /** * * @param arr 排序的数组 * @param left 左边有序序列的初始索引 * @param mid 中间索引 * @param right 右边索引 * @param temp 做中转的数组 */ public static void merge(int[] arr,int left,int mid,int right,int[]temp) int i=left;//初始化i,左边有序序列的 初始索引 int j=mid+1;//初始化j,右边序列的初始索引 int t=0;//指向temp数组的当前索引 //先把左右两边的数据按照规则填充到temp数组,直到左右两边的有序序列有一方处理完毕 while(i<=mid&&j<=right) if(arr[i]<=arr[j]) temp[t]=arr[i]; i++; else temp[t]=arr[j]; j++; t++; //将剩余数据的一方的数据一次全部填充到temp while (i <= mid) temp[t] = arr[i]; t++; i++; while (j <= right) temp[t] = arr[j]; t++; j++; //将temp数组的元素全部拷贝到arr t=0; int tempLeft=left; while(tempLeft<=right) arr[tempLeft]=temp[t]; t++; tempLeft++;
3.基数排序又叫桶排序(radixSort)
3.1 属于分配式排序(distribution sort),通过键值的各个位的值,将要排序的元素分配至某些“桶”中,达到排序的作用,算法属于稳定性的排序,基数排序法是效率高的稳定性排序法
基数排序是桶排序的扩展,将整数按位数切割成不同的数字,然后每个位数分别比较。
3.2 将所有带比较数值统一为同样的数位长度,数位较短的数前面补0。然后,从最低位开始,依次进行一次排序。这样从最低位排序一直到最高位排序完成以后,数列就变成一个有序序列。
第1轮排序:
(1)将每个元素的个位数取出,然后看这个数应该放在哪个对应的桶(一个一维数组)
(2)按照这个桶的顺序(一维数组的下标依次取出数据,放入原来数组)
第2轮排序:
(1)将每个元素的十位数取出,然后看这个数应该放在哪个对应的桶(一个一维数组)
(2)按照这个桶的顺序(一维数组的下标依次取出数据,放入原来数组)
第3轮排序:
(1)将每个元素的百位数取出,然后看这个数应该放在哪个对应的桶(一个一维数组)
(2)按照这个桶的顺序(一维数组的下标依次取出数据,放入原来数组)
3.3 源代码
package cn.atguigu.sort; import java.text.SimpleDateFormat; import java.util.Arrays; import java.util.Date; public class radixSort public static void main(String[] args) // TODO Auto-generated method stub // int[] arr= 53,3,542,748,14,214; int[] arr = new int[80000]; for (int i = 0; i < arr.length; i++) arr[i] = (int) (Math.random() * 80000); int temp[]=new int[arr.length];//归并排序需要额外的空间 Date date1 = new Date(); SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); String date1Str = simpleDateFormat.format(date1); System.out.println("排序前时间" + date1Str); radixSort(arr); Date date2 = new Date(); String date2Str = simpleDateFormat.format(date2); System.out.println("排序后时间" + date2Str); public static void radixSort(int[] arr) //最终代码 //1.得到数组中的最大的数的位数 int max=arr[0];//假设第一个数就是最大数 for(int i=0;i<arr.length;i++) if(arr[i]>max) max=arr[i]; //得到最大数是几位数 int maxLength=(max+"").length(); //使用循环代码处理 //定义一个二维数组,表示10个桶,每个桶就是一个一维数组 //说明 //1.二维数组包含10个一维数组 //2.为了防止在放入数的时候,数据溢出,则每一个一维数组,大小定位arr.length //3.明确基数排序是使用空间换时间的经典算法 int[][] bucket=new int[10][arr.length]; //为了记录每个桶中,实际存放了多少个数据,我们定义一个一维数组记录各个桶的每次放入的数据个数 //可以这样理解 //比如:bucketElementCounts[0],记录的就是bucket[0]桶的放入数据 int[] bucketElementCounts=new int[10]; for(int i=0,n=1;i<maxLength;i++,n*=10) for (int j = 0; j < arr.length; j++) //取出每个元素的个数 int digitOfElement=arr[j]/n%10; //放入到对应的桶中 bucket[digitOfElement][bucketElementCounts[digitOfElement]]=arr[j]; bucketElementCounts[digitOfElement]++; //按照这个桶的顺序(一维数组的下标依次取出数据,放入原来数组) int index=0; //遍历每一个桶,并将桶中的数据,放入到原来的数组 for(int k=0;k<bucketElementCounts.length;k++) //如果桶中,有数据,我们才放入到数组 if(bucketElementCounts[k]!=0) //循环该桶即第k个桶(第k个一维数组),放入 for(int l=0;l<bucketElementCounts[k];l++) //取出元素放入到arr arr[index]=bucket[k][l]; index++; //第i+1轮处理后,需要将每个bucketElementCounts[k]置0 bucketElementCounts[k]=0; // System.out.println("第"+i+"轮,对个位的排序"+Arrays.toString(arr));
4.排序算法时间复杂度比较
4.1 相关术语解释:
(1)稳定:如果a原本在b前面,而a=b,排序后a仍然在b的前面;
(2)不稳定:如果a原本在b的前面,而a=b,排序之后a可能会出现在b的后面;
(3)内排序:所有排序操作都在内存中完成;
(4)外排序:由于数据太大,因此把数据放在磁盘中,而排序通过磁盘和内存的数据传输才能进行;
(5)时间复杂度:一个算法执行所耗费的时间;
(6)空间复杂度:运行完一个程序所需要内存的大小;
(7)n:数据规模
(8)k:“桶”的个数
(9)In-space:不占用额外内存
(10)Out-space:占用额外内存
4.2 常用算法对比
排序算法 | 平均时间复杂度 | 最好情况 | 最坏情况 | 空间复杂度 | 排序方式 | 稳定性 |
冒泡排序 | O(n2) | O(n) | O(n2) | O(1) | In-space | 稳定 |
选择排序 | O(n2) | O(n2) | O(n2) | O(1) | In-space | 不稳定 |
插入排序 | O(n2) | O(n) | O(n2) | O(1) | In-space | 稳定 |
希尔排序 | O(n log n) | O(n log2 n) | O(n log2 n) | O(1) | In-space | 不稳定 |
归并排序 | O(n log n) | O(n log n) | O(n log n) | O(n) | Out-space | 稳定 |
快速排序 | O(n log n) | O(n log n) | O(n2) | O(log n) | In-space | 不稳定 |
堆排序 | O(n log n) | O(n log n) | O(n log n) | O(1) | In-space | 不稳定 |
计数排序 | O(n+k) | O(n+k) | O(n+k) | O(k) | Out-space | 稳定 |
桶排序 | O(n+k) | O(n+k) | O(n2) | O(n+k) | Out-space | 稳定 |
基数排序 | O(n*k) | O(n*k) | O(n*k) | O(n+k) | Out-space | 稳定 |
以上是关于D7-排序算法[Java数据结构和算法]的主要内容,如果未能解决你的问题,请参考以下文章
Java算法 选择排序算法 -- 选择排序算法的非递归和递归形式实现