总结5种比较高效常用的排序算法

1 概述

本文对比较常用且比较高效的排序算法进行了总结和解析,并贴出了比较精简的实现代码,包括选择排序、插入排序、归并排序、希尔排序、快速排序等。算法性能比较如下图所示:

2 选择排序

选择排序的第一趟处理是从数据序列所有n个数据中选择一个最小的数据作为有序序列中的第1个元素并将它定位在第一号存储位置,第二趟处理从数据序列的n-1个数据中选择一个第二小的元素作为有序序列中的第2个元素并将它定位在第二号存储位置,依此类推,当第n-1趟处理从数据序列的剩下的2个元素中选择一个较小的元素作为有序序列中的最后第2个元素并将它定位在倒数第二号存储位置,至此,整个的排序处理过程就已完成。

代码如下:

public class SelectionSort {
    public void selectionSort(int[] array) {
        int temp;
        for (int i = 0; i < array.length - 1; i++) {
            for (int j = i + 1; j <= array.length - 1; j++) {// 第i个和第j个比较j可以取到最后一位,所以要用j<=array.length-1
                if (array[i] > array[j]) {// 注意和冒泡排序的区别,这里是i和j比较。
                    temp = array[i];
                    array[i] = array[j];
                    array[j] = temp;
                }
            }
            // 打印每趟排序结果
            for (int m = 0; m <= array.length - 1; m++) {
                System.out.print(array[m] + "\t");
            }
            System.out.println();
        }
    }

    public static void main(String[] args) {
        SelectionSort selectionSort = new SelectionSort();
        int[] array = { 5, 69, 12, 3, 56, 789, 2, 5648, 23 };
        selectionSort.selectionSort(array);
        for (int m = 0; m <= array.length - 1; m++) {
            System.out.print(array[m] + "\t");
        }
    }
}

3 插入排序

直接插入排序法的排序原则是:将一组无序的数字排列成一排,左端第一个数字为已经完成排序的数字,其他数字为未排序的数字。然后从左到右依次将未排序的数字插入到已排序的数字中。

代码如下:

public class InsertSort {
    public void insertSort(int[] array, int first, int last) {
        int temp, i, j;
        for (i = first + 1; i <= last - 1; i++) {// 默认以第一个数为有序序列,后面的数为要插入的数。
            temp = array[i];
            j = i - 1;
            while (j >= first && array[j] > temp) {// 从后进行搜索如果搜索到的数小于temp则该数后移继续搜索,直到搜索到小于或等于temp的数即可
                array[j + 1] = array[j];
                j--;
            }
            array[j + 1] = temp;
            // 打印每次排序结果
            for (int m = 0; m <= array.length - 1; m++) {
                System.out.print(array[m] + "\t");
            }
            System.out.println();
        }
    }

    public static void main(String[] args) {
        InsertSort insertSort = new InsertSort();
        int[] array = { 5, 69, 12, 3, 56, 789, 2, 5648, 23 };
        insertSort.insertSort(array, 0, array.length);// 注意此处是0-9而不是0-8
        for (int i = 0; i <= array.length - 1; i++) {
            System.out.print(array[i] + "\t");
        }
    }
}

4 归并排序

算法描述:

把序列分成元素尽可能相等的两半。

把两半元素分别进行排序。

把两个有序表合并成一个。

代码如下:

public class MergeSortTest {
    public void sort(int[] array, int left, int right) {
        if (left >= right)
            return;
        // 找出中间索引
        int center = (left + right) / 2;
        // 对左边数组进行递归
        sort(array, left, center);
        // 对右边数组进行递归
        sort(array, center + 1, right);
        // 合并
        merge(array, left, center, right);
        // 打印每次排序结果
        for (int i = 0; i < array.length; i++) {
            System.out.print(array[i] + "\t");
        }
        System.out.println();

    }

    /**
     * 将两个数组进行归并,归并前面2个数组已有序,归并后依然有序
     *
     * @param array
     *            数组对象
     * @param left
     *            左数组的第一个元素的索引
     * @param center
     *            左数组的最后一个元素的索引,center+1是右数组第一个元素的索引
     * @param right
     *            右数组最后一个元素的索引
     */
    public void merge(int[] array, int left, int center, int right) {
        // 临时数组
        int[] tmpArr = new int[array.length];
        // 右数组第一个元素索引
        int mid = center + 1;
        // third 记录临时数组的索引
        int third = left;
        // 缓存左数组第一个元素的索引
        int tmp = left;
        while (left <= center && mid <= right) {
            // 从两个数组中取出最小的放入临时数组
            if (array[left] <= array[mid]) {
                tmpArr[third++] = array[left++];
            } else {
                tmpArr[third++] = array[mid++];
            }
        }
        // 剩余部分依次放入临时数组(实际上两个while只会执行其中一个)
        while (mid <= right) {
            tmpArr[third++] = array[mid++];
        }
        while (left <= center) {
            tmpArr[third++] = array[left++];
        }
        // 将临时数组中的内容拷贝回原数组中
        // (原left-right范围的内容被复制回原数组)
        while (tmp <= right) {
            array[tmp] = tmpArr[tmp++];
        }
    }

    public static void main(String[] args) {
        int[] array = new int[] { 5, 69, 12, 3, 56, 789, 2, 5648, 23 };
        MergeSortTest mergeSortTest = new MergeSortTest();
        mergeSortTest.sort(array, 0, array.length - 1);
        System.out.println("排序后的数组:");
        for (int m = 0; m <= array.length - 1; m++) {
            System.out.print(array[m] + "\t");
        }
    }
}

5 希尔排序

希尔排序又称“缩小增量排序”,该方法的基本思想是:先将整个待排元素序列分割成若干个子序列(由相隔某 个“增量”的元素组成的)分别进行直接插入排序,然后依次缩减增量再进行排序,待整个序列中的元素基本有序(增量足够小)时,再对全体元素进行一次直接插 入排序。因为直接插入排序在元素基本有序的情况下(接近最好情况),效率是很高的,因此希尔排序在时间效率上比前两种方法有较大提高。

代码如下:

public class ShellSort {
    public void shellSort(int[] array, int n) {
        int i, j, gap;
        int temp;
        for (gap = n / 2; gap > 0; gap /= 2) {// 计算gap大小
            for (i = gap; i < n; i++) {// 将数据进行分组
                for (j = i - gap; j >= 0 && array[j] > array[j + gap]; j -= gap) {// 对每组数据进行插入排序
                    temp = array[j];
                    array[j] = array[j + gap];
                    array[j + gap] = temp;
                }
                // 打印每趟排序结果
                for (int m = 0; m <= array.length - 1; m++) {
                    System.out.print(array[m] + "\t");
                }
                System.out.println();
            }
        }
    }

    public static void main(String[] args) {
        ShellSort shellSort = new ShellSort();
        int[] array = { 5, 69, 12, 3, 56, 789, 2, 5648, 23 };
        shellSort.shellSort(array, array.length);// 注意为数组的个数
        for (int m = 0; m <= array.length - 1; m++) {
            System.out.print(array[m] + "\t");
        }
    }
}

6 快速排序

快速排序(Quicksort)是对冒泡排序的一种改进。由C. A. R. Hoare在1962年提出。它的基本思想是:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然 后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。

代码如下:

public class QuickSort {
    public int partition(int[] sortArray, int low, int height) {
        int key = sortArray[low];// 刚开始以第一个数为标志数据
        while (low < height) {
            while (low < height && sortArray[height] >= key)
                height--;// 从后面开始找,找到比key值小的数为止
            sortArray[low] = sortArray[height];// 将该数放到key值的左边
            while (low < height && sortArray[low] <= key)
                low++;// 从前面开始找,找到比key值大的数为止
            sortArray[height] = sortArray[low];// 将该数放到key值的右边
        }
        sortArray[low] = key;// 把key值填充到low位置,下次重新找key值
        // 打印每次排序结果
        for (int i = 0; i <= sortArray.length - 1; i++) {
            System.out.print(sortArray[i] + "\t");
        }
        System.out.println();
        return low;
    }

    public void sort(int[] sortArray, int low, int height) {
        if (low < height) {
            int result = partition(sortArray, low, height);
            sort(sortArray, low, result - 1);
            sort(sortArray, result + 1, height);
        }
    }

    public static void main(String[] args) {
        QuickSort quickSort = new QuickSort();
        int[] array = { 5, 69, 12, 3, 56, 789, 2, 5648, 23 };
        for (int i = 0; i <= array.length - 1; i++) {
            System.out.print(array[i] + "\t");
        }
        System.out.println();
        quickSort.sort(array, 0, 8);
        for (int i = 0; i <= array.length - 1; i++) {
            System.out.print(array[i] + "\t");
        }
    }
}

  这里只贴出了自己总结的部分排序算法,更多的算法总结可参考自己另外一篇文章:Java自学之道

  原创文章欢迎转载,转载时请注明出处。

  作者推荐文章:

    》Java自学之道

    》Eclipse中部署Hadoop2.3.0并直接在Eclipse中提交mapreduce任务

    》Java如何获取系统信息(包括操作系统、jvm、cpu、内存、硬盘、网络等)

    》Java如何生成二维码过程详解

时间: 2024-10-19 05:04:24

总结5种比较高效常用的排序算法的相关文章

7 种常用的排序算法-视觉直观感受

7 种常用的排序算法-可视化 1. 快速排序 介绍: 快速排序是由东尼·霍尔所发展的一种排序算法.在平均状况下,排序 n 个项目要Ο(n log n)次比较.在最坏状况下则需要Ο(n2)次比较,但这种状况并不常见.事实上,快速排序通常明显比其他Ο(n log n) 算法更快,因为它的内部循环(inner loop)可以在大部分的架构上很有效率地被实现出来,且在大部分真实世界的数据,可以决定设计的选择,减少所需时间的二次方项之可能性. 步骤: 从数列中挑出一个元素,称为 “基准”(pivot),

几种常用的排序算法总结

主要针对于插入排序,交换(冒泡和快速),选择,堆排序,归并这几种排序的基本原理和时间复杂度,及空间复杂度的一个总结. 一.插入排序 基本执行过程:3  5  2  7  9  8 1.从小到大:从第二个数开始,每次比较都与前边的几个数进行比较 但是从大到小,要先与前边排好序的几个数中的最大的开始进行比较即倒序比较,依次往前推. 如:5 先与3进行比较,比3大,所以直接排在3的后边为:3 5: 2要先与5进行比较,比5小,再与3比较,比3小,所以排序后为 2 3 5: 7要先与5比,比5大,所以直

JavaScript实现常用的排序算法

▓▓▓▓▓▓ 大致介绍 由于最近要考试复习,所以学习js的时间少了 -_-||,考试完还会继续的努力学习,这次用原生的JavaScript实现以前学习的常用的排序算法,有冒泡排序.快速排序.直接插入排序.希尔排序.直接选择排序 ▓▓▓▓▓▓ 交换排序 交换排序是一类在排序过程中借助于交换操作来完成排序的方法,基本思想是两两比较排序记录的关键字,如果发现两个关键字逆序,则将两个记录位置互换,重复此过程,直到该排序列中所有关键字都有序为止,接下来介绍交换排序中常见的冒泡排序和快速排序 ▓▓▓▓▓▓

java SE 常用的排序算法

java程序员会用到的经典排序算法实现 常用的排序算法(以下代码包含的)有以下五类: A.插入排序(直接插入排序.希尔排序) B.交换排序(冒泡排序.快速排序) C.选择排序(直接选择排序.堆排序) D.归并排序 E.分配排序(基数排序) 以下算法都是可以实现的,但是什么情况使用什么算法都是根据实际情况选用的. 如果有用的话就顶起吧,谢谢. import java.util.ArrayList; import java.util.List; public class Sort { // test

【计算机基础】 常用的排序算法的时间复杂度和空间复杂度

常用的排序算法的时间复杂度和空间复杂度 排序法 最差时间分析 平均时间复杂度 稳定度 空间复杂度 冒泡排序 O(n2) O(n2) 稳定 O(1) 快速排序 O(n2) O(n*log2n) 不稳定 O(log2n)~O(n) 选择排序 O(n2) O(n2) 稳定 O(1) 二叉树排序 O(n2) O(n*log2n) 不一顶 O(n) 插入排序 O(n2) O(n2) 稳定 O(1) 堆排序 O(n*log2n) O(n*log2n) 不稳定 O(1) 希尔排序 O O 不稳定 O(1) 1

C#中常用的排序算法的时间复杂度和空间复杂度

常用的排序算法的时间复杂度和空间复杂度 常用的排序算法的时间复杂度和空间复杂度 排序法 最差时间分析 平均时间复杂度 稳定度 空间复杂度 冒泡排序 O(n2) O(n2) 稳定 O(1) 快速排序 O(n2) O(n*log2n) 不稳定 O(log2n)~O(n) 选择排序 O(n2) O(n2) 稳定 O(1) 二叉树排序 O(n2) O(n*log2n) 不一顶 O(n) 插入排序 O(n2) O(n2) 稳定 O(1) 堆排序 O(n*log2n) O(n*log2n) 不稳定 O(1)

常用查找排序算法

1.折半查找算法: 对于一个已排好序的数组,若要查找某元素是否属于数组中,则可以用这种算法. 返回找到的元素在数组中的下标,找不到则返回-1 #include <stdio.h> #define LEN 8 int a[LEN] = { 1, 3, 3, 3, 4, 5, 6, 7 }; int binarysearch(int number) { int mid, start = 0, end = LEN - 1; while (start <= end) { mid = (start

八种常用的排序算法(转)

下面要讲到的8种排序都属于内部排序,既在内存中完成,主要从理论原理方面来分析的.    插入排序 ①直接插入排序 例:六个数12 15 9 20  6 31 24 用直接插入排序,如下图: 思路: 第一步:从给出的六个数中,随便拿出一个数,比如12,形成一个有序的数据序列(一个数当然是有序的数据序列了,不看12之外的数,就当其他的数不存在): 第二步:从剩下的五个数中挑出一个数来,比如15,和刚才的12作比较,12<15,因此,放在12后面,形成数据序列12 15: 第三步:从剩下的四个数中挑出

几种常用的排序算法

什么是算法 我想很多程序员恐怕误解了「算法」的意义,一想到算法就是动态规划,机器学习之类的高大名词.算法其实就是数学中的「解题过程」,解题过程要求精确,考虑各种情况,需要人看得懂.算法不需要你在键盘上选择什么编程语言实现,只需要在本子上详细的写出每一个步骤就可以了. 算法真的很重要吗? 我经常在社区里看到有人说初级开发不需要懂算法,这是非常真切的,很多的业务构建都是很常规的套路,查个数据库返回,没有太多复杂的计算,哪需要什么解题过程. 但是我想遇到稍微复杂一点的业务,或者想要系统运行得更流畅.更