排序算法-->选择排序,插入排序,并归排序,快速排序

来源:互联网 发布:乾隆自恋知乎 编辑:程序博客网 时间:2024/06/05 03:19
package com.sort;import java.util.Arrays;import java.util.Random;import com.util.SortTestHelper;/** * 排序算法 * @author 文龙 * @version 2017-12-24 下午12:53:20 */public class Sort {/** * 选择排序: -->每次从未排序的部分选择最小进行插入    * 优点:简单 * 缺点:每一层循环都要全部遍历一次 * 时间复杂度是:n^2 * 原理:每次都  从剩余未排序的数中  选出最小的数  与前面已排序的  后一个  进行交换位置 */public static int[] selectionSort(int[] a) {for(int start = 0;start < a.length;start++) {int min = start;//查找到的最小的数的下标for(int i = start + 1;i < a.length; i++) {if(a[min] > a[i]) {min = i;}}//进行一次的交换int temp = a[start];a[start] = a[min];a[min] = temp;}return a;}/** * 插入排序   --> 每次从排序好的后一个选一个插入 * 优点: 对于近乎有序的数据,非常快,有时候比 nlogn 的算法还要快,时间复杂度甚至达到O(n)。,在很多复杂的算法中使用插入排序进行优化 * 时间复杂度:n^2 * 原理:选取 后一个 与 前面已排序的元素进行比较,插入到合适的位置 *  * 与选择排序相比: 插入排序的比较的是可以提前结束的 *  */public static int[] insertionSort(int[] a) {if(a.length == 1) return a;intcur = 1;//轮到哪一个元素进行插入了for(;cur < a.length; cur++) {//for里面的i为与哪一个进行对比了for(int i = cur - 1; i < a.length && i >= 0; i--) {if(a[i + 1] < a[i]) {//如果后一个比前一个小 则进行交换位置int temp = a[i + 1];a[i + 1] = a[i];a[i] = temp;} else {//如果出来比前面大的话,就不用与之前的比较了,因为前面的已经排序好了,前面的所有都会比它小break;}}}return a;}/** * 插入排序的优化版 -->上面的每次交换 都叫 两两交换(一个循环会有多次两两交换),下面 每次循环两两交换只进行一次 */public static int[] insertionSort2(int[] a) {/** * 注意: 做这些题要 先确定大体的框架,例如先 确定两个大循环,在逐渐的补充代码 */for(int cur = 1; cur < a.length; cur++) {int temp = a[cur];//把当前的下标的元素取出来int i = cur - 1;//与当前下标的上一个进行对比for(; i >= 0; i--) {if(temp < a[i]) {//如果当前的temp相对小,则将其对比的那个向后移动一个a[i + 1] = a[i];}else {//如果不小于,就是当前的temp大于或者是等于a[i],直接退出即可,因为前面的肯定都大于break;}}//因为上面将a[i]的元素给了a[i+1],则a[]的位置可以放了,但是循环结束了又减了1,在这里要加上1a[i + 1] = temp;}return a;}/** * 归并排序 * 时间复杂度:o(nlogn) * 优点:快 * 原理: 将一个数组不断的分为两部分排序(使用递归将分好的部分在继续分为两部分) *优化: 当分为的部分为一定个数时,可以使用插入排序 */public static int[] mergeSort(int[] arr) {merge_Sort(arr, 0, arr.length - 1);return arr;}//使用递归private static void merge_Sort(int[] arr,int l, int r) {if(l >= r) return;int mid = (l+r)/2;merge_Sort(arr, l, mid);merge_Sort(arr, mid + 1, r);/*//这里进行一次优化 --> 对近乎有序的数组效率很快if(arr[mid] > arr[mid + 1])*/sort(arr, l, mid, r );}//具体排序步骤private static void sort(int[] arr, int l, int mid, int r) {int[] copyArr = Arrays.copyOfRange(arr, l, r + 1);//这里复制的数组并不是和  开始传进来的一样长,而是递归 二分之后的长度int i = l;int j = mid + 1;for(int k = l;k <= r; k++) {if(i > mid) {arr[k] = copyArr[j - l];//所以如果直接使用copyArr[j]可能会越界j++;}else if (j > r) {arr[k] = copyArr[i - l];i++;}else if(copyArr[i - l] < copyArr[j - l]) {arr[k] = copyArr[i - l];i++;} else {arr[k] = copyArr[j - l];j++;}}}/** * 快速排序  -->被称为20世纪最快的算法 *时间复杂度: O(nlogn)  *原理: 选择一个temp,将数组分为分小于temp和大于temp两部分。再将这两部分进行递归处理 *两个优化:  *1,底层使用插入排序 *2.对于有序的数据,如果都是选择第一个作为标准值的话,那么两边就会极其的不平衡,这时候的优化是:不选择第一个数作为标准值,而是随机选择一个数作为标准值 *3,对于有很多重复的数,比如排序 1百万个 0到10 之间的数。那么这样也会很慢,因为当你选择了一个数,因为其重复出现的次数太多,也会造成两个的不平衡 *同时,如果使用三路快速排序的话  --> 将一组数据分为三个部分  大于 等于 小于 。对于 等于 的在一个排序结束,它们的位置就是已经确定的了 * @param arr * @return */public static int[] quickSort(int[] arr) {quick_Sort(arr, 0, arr.length - 1);return arr;}//这里使用递归private static void quick_Sort(int[] arr,int l,int r) {//递归结束的条件if(l >= r) return;//第一个优化可以在这里使用插入排序//返回的是小于与大于的分界线int p = partition(arr, l, r);quick_Sort(arr, l, p - 1);quick_Sort(arr, p + 1, r);}/** * 快排的具体实现步骤 * @param arr * @param l 起始位置 * @param r 结束位置 */private static int partition(int[] arr,int l, int r) {/*第二个优化,随机选择一个数,使得两遍更加平衡*/swap(arr, new Random().nextInt(r) % (r - l + 1) + l, l);//选择第一个数为标准值int v = arr[l];int j = l;int i = l + 1;for(;i <= r;i++) {if(arr[i] < v) {swap(arr, j + 1, i);j++;}}swap(arr, l, j);return j;}/** * 创建一个近乎有序的数组 * @param arr 要交换的数组 * @param n 交换的次数 * @return */public static int[] nearlyOrderedArray(int[] arr, int n) {for(;n > 0;n--) {Random random = new Random();Random random2 = new Random();int a = random.nextInt(arr.length - 1);int b = random2.nextInt(arr.length - 1);swap(arr, a, b);}return arr;}private static void swap(int[] arr,int a, int b) {int temp = arr[b];arr[b] = arr[a];arr[a] = temp;}public static void main(String[] args) {//创建排序用的数据int[] arr = SortTestHelper.generateRandomArray(10000000, 1, 1000000);int[] arr2 = Arrays.copyOf(arr, arr.length);int[] arr3 = Arrays.copyOf(arr, arr.length);//SortTestHelper.testSort(arr, "selectionSort");SortTestHelper.testSort(arr3, "quickSort");//打乱交换100次nearlyOrderedArray(arr3, 1000);//System.out.println(Arrays.toString(arr));//选择排序//SortTestHelper.testSort(arr, "selectionSort");//插入排序//SortTestHelper.testSort(arr, "insertionSort");//插入排序的优化版//SortTestHelper.testSort(arr2, "insertionSort2");//归并排序//SortTestHelper.testSort(arr, "mergeSort2");//mergeSort(arr);//System.out.println(Arrays.toString(arr));//quickSort(arr);//System.out.println(Arrays.toString(arr));//System.out.println(Arrays.toString(arr3));SortTestHelper.testSort(arr3, "quickSort");System.out.println(arr3.length);}}

阅读全文
'); })();
0 0
原创粉丝点击
热门IT博客
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 小雨滴app 绿水农家绕 疯狂小雨滴 小雨点 小雨点日记完结4 小雨点的日记 苏雯雯番外小雨点 贪玩的小雨点的日记 小雨点贷 小雨点贷款 小雨点小额贷款 小雨点网贷app 小雨点网贷app下载 小雨点小额贷款app 我是小雨点儿后续全文 重庆小雨点网贷 幼儿园小雨点儿歌 小雨点小额贷款是真假的 小雨点会变成什么 小雨点还会变成什么 雨点 小小雨点 小雨点歌曲 小小雨点儿歌mp3 小雨点的歌 欢迎小雨点 雯雯山村落难记2小雨点 雯雯山村历险记小雨点 小雨衣怎么用 口红小雨衣 小雨衣避孕套 户外雨衣 雨衣的图片 小雪人 小雪人儿童画图片 小雪人图片 小雪绒 汽车小零件 买手机壳送的小零件 小零嘴 零嘴是什么意思 自制小零食