【排序算法】交换排序

一、排序算法概述

所谓排序,即按照一定规则对数据进行排列,比如递增或递减的方式,实现这种排列的算法就是排序算法了,而常见的排序算法分类标准有:内部排序外部排序。内部排序是数据记录在内存中进行排序,外部排序是因排序的数据很大,一次不能容纳全部的排序记录,在排序过程中需要访问外存。

常见的内部排序算法有八种:插入排序、希尔排序、选择排序、冒泡排序、归并排序、快速排序、堆排序、基数排序等。外部排序的话,采用多路归并排序算法,将文件划分为几个能读入内存的小部分,然后分别读入进行排序,经过多次处理即可完成对大文件的排序。排序算法的大致分类如图所示:

实际应用中,内部排序的对象是整数,而排序的规则包括从小到大排序和从大到小排序,每一种排序算法都有其各自的特点,在特定的场合也有着不错的执行效率,后面会一一进行分析和整理,以数组元素为例,先看一下交换排序。

二、冒泡排序

它是一种最简单、最直观的排序方式,属于交换排序,整个排序过程就像水泡的浮起过程一样,故因此而得名冒泡排序。核心思路是相邻的数据进行交换达到排序目的。

冒泡排序的步骤大致如下:

  1). 从一开始,对前后相邻的元素去比较,若前面的元素大于后面的元素,则交换二者的位置。

  2). 针对所有的元素重复上述步骤,直到从小到大的完成排序。

Demo演示:

public class ArraySortDemo{
    /** 以整形数组为例测试 */
    public static void main(String[] args) {
        int[] arr = {4, 3, 7, 89, 23, 6, 20, 15, 32, 35};
        int[] result = bubbleSort(arr);
        for (int i = 0; i < result.length - 1; i++) {
            System.out.print(" " + result[i]); // 3 4 6 7 15 20 23 32 35 89
        }
    }
    /** 冒泡排序 */
    public static int[] bubbleSort(int[] num) {
        for (int i = 0; i < num.length - 1; i++) {
            for (int j = 0; j < num.length - 1 - i; j++) {
                // 相邻的元素进行比较
                if (num[j] > num[j + 1]) {
                    // 使用临时变量交换元素
                    int temp = num[j];
                    num[j] = num[j + 1];
                    num[j + 1] = temp;
                }
            }
        }
        return num;
    }
}

优缺点分析:

  • 优点:就是简单、直观,空间复杂度较低,是一种稳定排序。
  • 缺点:时间复杂度较高,排序速度慢。

三、快速排序

它可看作是冒泡排序的改进版,也属于交换排序,核心思路是将数据按照基准值划分为两部分,小于基准值的放在一边,大于基准值的放在另一边,然后再选择一个基准值多次递归上述操作,最终达到交换排序目的。因此,快速排序利用的是分治思想和递归思想。

快速排序的步骤大致如下:

  1). 选定一个分界值作为基准,将数组一分为二。

  2). 数组的所有元素比基准值小的会放在基准的左边,所有元素比基准值大的会在基准的右边。

  3). 基准的左边和基准的右边又可以各选定一个分界值作为基准,继续排序,递归的进行上述过程,最终整个数组就会按从小到大顺序完成排序。

Demo演示:

public class ArraySortDemo{
    /** 快速排序测试 */
	public static void main(String[] args) {
        int[] num = {9, 18, 7, 99, 43, 66, 10, 12, 2, 45};
        fast(num, 0, num.length - 1);
    }

    /** 对数组 或数组指定范围的元素进行快速排序 */
    public static void fast(int[] arry, int first, int last) {
        if (last > first) {
            // 选择基准值
            int pivotIndex = fastvoid(arry, first, last);
            // 前半部分
            fast(arry, first, pivotIndex - 1);
            // 后半部分
            fast(arry, pivotIndex + 1, last);
        }
    }
 
    /** 从前向后和从后向前依次和主元比较,当前面的元素比主元大,后面的元素比主元小则这两个元素互换位置 */
    public static int fastvoid(int[] arry, int first, int last) {
        int privot = arry[first];
        int low = first + 1;
        int high = last;
        while (low < high) {
            while (low <= high && arry[low] <= privot) {
                low++;
            }
            while (low <= high && arry[high] >= privot) {
                high--;
            }
            if (high > low) {
                int temp = arry[high];
                arry[high] = arry[low];
                arry[low] = temp;
            }
        }

        while (high > first && arry[high] >= privot) {
            high--;
        }
        if (privot > arry[high]) {
            arry[first] = arry[high];
            arry[high] = privot;
            return high;
        } else {
            return first;
        }
    }
}

优缺点分析:

  • 优点:作为冒泡排序的改进版,基于分治策略和递归策略,时间复杂度较低,排序速度快。
  • 缺点:是一种不稳定排序。

小结

排序算法是基本的算法的一部分,常见的排序算法有上面罗列的八种内部算法,学习和掌握它们的核心思路最为重要,这里,先重点整理了两种交换排序的算法。

参考:《Java常用算法手册(第3版)》+ 百度图片

猜你喜欢

转载自blog.csdn.net/qq_29119581/article/details/112652869