美文网首页
八种排序算法及Java实现

八种排序算法及Java实现

作者: 卡路fly | 来源:发表于2020-05-15 20:40 被阅读0次

1. 冒泡排序

image
private static void bubbleSort(int[] a) {
        if (a == null || a.length == 0) {
            return;
        }

        int length = a.length;

        for (int i = 0; i < length - 1; i++) {
            for (int j = i; j < length - 1 - i; j++) {
                if (a[j] > a[j + 1])
                    swap(a, j, j + 1);
            }
        }
    }

2. 快排

①. 从数列中挑出一个元素,称为”基准”(pivot)。
②. 重新排序数列,所有比基准值小的元素摆放在基准前面,所有比基准值大的元素摆在基准后面(相同的数可以到任一边)。在这个分区结束之后,该基准就处于数列的中间位置。这个称为分区(partition)操作。
③. 递归地(recursively)把小于基准值元素的子数列和大于基准值元素的子数列排序。
递归到最底部时,数列的大小是零或一,也就是已经排序好了。


  /**
     * 快排
     * @param arr
     * @param low
     * @param high
     */
    public static void quickSort(int arr[], int low, int high) {
        if (arr == null || arr.length <= 0) {
            return;
        }
        if (low >= high) {
            return;
        }

        int left = low;
        int right = high;
        int temp = arr[left]; //挖坑1:保存基准的值

        while (left < right) {
            while (left < right && arr[right] >= temp) {
                right--;
            }
            arr[left] = arr[right]; //坑2:从后向前找到比基准小的元素,插入到基准位置坑1中
            while (left < right && arr[left] <= temp) {
                left++;
            }
            arr[right] = arr[left]; //坑3:从前往后找到比基准大的元素,放到刚才挖的坑2中
        }
        arr[left] = temp; //基准值填补到坑3中,准备分治递归快排
        System.out.println("Sorting: " + Arrays.toString(arr));
        quickSort(arr, low, left - 1);
        quickSort(arr, left + 1, high);
    }

3. 简单选择排序

每次选取最大的一个数字,放在数组未排序的最后一个,直到排序结束。

/**
     * 选择排序
     *
     */
    private static void selectSort2(int[] a) {
        if (a == null || a.length == 0) {
            return;
        }
        int n = a.length;

        while (n > 1) {
            int pos = findMaxIndex(a, n);
            swap(a, pos, n - 1);
            n--;
        }

    }

    /**
     * 获取数组中最大数字的index
     */
    public static int findMaxIndex(int[] a, int n) {
        int max = a[0];
        int pos = 0;
        for (int i = 1; i < n; i++) {
            if (a[i] > max) {
                max = a[i];
                pos = i;
            }
        }
        return pos;
    }

4. 堆排序

堆排序是一种树形选择排序方法,特点是在排序过程中将L[1···n]看成是一颗完全二叉树的顺序存储结构,利用完全二叉树中双亲结点和孩子结点的内在关系,在当前无序区中选择关键字最大(或最小)元素。

  • 父节点 parent = (i-1)/2;
  • 左子节点 c1 = 2i+1;
  • 右子节点 c2 = 2i+2;

数字:87 45 78 32 17 65 53 09

①从上到下,从左到右建堆

int parent = (last_node - 1) / 2;
根据数组最后一位可以得出【09】的根节点为【32】
倒着进行heapify

② 从倒数第二层左节点开始,与左右子树进行比较交换

③ 从第二步max位置依次递归直到顶端为最大数

④ 将根节点【87】与最后一位【09】交换,移出最后一位【87】,最后对根节点进行重新heapfy,将【09】与【78】进行交换……直到排序完成

 /**
     * 堆排序
     *
     * @param a
     */
    private static void heapSort(int[] a) {
        if (a == null || a.length == 0) {
            return;
        }
        int n = a.length;
        buildHeap(a, n);

        for (int i = n - 1; i >= 0; i--) {
            swap(a, i, 0); // 交换根节点和最后一个节点
            heapify(a, i, 0); // 重新heapify
        }
    }

    /**
     * 父节点 parent = (i-1)/2;
     * 左子节点 c1 = 2i+1;
     * 右子节点 c2 = 2i+2;
     */
    private static void heapify(int[] tree, int n, int i) {
        if (i >= n)
            return;
        int c1 = 2 * i + 1;
        int c2 = 2 * i + 2;

        /*
         * 左中右三个节点找最大值
         */
        int max = i;

        if (c1 < n && tree[c1] > tree[max])
            max = c1;
        if (c2 < n && tree[c2] > tree[max])
            max = c2;
        if (max != i) {
            // 将最大值与i进行交换
            swap(tree, max, i);
            heapify(tree, n, max);
        }

    }

    private static void buildHeap(int[] tree, int n) {
        int last_node = n - 1;
        int parent = (last_node - 1) / 2;
        for (int i = parent; i >= 0; i--) {
            heapify(tree, n, i);
        }
    }

5. 直接插入排序

从第二个数字开始,依次把数字插入到合适的位置。


   /**
     * 插入排序
     */
    private static void insertSort(int[] a) {
        if (a == null || a.length == 0) {
            return;
        }
        int length = a.length;

        for (int i = 1; i < length; i++) {
            insert(a, i);
        }
    }

    /**
     * 把第n个数插入到数组a合适的位置
     */
    private static void insert(int[] a, int n) {
        int key = a[n];
        int i = n;
        while (a[i - 1] > key) {
            a[i] = a[i - 1];
            i--;
            if (i == 0)
                break;
        }
        a[i] = key;

    }

6. 希尔排序

将待排序数组按照步长gap进行分组,然后将每组的元素利用直接插入排序的方法进行排序;每次再将gap折半减小,循环上述操作;当gap=1时,利用直接插入,完成排序。


/**
     * 希尔排序
     */
    public static void shellSort(int a[]) {
        if (a == null || a.length == 0) {
            return;
        }

        int n = a.length;

        for (int gap = n / 2; gap >= 1; gap = gap / 2) {
            for (int i = 0; i + gap < n; i++) {
                for (int j = 0; j + gap < n; j += gap) {
                    if (a[j] > a[j + gap]) {
                        swap(a, j, j + gap);
                    }
                }
            }
        }
    }

7. 归并排序

/**
     * 归并
     * 2, 8, 9, 10, 4, 5, 6, 7
     *
     * @param a
     */

    public static void mergeSort(int[] a, int l, int r) {
        if (l == r)
            return;
        int mid = (l + r) / 2;
        // 左归并,右归并
        mergeSort(a, l, mid);
        mergeSort(a, mid + 1, r);
        merge(a, l, mid + 1, r);
    }

    /**
     * 合并一个从l-mid,r-mid排好序的数组
     * 2, 8, 9, 10, 4, 5, 6, 7
     * l = 0,mid=4,r=7
     */
    private static void merge(int[] a, int l, int mid, int r) {
        int leftSize = mid - l;
        int rightSize = r - mid + 1;
        int left[] = new int[leftSize];
        int right[] = new int[rightSize];
        /*
         * 1. 构建两个数组
         * left [2,8,9,10]
         * right[4,5,6,7]
         */
        for (int i = l; i < mid; i++) {
            left[i - l] = a[i];
        }
        for (int i = mid; i <= r; i++) {
            right[i - mid] = a[i];
        }

        /**
         * 2.合并成1个
         * i指向左数组第一个
         * j指向右数组第一个
         * k 指向空数组最左边
         */
        int i = 0;
        int j = 0;
        int k = l;

        while (i < leftSize && j < rightSize) {
            if (left[i] < right[j]) {
                a[k] = left[i];
                i++;
                k++;
            } else {
                a[k] = right[j];
                j++;
                k++;
            }
        }


        /**
         * 如果上面循环完毕,i仍旧没到达顶部,则把剩下的数字抄一下
         */
        while (i < leftSize) {
            a[k] = left[i];
            i++;
            k++;
        }


        /**
         * 如果上面循环完毕,j仍旧没到达顶部,则把剩下的数字抄一下
         */
        while (j < rightSize) {
            a[k] = right[j];
            j++;
            k++;
        }
    }

8. 基数排序

  • ① 取得数组中的最大数,并取得位数;
  • ② arr为原始数组,从最低位开始取每个位组成radix数组;
  • ③ 对radix进行计数排序(利用计数排序适用于小范围数的特点);


整理自https://juejin.im/post/5b95da8a5188255c775d8124#heading-0

相关文章

  • 排序

    八大排序算法 一、归并排序 递归及非递归的JAVA实现 二、快速排序 快排算法JAVA实现 三、堆排序 堆排序堆排...

  • 数据结构&算法(一)

    一、Java实现快速排序算法 二、Java实现折半插入排序算法 三、Java实现冒泡排序算法

  • 一文搞定十大经典排序算法(Java实现)

    本文总结十大经典排序算法及变形,并提供Java实现。参考文章:十大经典排序算法总结(Java语言实现)快速排序算法...

  • 八种排序算法原理及Java实现

    八种排序算法原理及Java实现 概述 排序算法分为内部排序和外部排序,内部排序把数据记录放在内存中进行排序,而外部...

  • 排序算法

    常见排序算法及JAVA实现 简单选择排序(SelectSort) 选择排序思想很简单,对所有元素进行遍历,选出最小...

  • java 实现排序算法之「插入排序」

    java 实现排序算法系列 这是 Java 实现排序算法的第三篇文章——插入排序算法。插入排序可以说成是「一类」简...

  • 快速排序

    手写java版快速排序算法实现

  • 排序算法

    常见排序算法比较 参考资料:各种排序算法比较 参考资料:快速排序算法 必须知道的八大种排序算法【java实现】(一...

  • 排序算法最强总结及其代码实现(Python/Java)

    前言 本文总结了常用的全部排序算法,内容包括: 排序算法的定义和思路 排序算法的代码实现:Python和Java,...

  • 7大经典的排序算法总结实现

    作者 : 专注J2EE来源 : 博客园 常见排序算法总结与实现 本文使用Java实现这几种排序。以下是对排序算法总...

网友评论

      本文标题:八种排序算法及Java实现

      本文链接:https://www.haomeiwen.com/subject/mmjhohtx.html