zoukankan      html  css  js  c++  java
  • 教了公司新来的小姐姐这七种排序算法以及实现,她一脸崇拜的看着我

    前言

    最近学习一些排序算法,怕自己以后忘记就打算整理起来供自己复习

    如有错误希望大佬指正,欢迎大家在评论区交流探讨。

    1.冒泡排序

    • 通过待排序的序列从前往后依次比较相邻的元素,若发现逆序则两两交换,直到下一趟排序下来没有进行交换,说明排序完成
    • 冒泡排序每一趟会确定一个最大值(默认从小到大)
    import java.util.Arrays;
    
    public class BubbleSort {
        public static void main(String[] args) {
            int array[] = {10,9,2,-3,6,8,1,-6,-5,4};
            for (int i = 0; i < array.length ; i++) { //循环每一趟排序
                for (int j = 0; j < array.length-1-i ; j++) {
    // 每一趟排序的数据交换
    // 由于array[j]是和array[j+1]比较,防止数据越界这里array.length要减一
                    int temp = 0;
                    if (array[j]>array[j+1]){
                        temp = array[j+1];
                        array[j+1] = array[j];
                        array[j] = temp;
                    }
                }
            }
    //  两种方法输出
    //  1.格式化输出,需import,之后的代码演示全用格式化输出
            System.out.println(Arrays.toString(array));
    //  2.for循环输出
            for (int i = 0; i < array.length ; i++) {
                System.out.print(array[i]+" ");
            }
    
        }
    }
    

      

    2.选择排序

    • 第一趟排序是从array[0]到array[array.length-1]找到一个最小值array[n]与array[0]进行交换,第一趟排序是从array[1]到array[array.length-1]找到一个最小值array[n]与array[1]进行交换,直到排序完成
    • 选择排序每一趟排序会确定一个最小值(默认从小到大)
    • 以下是三种不同的代码实现
    import java.util.Arrays;
    
    public class SelectSortDemo01 {
        public static void main(String[] args) {
            int array[] = {10,9,2,-3,6,8,1,-6,-5,4};
            for (int i = 0; i < array.length-1 ; i++) {
                for (int j = 1+i; j < array.length; j++) {
    //  此算法与冒泡排序的算法类似,只不过冒泡算法的每一趟排序是两两比较,这个是第一个数与每一个数比较
                    int temp = 0;
                    if (array[i] > array[j]){
                        temp = array[j];
                        array[j] = array[i];
                        array[i] = temp;
                    }
                }
            }
            System.out.println(Arrays.toString(array));
        }
    }
    

      

    import java.util.Arrays;
    
    public class SelectSortDemo02 {
        public static void main(String[] args) {
            int array[] = {10,9,2,-3,6,8,1,-6,-5,4};
            int temp = 0;
            for (int j = 0; j <array.length-1 ; j++) {
                for (int i = 1; (i+j)< array.length ; i++) {
    //此算法与上面一个大同小异,也实现了相同的效果,可以根据自己的思维选择一个合适的算法              
                    if (array[j] > array[i+j]) {
                        temp = array[i+j];
                        array[i+j] = array[j];
                        array[j] = temp;
                    }
                } 
            }
          System.out.println(Arrays.toString(array));
        }
    }
    

      

    public class SelectSortDemo02 {
        public static void main(String[] args) {
            int array[] = {10,9,2,-3,6,8,1,-6,-5,4};
            for (int i = 0; i < array.length-1 ; i++) { 
     //      与前面两种方法不同的是此算法直接先假定每一趟排序的第i个数的数值最小,提取当前下标i,
     //      方便每一趟排序与第i个数据进行交换
     //      这样也更容易理解
                int min = array[i];
                int minIndex = i;
                for (int j =  1 + i; j < array.length; j++) {
                    if (min > array[j] ){
     //      说明假定的最小值并不是最小的,需要重置min,此时只需赋值,不需要交换
     //      让其循环结束直到赋值到最小值
                        min = array[j];
                        minIndex = j;
                    }
                }
    //        将最小值放在arr[0],交换
                if (minIndex != j) {
                    array[minIndex] = arr[j];
                    array[j] = min;
                }
            }
            System.out.println(Arrays.toString(array));
        }
    }
    

      

    3.插入排序

    • 假如有n个数,第一趟排序就是比较前两个数将它们排好(默认从小到大),然后在来一个数比较他们三个再排好
    • 可以理解为斗地主的摸牌,先摸了两张J和K,要把J放在K的前面,在摸一张6要放在J和K的前面,在摸一张10就要放在6和J之间,排摸完了就相当于排序结束
    import java.util.Arrays;
    
    public class InsertSortDemo01 {
        public static void main(String[] args) {
            int[] array = {5, 2, -1, 4, 7};
            for (int i = 1; i < array.length; i++) {
    //      与选择排序第三种类似,先定义一个待插入的数据和插入的位置,便于之后赋值
                int insertVal = array[i];
    //      为了将待插入的数插入到array[i]的前一个位置
                int insertIndex = i - 1;
    //      待插入的位置必须大于等于0,保证数组不越界
                while (insertIndex >= 0 && insertVal < array[insertIndex]) {
    //      直接赋值不用交换数据
                    array[insertIndex + 1] = array[insertIndex];
    //      为了让第i个数与前面的数都进行比较然后赋值,前面有条件不用但不用担心数组越界         
                    insertIndex--;
                }
    //      insertIndex + 1 = i 说明第i轮已经有序      
                if (insertIndex + 1 != i) {
                    array[insertIndex + 1] = insertVal;
                }
            }
            System.out.println(Arrays.toString(array));
        }
    
    }
    

      

    4.希尔排序

    • 希尔排序相当于对插入排序进行优化,是一种缩小增量排序
    • 希尔排序第一趟按照arraylength2进行分组,每组分别进行直接插入排序,第二趟按照arraylength22进行分组,每组分别进行直接插入排序,直到增量减至为一,整个文件恰好被分为一组
    • 以下是两种不同的代码实现
    import java.util.Arrays;
    //      交换法,此实现方法速度是很慢,
    //      因为插入排序比较之后直接移位,而此类方法一遇到逆序就会发生交换,
    //      交换法与冒泡排序类似,不停的交换效率很低
    public class ShellSortDemo02 {
        public static void main(String[] args) {
            int array[] = {10,9,2,-3,6,8,1,-6,-5,4};
            int temp = 0;
            for (int len = array.length/2; len > 0;len/=2) {
    //      循环每一次分组
                for (int i = len; i < array.length; i++) {
    //      遍历各组的所有元素,有len组
                    for (int j = i - len; j >= 0; j -= len) {
                        if (array[j] > array[j + len]) {
                            temp = array[j];
                            array[j] = array[j + len];
                            array[j + len] = temp;
                        }
                    }
                }
            }
            System.out.println(Arrays.toString(array));
    
        }
    }
    

      

    import java.util.Arrays;
    
    public class ShellSortDemo03 {
    //    对交换式的希尔排序进行优化,采用移位法
    //    当需要插入的数是最小数时,后移的次数明显增多,所以使用分组插入排序会大大的提高效率
        public static void main(String[] args) {
            int[] array = {10, 9, 2, -3, 6, 8, 1, -6, -5, 4};
    //    仍然使用增量len,并逐步缩小增量
            for (int len = array.length / 2; len > 0; len /= 2) {
    //    逐个对其所在的组进行直接插入排序
                for (int i = len; i < array.length; i++) {
                    int j = i;
                    int temp = array[j];
                    if (array[j] < array[j - len]) {
                        while (j-len >= 0 && temp < array[j - len]) {
    //  移动,与直接插入排序不同的是这个是间距len之间的数据移位,而直接插入排序是两两移位
                            array[j] = array[j - len];
                            j -=len;
                        }
    //     当退出while循环后,就给temp找到了插入的位置
                        array[j] = temp;
                    }
                }
            }
            System.out.println(Arrays.toString(array));
        }
    }
    

      

    5.快速排序

    • 快速排序是一种对冒泡排序的改进,第一趟排序以中间的一个数为基准,将数组中比他小的数放在此数的左边,比他大的数放在此数的右边,第二趟排序以第一趟排好的左右的中间一个数为基准,在分别重复上面操作
    import java.util.Arrays;
    
    public class QuickSortDemo01 {
        public static void main(String[] args) {
            int array[] = {10,9,2,-3,6,8,1,-6,-5,4};
            quickSort(array,0,array.length-1);
            System.out.println(Arrays.toString(array));
        }
        public static void quickSort(int a[],int l,int r){
            if(l>=r)
                return;
    
            int i = l; int j = r; int key = a[(l+r)/2];
    //     选择第一个数为key,我们数组中间的数为例
            while(i<j){
    
                while(i<j && a[j]>=key)
    //     从右向左找第一个小于key的值,找到了,j就前移
                    j--;
    //     如果a[j]<key值,a[j]会放到前面的a[i]同时i会后移          
                if(i<j){
                    a[i] = a[j];
                    i++;
                }
    
                while(i<j && a[i]<key)
    //     从左向右找第一个大于key的值,找到了i就后移
                    i++;
    //     如果a[i]>key值,a[i]会放到后面的a[j]同时j会前移 
                if(i<j){
                    a[j] = a[i];
                    j--;
                }
            }
            //i == j
            a[i] = key;
            quickSort(a, l, i-1);//递归调用
            quickSort(a, i+1, r);//递归调用
        }
    }
    

      

    6.归并排序

    • 归并算法的核心思想就是分解在合并,也就是分治,分解可以采用递归,设一个数组最右边的元素索引为low,最左边的元素的索引为height,中间元素索引为(low+height)/2,每一次分解可以发现当low==height的时候,整个数组被分解成每一个元素,合并就是将两个有序归并段归并为一个有序的归并段,直到有序为止
    import java.util.Arrays;
    
    public class MergeSortDemo01 {
        //合并函数
        public static void merge(int[] array,int low,int mid,int height){
            int s1 = low;
            int s2 = mid+1;
            int[] ret = new int[height-low+1];
            int i = 0;//表示ret数组的下标
            while (s1<=mid && s2<=height){
                if (array[s1]<=array[s2]){
                       ret[i++] = array[s1++];
                }else{
                  ret[i++] = array[s2++];
                }
            }
            while (s1<=mid){
                ret[i++] = array[s1++];
            }
            while (s2<=height){
                ret[i++] = array[s2++];
            }
            for (int j=0;j<ret.length;j++){
                array[low+j] = ret[j];
            }
    
        }
        public static void mergeSort(int[]array,int low,int height){
            if (low>=height){
                return;
            }
            int mid = (low+height)/2;
            mergeSort(array,low,mid);//递归分解左半部分
            mergeSort(array,mid+1,height);//递归分解右半部本
            merge(array,low,mid,height);//合并操作
        }
    
        public static void main(String[] args) {
            int array[] = {10,9,2,-3,6,8,1,-6,-5,4};
            System.out.println(Arrays.toString(array));
            mergeSort(array,0,array.length-1);
            System.out.println(Arrays.toString(array));
        }
    }
    

      

    7.基数排序

    • 本质上是将整数按位数切割成不同的数字,然后按每个位数分别比较,基数排序又叫桶子法
    • 定义10个编号为0~9一维数组,找到每个数的个位数分别放在对应编号的数组中,然后再将十位数取出分别放在对应编号的数组中,直到取到最高位就变为有序
    • 基数排序是效率最高的稳定性排序法
    import java.util.Arrays;
    
    public class RadixSortDemo01 {
        public static void main(String[] args) {
            int array[] = {10, 99, 2, 457, 6, 83, 16, 96, 25, 48};
            radixSort(array);
        }
    
        //基数排序算法
        public static void radixSort(int[] arr) {
            int max = arr[0];
    //    假设第一个数是最大数
            for (int i = 0; i < arr.length; i++) {
                if (arr[i] > max) {
                    max = arr[i];
                }
            }
            int maxLength = (max + " ").length();
    //        定义一个二维数组,表示10个桶,每一个桶是一个一维数组用于存放数据
    //        为了防止放入数的时候,数据溢出,则每个一维数组的大小定位arr.length
            int[][] bucket = new int[10][arr.length];
    //      为了记录每个桶中,实际存放了多少数据,我们定义一个一维数组,我们定义一个一维数组记录各个桶每次放入的数据个数
            int[] bucketCounts = new int[10];
            for (int k=0,n=1;k<maxLength-1;k++,n *=10){
                for (int i = 0; i < arr.length; i++) {
    //         取出每个元素的个位
                    int digitOfElement = arr[i] / n % 10;
    //          放入到对应的桶中
                    bucket[digitOfElement][bucketCounts[digitOfElement]] = arr[i];
    //            每放一个数据此桶的中的数据就要加一
                    bucketCounts[digitOfElement]++;
                }
    //        按照这个桶的顺序(一维数组的下标依次取出数据,放入原来数组)
                int index = 0;
    //        遍历每一个桶并将桶中数据放入原数组
                for (int i = 0; i < bucketCounts.length; i++) {
    //         如果桶中有数据我们才放入到原数组
                    if (bucketCounts[i] != 0) {
                        for (int j = 0; j < bucketCounts[i]; j++) {
    //         取出元素放入到arr
                            arr[index++] = bucket[i][j];
                        }
                    }
    //            第轮处理后需要将每一个bucketCounts[i] = 0;
                    bucketCounts[i] = 0;
                }
                System.out.println("第"+(k+1)+"轮排序 arr =" + Arrays.toString(arr));
            }
        }
    }
    

      

    最后

    感谢你看到这里,看完有什么的不懂的可以在评论区问我,觉得文章对你有帮助的话记得给我点个赞,每天都会分享java相关技术文章或行业资讯,欢迎大家关注和转发文章!

  • 相关阅读:
    sosoapi的安装
    centos7 安装后,意外出现Please make your choice from above ['q' to quit | 'c' to continue | 'r' to refresh]
    crontab 每月最后一天执行命令
    svn的常用命令
    svn的安装与使用
    RPC简述
    REST简介
    VS2015 IIS Express 无法启动 解决办法
    NUnit的安装
    NUnit.Framework在VS2015中如何进行单元测试
  • 原文地址:https://www.cnblogs.com/lwh1019/p/13399474.html
Copyright © 2011-2022 走看看