Java 数据结构与算法系列精讲之排序算法

yizhihongxing

Java 数据结构与算法系列精讲之排序算法攻略

1. 序言

排序算法是计算机程序设计中常见的一类算法,主要用于将一组数据按照一定的顺序重新排列。在实际工作和面试中,排序算法是计算机程序员必须掌握的基本算法之一。本文将重点讲解 Java 数据结构与算法系列中的排序算法,其中包括冒泡排序、选择排序、插入排序、希尔排序、归并排序、快速排序和堆排序。

2. 冒泡排序

冒泡排序是一种较为简单的排序方式,其基本思想是从头到尾比较相邻两元素的大小,并交换位置。在一次完整的冒泡过程中,将会把数字序列中最大的数“冒泡”到最后面。最好情况下时间复杂度为 O(n),最坏情况和平均情况时间复杂度均为 O(n²)。

示例:

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

3. 选择排序

选择排序和冒泡排序一样,都是简单的排序算法。它的基本思想是从未排序的序列中选择一个最小的元素存放到已排序序列的末尾,然后再从未排序序列中选择最小元素。最好情况、最坏情况和平均情况下时间复杂度均为 O(n²)。

示例:

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

4. 插入排序

插入排序方面,插入排序的基本思想是将一个记录插入到有序的序列中,从而得到一个新的序列。在插入排序过程中,记录从前往后依次插入,未排序的序列每次从前面取出一个元素,并插入到有序序列的相应位置中。最好情况时间复杂度为 O(n),最坏情况和平均情况时间复杂度均为 O(n²)。

示例:

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

5. 希尔排序

希尔排序是插入排序的一种优化版本。它通过缩小增量(增量序列的选择也有影响)来改变待排序序列中各元素的相对位置,从而达到排序的目的。希尔排序是非稳定排序,它的时间复杂度依据所选取的增量序列不同而不同,通常情况下它的时间复杂度都是 O(n log n) 级别的。

示例:

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;
            for (j = i; j >= gap && temp < arr[j - gap]; j -= gap) {
                arr[j] = arr[j - gap];
            }
            arr[j] = temp;
        }
    }
}

6. 归并排序

归并排序采用先拆分再合并的递归方法,将序列分成若干个长度为1的子序列,然后再将它们两两合并,直接合并完成为止。归并排序是稳定排序,在排序过程中需要开辟一个与原数组大小相等的数组来辅助排序。时间复杂度是 O(n log n)。

示例:

public static void mergeSort(int[] arr, int l, int r) {
    if (l < r) {
        int m = (l + r) / 2;
        mergeSort(arr, l, m);
        mergeSort(arr, m + 1, r);
        merge(arr, l, m, r);
    }
}

public static void merge(int[] arr, int l, int m, int r) {
    int[] temp = new int[arr.length];
    int i = l, j = m + 1, k = l;
    while (i <= m && j <= r) {
        if (arr[i] < arr[j]) {
            temp[k++] = arr[i++];
        } else {
            temp[k++] = arr[j++];
        }
    }
    while (i <= m) {
        temp[k++] = arr[i++];
    }
    while (j <= r) {
        temp[k++] = arr[j++];
    }
    for (int x = l; x <= r; x++) {
        arr[x] = temp[x];
    }
}

7. 快速排序

快速排序是一种快速的排序方法,采用分而治之的思想,利用递归实现。它的基本思想就是选择一个基准元素,然后将序列分成两部分,分别对这两部分再进行快速排序,直到整个序列有序为止。快速排序是不稳定的排序方法,其时间复杂度平均情况下为 O(n log n)。

示例:

public static void quickSort(int[] arr, int low, int high) {
    if (low < high) {
        int pivot = partition(arr, low, high);
        quickSort(arr, low, pivot - 1);
        quickSort(arr, pivot + 1, high);
    }
}

public static int partition(int[] arr, int low, int high) {
    int pivot = arr[low];
    while (low < high) {
        while (low < high && arr[high] >= pivot) {
            high--;
        }
        arr[low] = arr[high];
        while (low < high && arr[low] <= pivot) {
            low++;
        }
        arr[high] = arr[low];
    }
    arr[low] = pivot;
    return low;
}

8. 堆排序

堆排序是一种树形选择排序方法,其基本思想是将待排序的序列构建成一个大根堆或小根堆,依次取出最大或最小元素放到根节点中,再对剩余的元素重新构造堆,直到整个序列有序为止。堆排序是一种不稳定的排序方法,其平均时间复杂度为 O(n log n),空间复杂度为 O(1)。

示例:

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 l = 2 * i + 1;
    int r = 2 * i + 2;
    if (l < n && arr[l] > arr[largest]) {
        largest = l;
    }
    if (r < n && arr[r] > arr[largest]) {
        largest = r;
    }
    if (largest != i) {
        int temp = arr[i];
        arr[i] = arr[largest];
        arr[largest] = temp;
        heapify(arr, n, largest);
    }
}

9. 总结

通过本文对 Java 数据结构与算法系列中的排序算法的讲解,我们可以了解到不同的排序算法的原理、时间复杂度和空间复杂度等方面的知识。其中包括了冒泡排序、选择排序、插入排序、希尔排序、归并排序、快速排序和堆排序等七种基本排序算法,希望这篇文章能为你理解和掌握排序算法提供帮助。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Java 数据结构与算法系列精讲之排序算法 - Python技术站

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

相关文章

  • GTA5网购车做任务老是丢解决方法介绍

    GTA5网购车做任务老是丢解决方法介绍 在玩GTA5时,可能会遇到这样一个问题:买了网购车却在做任务时经常会丢失,这是为什么呢?如何解决?下面我们就一起来看看。 为什么会丢失网购车 首先,我们需要了解一下网购车的特点。网购车是可以在网上商店购买的虚拟车辆。它们不同于你在游戏中得到的那些车辆,它们不能被你的人物保管起来,而是必须使用保险公司的服务来代替。 当你…

    other 2023年6月27日
    00
  • Bat脚本-Call,Start,直接调用,goto 四种方式调用批处理

    下面是关于“Bat脚本-Call,Start,直接调用,goto 四种方式调用批处理”的完整攻略。 Call调用方式 Call是一种在当前脚本中调用其他脚本的方法。可以使用Call调用其他批处理文件或外部程序。使用这条命令时,必须将批处理文件的名称放在Call之后,并在文件名前加上扩展名“ .bat”或“ .cmd”。 示例:调用另一个批处理文件,文件名为 …

    other 2023年6月26日
    00
  • 魔兽世界7.3.5兽王猎怎么堆属性 wow7.35兽王猎配装属性优先级攻略

    魔兽世界7.3.5兽王猎怎么堆属性攻略 引言 作为魔兽世界中的一个职业,兽王猎人在7.3.5版本中是一个非常强力的远程输出职业。在配装时,合理的堆积属性可以提高兽王猎的输出能力。本攻略将介绍在wow7.35版本中如何堆积合适的属性,并给出属性优先级的攻略。 属性堆积原则 在选择装备和宝石等提升属性的工具时,兽王猎人可以根据如下原则进行属性堆积: 爆发伤害:优…

    other 2023年6月28日
    00
  • 如何知道文件的格式 winXP系统隐藏或显示文件格式的方法

    如何知道文件的格式 在Windows XP系统中,你可以使用以下方法来查看文件的格式,无论文件是否隐藏。 方法一:使用文件扩展名 大多数文件在Windows系统中都有文件扩展名,它是文件名的一部分,用于指示文件的格式。通过查看文件的扩展名,你可以快速了解文件的格式。 打开文件所在的文件夹。 在Windows资源管理器中,找到你要查看格式的文件。 右键单击文件…

    other 2023年8月5日
    00
  • json数据格式及json校验格式化工具简单实现

    json数据格式及json校验格式化工具简单实现 JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,易于阅读和编写,并且易于机器解析和生成。在现代web应用程序开发中,JSON已经成为一种常用的数据格式。本文将介绍JSON数据格式,并提供一个简单的JSON校验、格式化工具的实现代码。 什么是JSON格式 JSON格式…

    其他 2023年3月28日
    00
  • 第0章概述及常见dos命令

    第0章概述及常见dos命令 概述 DOS是英文Disk Operating System(磁盘操作系统)的缩写,是一种与硬件直接交互的操作系统,是Windows操作系统的前身。 DOS是一个单用户、单任务的操作系统,它使用了命令行界面(Command Line Interface, CLI)而不是图形用户界面(Graphical User Interface…

    其他 2023年3月29日
    00
  • 从UI Automation看Windows平台自动化测试原理

    从UI Automation看Windows平台自动化测试原理 Windows系统是应用程序广泛运行的平台,而自动化测试是保证软件质量的重要手段之一。因此,掌握Windows平台自动化测试原理是非常必要的。 UI Automation是Windows平台上的自动化测试框架,它提供了一组API,用于识别和操作应用程序的UI元素。以下是UI Automation…

    其他 2023年3月28日
    00
  • 联通光猫HG8321R怎么破解? 华为hg8321开启路由功能的技巧

    联通光猫HG8321R的破解攻略 一、前置知识 在开始之前,需要了解以下一些基础知识: 什么是光猫光猫是指光纤调制解调器,是光纤宽带网络终端设备,主要功能是将光纤接入用户的家庭或办公室,转换为家庭或办公室内的网线信号,用于连接电脑、路由器等终端设备。 什么是路由器路由器是一种网络设备,能够将各种不同的网络连接在一起组成互联网。它可以将来自网络的数据进行分配和…

    other 2023年6月27日
    00
合作推广
合作推广
分享本页
返回顶部