八大排序算法的java实现

冒泡排序

  • 比较相邻的元素。如果第一个比第二个大,就交换他们两个,小的数往上冒
  • 对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。在这一点,最后的元素应该会是最大的数。
  • 针对所有的元素重复以上的步骤,除了最后一个。
  • 持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。
   public static void bubbleSort(int[] numbers)
   {
       int temp = 0;
       int size = numbers.length;
       for(int i = 0 ; i < size-1; i ++)
       {
           //一趟比较之后,最大的元素就到了最右边(最下面)
           for(int j = 0 ;j < size-1-i ; j++)
           {
               //小数往上冒,大数下沉
               if(numbers[j] > numbers[j+1])
               {
                   temp = numbers[j];
                   numbers[j] = numbers[j+1];
                   numbers[j+1] = temp;
               }
           }
       }
   }

快速排序

在这里插入图片描述

    public static void quickSort(int[] arr, int low, int high) {
        int i, j, temp;
        if (low > high) {
            return;
        }

        i = low;//左边哨兵的索引
        j = high;//右边哨兵的索引
        temp = arr[low];//以最左边为基准位

        while (i < j) {
            //先看右边,依次往左递减
            //先从右往左找一个小于 基准位的数
            //当右边的哨兵位置所在的数>基准位的数时
            //继续从右往左找(同时 j 索引-1)
            //找到后会跳出while循环
            while (temp <= arr[j] && i < j) {
                j--;
            }

            //再看左边,依次往右递增,步骤和上面类似
            while (temp >= arr[i] && i < j) {
                i++;
            }

            //如果满足条件则交换
            if (i < j) {
                // 左右哨兵 交换数据(互相持有对方的数据)
                arr[i] = arr[i]^arr[j];
                arr[j] = arr[i]^arr[j];
                arr[i] = arr[i]^arr[j];
            }
        }

        //这时 跳出了 “while (i<j) {}” 循环,说明 i=j 左右在同一位置
        //最后将基准为与i和j相等位置的数字交换
        arr[low] = arr[i];//或 arr[low] = arr[j];
        arr[i] = temp;//或 arr[j] = temp;

        //递归调用左半数组
        quickSort(arr, low, j - 1);
        //递归调用右半数组
        quickSort(arr, j + 1, high);
    }

直接选择排序

  • 在要排序的一组数中,选出最小的一个数与第一个位置的数交换;
  • 然后在剩下的数当中再找最小的与第二个位置的数交换,如此循环直到只剩两个数做最后一次排序。
    public static void selectSort(int[] numbers)
    {
        for(int i = 0 ; i < numbers.length -1 ; i++)
        {
            int k = i;
            //选择出应该在第i个位置的数
            for(int j = numbers.length -1 ; j > i ; j--)
            {
                if(numbers[j] < numbers[k]) k = j;
            }
            //交换两个数
            numbers[i] = numbers[i]^numbers[k];
            numbers[k] = numbers[i]^numbers[k];
            numbers[i] = numbers[i]^numbers[k];
        }
    }

直接插入排序

  • 选出最左边两个元素,排序,得到一个排序好的子集
  • 选出左边的第三个元素,插入到排序好的子集当中(从右到左遍历,找到合适的插入位置)
  • 循环执行第二部,直到最后一个元素。
    public static void insertSort(int[] numbers)
    {
        int temp,j;

        for(int i = 0 ; i < numbers.length ; i++)
        {
            temp = numbers[i];
            //假如temp比前面的值小,则将前面的值后移
            for(j = i ; j > 0 && temp < numbers[j-1] ; j --)
            {
                numbers[j] = numbers[j-1];
            }
            numbers[j] = temp;
        }
    }

希尔排序(直接插入改良版)

插入排序当数组基本有序时,比较高效。但是对于较大规模且无序的数据,插入排序效率就低了。可以采用希尔排序。
在这里插入图片描述
可以看出,他是按下标相隔距离为4分的组,也就是说把下标相差4的分到一组,比如这个例子中a[0]与a[4]是一组、a[1]与a[5]是一组…,这里的差值(距离)被称为增量。
每个分组进行插入排序后,各个分组就变成了有序的了(整体不一定有序)。
在这里插入图片描述
然后缩小增量为上个增量的一半:2,继续划分分组,此时,每个分组元素个数多了,但是,数组变的部分有序了,插入排序效率同样比高。
在这里插入图片描述
同理对每个分组进行排序(插入排序),使其每个分组各自有序。
在这里插入图片描述
最后设置增量为上一个增量的一半:1,则整个数组被分为一组,此时,整个数组已经接近有序了,插入排序效率高。
在这里插入图片描述
对以上数组再进行插入排序后,希尔排序就全部完成了。
有一点需要特别补充,对各个组进行插入排序的时候,并不是先对一个组进行排序完,再对另一个组排序。而是每个组并发执行的,每次插入一个元素进行排序。
在这里插入图片描述

public static void shellSort(int [] arr){
    int N = arr.length;
    //进行分组,最开始的时候,增量为数组的一半,即分成N/2组
    for(int gap=N/2;gap>0;gap/=2){
        /**
         * 对每组进行插入排序
         * 对各个组进行插入排序的时候,
         * 并不是先对一个组进行排序完,再对另一个组排序
         * 而是每个组并发,每次插入一个元素进行排序
         */
        for(int i = gap; i<N; i++){
            //将arr[i]插入到分组的正确位置上
            int insert = arr[i];
            int idx;
            for(idx = i-gap; idx >=0 && insert<arr[idx]; idx-=gap){
                arr[idx+gap] = arr[idx];
            }
            arr[idx+gap] = insert;
        }
    }
}

归并排序

归并(Merge)排序法是将两个有序表合并成一个新的有序表,即把待排序序列分为若干个子序列,每个子序列是有序的。然后再把有序子序列合并为整体有序序列。
合并方法:

设r[i…n]由两个有序子表r[i…m]和r[m+1…n]组成,两个子表长度分别为n-i +1、n-m。
1、j=m+1;k=i;i=i; //置两个子表的起始下标及辅助数组的起始下标
2、若i>m 或j>n,转⑷ //其中一个子表已合并完,比较选取结束
3、//选取r[i]和r[j]较小的存入辅助数组rf
        如果r[i]<r[j],rf[k]=r[i]; i++; k++; 转⑵
        否则,rf[k]=r[j]; j++; k++; 转⑵
4、//将尚未处理完的子表中元素存入rf
        如果i<=m,将r[i…m]存入rf[k…n] //前一子表非空
        如果j<=n ,  将r[j…n] 存入rf[k…n] //后一子表非空
5、合并结束。

代码实现

    public static int[] mergeSort(int[] nums, int low, int high) {
        int mid = (low + high) / 2;
        if (low < high) {
            // 左边
            mergeSort(nums, low, mid);
            // 右边
            mergeSort(nums, mid + 1, high);
            // 左右归并
            {
                int[] temp = new int[high - low + 1];
                int i = low;// 左指针
                int j = mid + 1;// 右指针
                int k = 0;

                // 把较小的数先移到新数组中
                while (i <= mid && j <= high) {
                    if (nums[i] < nums[j]) {
                        temp[k++] = nums[i++];
                    } else {
                        temp[k++] = nums[j++];
                    }
                }

                // 把左边剩余的数移入数组
                while (i <= mid) {
                    temp[k++] = nums[i++];
                }

                // 把右边边剩余的数移入数组
                while (j <= high) {
                    temp[k++] = nums[j++];
                }

                // 把新数组中的数覆盖nums数组
                for (int k2 = 0; k2 < temp.length; k2++) {
                    nums[k2 + low] = temp[k2];
                }
            }
        }
        return nums;
    }

堆排序(直接选择改良版)

堆排序是利用堆这种数据结构而设计的一种排序算法,堆排序是一种选择排序,它的最坏,最好,平均时间复杂度均为O(nlogn),它也是不稳定排序。
详细介绍可以参考下面这篇文章
https://www.cnblogs.com/chengxiao/p/6129630.html
堆排序是一种选择排序,概括如下:

  • 构建初始堆(大顶堆或小顶堆)
  • 交换堆顶元素和末尾元素(选择出了最大或最小元素
  • 剔除末尾元素,回到第一步重建堆的操作,如此循环直到结束。
    其中构建初始堆经推导复杂度为O(n),在交换并重建堆的过程中,需交换n-1次,而重建堆的过程中,根据完全二叉树的性质,[log2(n-1),log2(n-2)…1]逐步递减,近似为nlogn。所以堆排序时间复杂度一般认为就是O(nlogn)级。
    代码实现:
    public static void hepSort(int []arr){
        //1.构建大顶堆
        for(int i=arr.length/2-1;i>=0;i--){
            //从第一个非叶子结点从下至上,从右至左调整结构
            adjustHeap(arr,i,arr.length);
        }
        //2.调整堆结构+交换堆顶元素与末尾元素
        for(int j=arr.length-1;j>0;j--){
            //将堆顶元素与末尾元素进行交换
            int temp=arr[0];
            arr[0] = arr[j];
            arr[j] = temp;
            //重新对堆进行调整
            adjustHeap(arr,0,j);
        }

    }

    /**
     * 调整大顶堆(仅是调整过程,建立在大顶堆已构建的基础上)
     * @param arr
     * @param i
     * @param length
     */
    private static void adjustHeap(int []arr,int i,int length){
        int temp = arr[i];//先取出当前元素i
        for(int k=i*2+1;k<length;k=k*2+1){//从i结点的左子结点开始,也就是2i+1处开始
            if(k+1<length && arr[k]<arr[k+1]){//如果左子结点小于右子结点,k指向右子结点
                k++;
            }
            if(arr[k] >temp){//如果子节点大于父节点,将子节点值赋给父节点(不用进行交换)
                arr[i] = arr[k];
                i = k;
            }else{
                break;
            }
        }
        arr[i] = temp;//将temp值放到最终的位置
    }

基数排序

基数排序法是属于稳定性的排序,其时间复杂度为O (nlog®m),其中r为所采取的基数,而m为堆数,在某些时候,基数排序法的效率高于其它的稳定性排序法。
1.先按照个位数的数值,遍历数组,把它们分配至0到9的桶中。
2.将桶中的值重新串联起来
3.按照十位数的数值,遍历2串联起来的数组,把它们分配到0到9的桶中。
4.将桶中的值重新串联起来
5.如果待排序数组中有百位,千位数值,则重复3,4步操作,直至最高位排序完。
https://www.runoob.com/w3cnote/radix-sort.html

总结

在这里插入图片描述
希尔排序是选择排序的改良版,堆排序是快速排序的改良版。
这四种排序都属于不稳定排序。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是使用Java实现八大排序算法的示例代码: 1. 冒泡排序: ```java public class BubbleSort { public static void bubbleSort(int[] arr) { int n = arr.length; for (int i = 0; i < n - 1; i++) { for (int j = 0; j < n - 1 - i; j++) { if (arr[j] > arr[j + 1]) { int temp = arr[j]; arr[j] = arr[j + 1]; arr[j + 1] = temp; } } } } public static void main(String[] args) { int[] arr = {49, 38, 65, 97, 76, 13, 27, 49, 78, 34, 12, 64, 5, 4, 62, 99, 98, 54, 56, 17, 18, 23, 34, 15, 35, 25, 53, 51}; bubbleSort(arr); for (int i = 0; i < arr.length; i++) { System.out.println(arr[i]); } } } ``` 2. 选择排序: ```java public class SelectionSort { public static void selectionSort(int[] arr) { int n = arr.length; for (int i = 0; i < n - 1; i++) { int minIndex = i; for (int j = i + 1; j < n; j++) { if (arr[j] < arr[minIndex]) { minIndex = j; } } int temp = arr[i]; arr[i] = arr[minIndex]; arr[minIndex] = temp; } } public static void main(String[] args) { int[] arr = {49, 38, 65, 97, 76, 13, 27, 49, 78, 34, 12, 64, 5, 4, 62, 99, 98, 54, 56, 17, 18, 23, 34, 15, 35, 25, 53, 51}; selectionSort(arr); for (int i = 0; i < arr.length; i++) { System.out.println(arr[i]); } } } ``` 3. 插入排序: ```java public class InsertionSort { public static void insertionSort(int[] arr) { int n = arr.length; for (int i = 1; i < n; i++) { int key = arr[i]; int j = i - 1; while (j >= 0 && arr[j] > key) { arr[j + 1] = arr[j]; j--; } arr[j + 1] = key; } } public static void main(String[] args) { int[] arr = {49, 38, 65, 97, 76, 13, 27, 49, 78, 34, 12, 64, 5, 4, 62, 99, 98, 54, 56, 17, 18, 23, 34, 15, 35, 25, 53, 51}; insertionSort(arr); for (int i = 0; i < arr.length; i++) { System.out.println(arr[i]); } } } ``` 4. 希尔排序: ```java public class ShellSort { public static void shellSort(int[] arr) { int n = arr.length; for (int gap = n / 2; gap > 0; gap /= 2) { for (int i = gap; i < n; i++) { int temp = arr[i]; int j = i; while (j >= gap && arr[j - gap] > temp) { arr[j] = arr[j - gap]; j -= gap; } arr[j] = temp; } } } public static void main(String[] args) { int[] arr = {49, 38, 65, 97, 76, 13, 27, 49, 78, 34, 12, 64, 5, 4, 62, 99, 98, 54, 56, 17, 18, 23, 34, 15, 35, 25, 53, 51}; shellSort(arr); for (int i = 0; i < arr.length; i++) { System.out.println(arr[i]); } } } ``` 5. 归并排序: ```java public class MergeSort { public static void mergeSort(int[] arr, int left, int right) { if (left < right) { int mid = (left + right) / 2; mergeSort(arr, left, mid); mergeSort(arr, mid + 1, right); merge(arr, left, mid, right); } } public static void merge(int[] arr, int left, int mid, int right) { int n1 = mid - left + 1; int n2 = right - mid; int[] L = new int[n1]; int[] R = new int[n2]; for (int i = 0; i < n1; ++i) { L[i] = arr[left + i]; } for (int j = 0; j < n2; ++j) { R[j] = arr[mid + 1 + j]; } int i = 0, j = 0; int k = left; while (i < n1 && j < n2) { if (L[i] <= R[j]) { arr[k] = L[i]; i++; } else { arr[k] = R[j]; j++; } k++; } while (i < n1) { arr[k] = L[i]; i++; k++; } while (j < n2) { arr[k] = R[j]; j++; k++; } } public static void main(String[] args) { int[] arr = {49, 38, 65, 97, 76, 13, 27, 49, 78, 34, 12, 64, 5, 4, 62, 99, 98, 54, 56, 17, 18, 23, 34, 15, 35, 25, 53, 51}; mergeSort(arr, 0, arr.length - 1); for (int i = 0; i < arr.length; i++) { System.out.println(arr[i]); } } } ``` 6. 快速排序: ```java public class QuickSort { public static void quickSort(int[] arr, int low, int high) { if (low < high) { int pi = partition(arr, low, high); quickSort(arr, low, pi - 1); quickSort(arr, pi + 1, high); } } public static int partition(int[] arr, int low, int high) { int pivot = arr[high]; int i = low - 1; for (int j = low; j < high; j++) { if (arr[j] < pivot) { i++; int temp = arr[i]; arr[i] = arr[j]; arr[j] = temp; } } int temp = arr[i + 1]; arr[i + 1] = arr[high]; arr[high] = temp; return i + 1; } public static void main(String[] args) { int[] arr = {49, 38, 65, 97, 76, 13, 27, 49, 78, 34, 12, 64, 5, 4, 62, 99, 98, 54, 56, 17, 18, 23, 34, 15, 35, 25, 53, 51}; quickSort(arr, 0, arr.length - 1); for (int i = 0; i < arr.length; i++) { System.out.println(arr[i]); } } } ``` 7. 堆排序: ```java public class HeapSort { public static void heapSort(int[] arr) { int n = arr.length; for (int i = n / 2 - 1; i >= 0; i--) { heapify(arr, n, i); } for (int i = n - 1; i >= 0; i--) { int temp = arr[0]; arr[0] = arr[i]; arr[i] = temp; heapify(arr, i, 0); } } public static void heapify(int[] arr, int n, int i) { int largest = i; int left = 2 * i + 1; int right = 2 * i + 2; if (left < n && arr[left] > arr[largest]) { largest = left; } if (right < n && arr[right] > arr[largest]) { largest = right; } if (largest != i) { int swap = arr[i]; arr[i] = arr[largest]; arr[largest] = swap; heapify(arr, n, largest); } } public static void main(String[] args) { int[] arr = {49, 38, 65, 97, 76, 13, 27, 49, 78, 34, 12, 64, 5, 4, 62, 99, 98, 54, 56, 17, 18, 23, 34, 15, 35, 25, 53, 51}; heapSort(arr); for (int i = 0; i < arr.length; i++) { System.out.println(arr[i]); } } } ``` 8. 计数排序: ```java public class CountingSort { public static void countingSort(int[] arr) { int n = arr.length; int max = Arrays.stream(arr).max().getAsInt(); int min = Arrays.stream(arr).min().getAsInt(); int range = max - min + 1; int[] count = new int[range]; int[] output = new int[n]; for (int i = 0; i < n; i++) { count[arr[i] - min]++; } for (int i = 1; i < range; i++) { count[i] += count[i - 1]; } for (int i = n - 1; i >= 0; i--) { output[count[arr[i] - min] - 1] = arr[i]; count[arr[i] - min]--; } for (int i = 0; i < n; i++) { arr[i] = output[i]; } } public static void main(String[] args) { int[] arr = {49, 38, 65, 97, 76, 13, 27, 49, 78, 34, 12, 64, 5, 4, 62, 99, 98, 54, 56, 17, 18, 23, 34, 15, 35, 25, 53, 51}; countingSort(arr); for (int i = 0; i < arr.length; i++) { System.out.println(arr[i]); } } } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值