Java实现常见排序算法的优化

Java实现常见排序算法的优化攻略

本文将介绍如何使用Java实现几种常见的排序算法并对其进行优化,提高算法效率。

常见排序算法的分类

常见的排序算法分为两类:

  1. 比较类排序: 直接通过比较元素大小来确定元素间的相对次序,如冒泡排序、选择排序、插入排序、希尔排序、归并排序和快速排序等。这类算法时间复杂度下限为Ω(nlogn),也是大多数排序算法的时间复杂度上限。
  2. 非比较类排序: 不直接比较元素的大小,而根据具体问题的特定要求,通过非比较的方法确定元素间的相对次序,如计数排序、桶排序、基数排序等。这类算法时间复杂度可以达到O(n)。

常见排序算法的实现与优化

冒泡排序

冒泡排序是一种简单的交换排序算法,时间复杂度为O(n^2)。其基本思想是将相邻的元素两两比较,如果前面的元素大于后面的元素则交换这两个元素的位置,直到没有任何一对数字需要比较。

普通实现:

public static void bubbleSort(int[] arr) {
    for (int i = 0; i < arr.length - 1; i++) {
        for (int j = 0; j < arr.length - 1 - i; j++) {
            if (arr[j] > arr[j + 1]) {
                int temp = arr[j];
                arr[j] = arr[j + 1];
                arr[j + 1] = temp;
            }
        }
    }
}

优化1: 增加一个标志位,如果在一次排序中没有进行任何交换,则说明序列已具有有序性,排序提前结束。

public static void bubbleSort1(int[] arr) {
    boolean flag;
    for (int i = 0; i < arr.length - 1; i++) {
        flag = false;
        for (int j = 0; j < arr.length - 1 - i; j++) {
            if (arr[j] > arr[j + 1]) {
                int temp = arr[j];
                arr[j] = arr[j + 1];
                arr[j + 1] = temp;
                flag = true;
            }
        }
        if (!flag) {
            break;
        }
    }
}

优化2: 记录最后一次交换的位置,该位置以下的数据已经有序,无需再进行比较。

public static void bubbleSort2(int[] arr) {
    boolean flag;
    int lastExchangeIndex = 0;
    int sortBorder = arr.length - 1;
    for (int i = 0; i < arr.length - 1; i++) {
        flag = false;
        for (int j = 0; j < sortBorder; j++) {
            if (arr[j] > arr[j + 1]) {
                int temp = arr[j];
                arr[j] = arr[j + 1];
                arr[j + 1] = temp;
                flag = true;
                lastExchangeIndex = j;
            }
        }
        sortBorder = lastExchangeIndex;
        if (!flag) {
            break;
        }
    }
}

快速排序

快速排序是一种基于分治思想的排序算法,时间复杂度为O(nlogn)。其基本思想是选取一个数(一般为第一个数)作为基准,将小于基准的数放到其左边,大于基准的数放到其右边,然后再依次对左右两部分进行递归排序。

普通实现:

public static void quickSort(int[] arr, int left, int right) {
    if (left < right) {
        int partitionIndex = partition(arr, left, right);
        quickSort(arr, left, partitionIndex - 1);
        quickSort(arr, partitionIndex + 1, right);
    }
}

private static int partition(int[] arr, int left, int right) {
    int pivot = arr[left];
    int i = left;
    int j = right;
    while (i < j) {
        while (i < j && arr[j] >= pivot) {
            j--;
        }
        while (i < j && arr[i] <= pivot) {
            i++;
        }
        if (i < j) {
            int temp = arr[i];
            arr[i] = arr[j];
            arr[j] = temp;
        }
    }
    arr[left] = arr[i];
    arr[i] = pivot;
    return i;
}

优化1: 选取基准点的方法可以优化,在序列的开头、结尾和中间位置各选取一个元素,取这三个数的中位数作为基准。

private static int median3(int[] arr, int left, int right) {
    int mid = left + (right - left) / 2;
    if (arr[left] > arr[mid]) {
        int temp = arr[left];
        arr[left] = arr[mid];
        arr[mid] = temp;
    }
    if (arr[left] > arr[right]) {
        int temp = arr[left];
        arr[left] = arr[right];
        arr[right] = temp;
    }
    if (arr[mid] > arr[right]) {
        int temp = arr[mid];
        arr[mid] = arr[right];
        arr[right] = temp;
    }
    int pivot = arr[mid];
    arr[mid] = arr[left];
    arr[left] = pivot;
    return pivot;
}

public static void quickSort1(int[] arr, int left, int right) {
    if (left < right) {
        int partitionIndex = partition1(arr, left, right);
        quickSort1(arr, left, partitionIndex - 1);
        quickSort1(arr, partitionIndex + 1, right);
    }
}

private static int partition1(int[] arr, int left, int right) {
    int pivot = median3(arr, left, right);
    int i = left;
    int j = right;
    while (i < j) {
        while (i < j && arr[j] >= pivot) {
            j--;
        }
        while (i < j && arr[i] <= pivot) {
            i++;
        }
        if (i < j) {
            int temp = arr[i];
            arr[i] = arr[j];
            arr[j] = temp;
        }
    }
    arr[left] = arr[i];
    arr[i] = pivot;
    return i;
}

优化2: 对于小规模的子序列,使用插入排序。

public static void quickSort2(int[] arr, int left, int right) {
    if (left < right) {
        if (right - left + 1 < INSERTION_SORT_THRESHOLD) {
            insertionSort(arr, left, right);
        } else {
            int partitionIndex = partition1(arr, left, right);
            quickSort2(arr, left, partitionIndex - 1);
            quickSort2(arr, partitionIndex + 1, right);
        }
    }
}

private static void insertionSort(int[] arr, int left, int right) {
    for (int i = left + 1; i <= right; i++) {
        int temp = arr[i];
        int j = i - 1;
        while (j >= left && arr[j] > temp) {
            arr[j + 1] = arr[j];
            j--;
        }
        arr[j + 1] = temp;
    }
}

示例说明

示例1——冒泡排序

public static void main(String[] args) {
    int[] arr = {9, 8, 7, 6, 5, 4, 3, 2, 1};
    System.out.println("排序前:" + Arrays.toString(arr));
    bubbleSort2(arr);
    System.out.println("排序后:" + Arrays.toString(arr));
}

输出结果:

排序前:[9, 8, 7, 6, 5, 4, 3, 2, 1]
排序后:[1, 2, 3, 4, 5, 6, 7, 8, 9]

示例2——快速排序

public static void main(String[] args) {
    int[] arr = {45, 99, 12, 19, 33, 78, 53, 46, 28, 89, 67, 56};
    System.out.println("排序前:" + Arrays.toString(arr));
    quickSort2(arr, 0, arr.length - 1);
    System.out.println("排序后:" + Arrays.toString(arr));
}

输出结果:

排序前:[45, 99, 12, 19, 33, 78, 53, 46, 28, 89, 67, 56]
排序后:[12, 19, 28, 33, 45, 46, 53, 56, 67, 78, 89, 99]

总结

通过对常见排序算法的优化,可以大大提高算法效率。在实际开发中要根据具体的需求和数据规模来选择合适的排序算法并进行优化。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Java实现常见排序算法的优化 - Python技术站

(0)
上一篇 2023年6月27日
下一篇 2023年6月27日

相关文章

  • 消息提示插件toastr.js与messenger组件

    消息提示插件toastr.js与messenger组件 在网站开发中,消息提示是一个不可或缺的功能,可以使得用户快速了解网站的反馈信息和操作结果。而通过使用第三方的消息提示插件,可以实现更加美观、实用和易于管理的消息提示体验,其中toastr.js和messenger组件就是比较受欢迎的选择。 toastr.js toastr.js是一款轻量级、简单易用的J…

    其他 2023年3月29日
    00
  • sourceTree初识

    下面是关于SourceTree初识的完整攻略,包括介绍、步骤和两个示例说明。 介绍 SourceTree是一款免费的Git和Mercurial版本控制工具,可以帮助开发者更方便地管理和协作代码。本文将介绍如何使用SourceTree进行版本控制和协作开发。 步骤 使用SourceTree进行版本控制和协作开发的步骤通常包括以下几个步骤: 下载和安装Sourc…

    other 2023年5月6日
    00
  • C语言实现带头双向环形链表

    C语言实现带头双向环形链表的完整攻略 什么是双向环形链表 双向链表是在单向链表的基础上增加了一个指向前驱节点的指针,使得链表可以双向遍历。双向环形链表是在双向链表的基础上将尾指针指向头节点,形成一个环形结构。带头结点的链表是在链表头增加一个头结点,并将头结点的指针指向第一个节点,使得链表的插入和删除操作更加简单。 如何实现带头双向环形链表 实现带头双向环形链…

    other 2023年6月27日
    00
  • Win10最新预览版14393自制ISO镜像下载 32位/64位

    Win10最新预览版14393自制ISO镜像下载攻略 本攻略将详细介绍如何下载Win10最新预览版14393的自制ISO镜像,包括32位和64位版本。以下是具体步骤: 步骤一:准备工作 在开始之前,请确保您已经完成以下准备工作: 确认您的计算机符合Win10最新预览版14393的系统要求。 确保您有稳定的网络连接。 准备一个可用的USB闪存驱动器或空白的DV…

    other 2023年7月28日
    00
  • 沉淀再出发:关于IntelliJ IDEA使用的一些总结

    沉淀再出发:关于 IntelliJ IDEA 使用的一些总结 IntelliJ IDEA 是一款既强大又流行的集成开发环境(Integrated Development Environment,IDE),它被广泛应用于 Java、Kotlin 等编程语言的开发中。在长期的使用过程中,我对 IntelliJ IDEA 进行了一些总结,分享一些使用上的技巧和注意…

    其他 2023年3月28日
    00
  • Java与C++分别用递归实现汉诺塔详解

    Java与C++分别用递归实现汉诺塔详解 1. 理论背景 汉诺塔是一个经典的递归问题,它可以用于验证一个编程语言是否具备递归能力。 汉诺塔由三根针和若干个圆盘组成,每个圆盘有一个固有的大小,这些圆盘可以滑动到任意一根针上,但是每次只能移动一个圆盘并且大的圆盘不能放在小的圆盘上面。使用递归的方式可以让我们轻松找出三个针上的圆盘移动方法。 2. 递归实现 Jav…

    other 2023年6月27日
    00
  • WPS表格怎么添加漂亮的边框和底纹?

    当我们使用WPS表格进行表格制作时,边框和底纹是必不可少的。 这里我为大家详细讲解一下如何在WPS表格中添加漂亮的边框和底纹。 添加边框 第一步:选中单元格或单元格区域 首先,我们需要选中需要添加边框的单元格或单元格区域。在进行边框添加前,确保你已经选中了需要添加边框的单元格或单元格区域。 第二步:打开边框选项 在选定单元格或单元格区域后,点击“开始”选项卡…

    other 2023年6月27日
    00
  • js去掉字符串前后空格或去掉所有空格的用法

    JS去掉字符串前后空格或去掉所有空格的用法 在Web开发中,我们常常需要进行字符串操作,其中包括去掉字符串的空格,这样可以方便地对数据进行处理。本文将介绍如何使用JavaScript去掉字符串前后空格或去掉所有空格。 去掉字符串前后空格 使用Trim方法 在Javascript中,可以使用trim()方法去掉字符串前后空格。这个方法返回一个新的字符串,这个字…

    其他 2023年3月29日
    00
合作推广
合作推广
分享本页
返回顶部