IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> Java版排序算法——冒泡排序、选择排序、插入排序、希尔排序、归并排序、快速排序【含代码以及讲解】 -> 正文阅读

[数据结构与算法]Java版排序算法——冒泡排序、选择排序、插入排序、希尔排序、归并排序、快速排序【含代码以及讲解】

常见的排序算法复杂度:

冒泡排序:时间复杂度O(n^2)

排序方法:

  1. 比较相邻元素,如果第一个比第二个大,则交换他们
  2. 一轮下来,可以保证最后一个数是最大的
  3. 执行n-1轮,就可以完成排序

实现思路:

  • 用二重循环实现,外循环变量设为i,内循环变量设为j。假如有n个数需要进行排序,则外循环重复n-1次,内循环依次重复n-1,n-2,...,1次。每次进行比较的两个元素都是与内循环j有关的,它们可以分别用a[j]和a[j+1]标识,i的值依次为1,2,...,n-1,对于每一个i,j的值依次为0,1,2,...n-i 。
  1. 设数组长度为N:
  2. 比较相邻的前后二个数据,如果前面数据大于后面的数据,就将二个数据交换。
  3. 这样对数组的第0个数据到N-1个数据进行一次遍历后,最大的一个数据就“沉”到数组第N-1个位置。
  4. N=N-1,如果N不为0就重复前面二步,否则排序完成。

代码:

public class BubbleSort {
    public static void BubbleSort(int[] arr) {
        int temp;//定义一个临时变量
        for (int i = 0; i < arr.length - 1; i++) {//冒泡趟数
            for (int j = 0; j < arr.length - i - 1; j++) {
                // 后面比前面小,则进行交换,这样必然就是大的往后挪动
                if (arr[j + 1] < arr[j]) {
                    temp = arr[j];
                    arr[j] = arr[j + 1];
                    arr[j + 1] = temp;
                }
            }
        }
    }

    public static void main(String[] args) {
        int arr[] = new int[]{1, 6, 2, 2, 5};
        System.out.println("原数组:");
        for (int num : arr) {
            System.out.print(num + " ");
        }

        BubbleSort.BubbleSort(arr);
        System.out.println();
        System.out.println("排序后:");
        for (int num : arr) {
            System.out.print(num + " ");
        }
    }
}

选择排序:时间复杂度O(n^2)

排序思路:

  • 找到数组中的最小值,将它放在第一位;(直接将最小的元素与第一个元素进行交换)
  • 接着找到第二小的值,将它放在第二位;
  • 依次类推,执行n-1轮;

代码实现:

public class SelectionSort {
    public static void SelectionSort(int[] arr) {
        //选择排序的优化
        for (int i = 0; i < arr.length - 1; i++) {// 做第i趟排序
            int k = i;
            for (int j = k + 1; j < arr.length; j++) {// 选最小的记录
                if (arr[j] < arr[k]) {
                    k = j; //记下目前找到的最小值所在的位置
                }
            }
            //在内层循环结束,也就是找到本轮循环的最小的数以后,再进行交换
            if (i != k) {  //交换a[i]和a[k]
                int temp = arr[i];
                arr[i] = arr[k];
                arr[k] = temp;
            }
        }

    }

    public static void main(String[] args) {
        int[] arr = {1, 6, 2, 2, 5};
        System.out.println("原数组:");
        for (int num : arr) {
            System.out.print(num + " ");
        }

        SelectionSort(arr);

        System.out.println();
        System.out.println("排序后:");
        for (int num : arr) {
            System.out.print(num + " ");
        }
    }
}

插入排序:时间复杂度O(n^2)

排序方法:将元素插入到排序好的数组中

  • 从第二个数开始往前比;(所以需要设置临时变量)
  • 寻找合适的插入位置,直到当前这个元素比前面大且比后面小为止;
  • 以此类推直到最后一个数;

代码实现:

public class StraightInsertionSort {
    //直接插入排序
    static void insertSort(int[] a) {
        int Arrlength = a.length;
        // 从第二个数开始
        for (int i = 1; i < Arrlength; i++) {
            // 前面比后面大,需要进行排序
            if (a[i - 1] > a[i]) {
                // 记录这个比后面大元素的位置,需要寻找后面这个元素的插入位置,寻找的范围是前i-1的位置
                int j = i - 1;
                // 后面的这个元素
                int temp = a[i];
                // 给后面这个元素寻址位置
                while (temp < a[j]) {
                    // 元素往后窜的过程
                    a[j + 1] = a[j];
                    j--;
                    if (j < 0) {
                        break;
                    }
                }
                a[j + 1] = temp;
            }
        }
    }

    public static void main(String[] args) {
        int[] arr = {1, 6, 2, 2, 5};
        System.out.println("原数组:");
        for (int num : arr) {
            System.out.print(num + " ");
        }

        insertSort(arr);

        System.out.println();
        System.out.println("排序后:");
        for (int num : arr) {
            System.out.print(num + " ");
        }
    }
}

希尔排序:

排序方法:

希尔排序(Shell's Sort)是插入排序的一种又称“缩小增量排序”(Diminishing Increment Sort),是直接插入排序算法的一种更高效的改进版本。希尔排序是非稳定排序算法。

代码实现:似乎不常用?

归并排序:时间复杂度O(nlogn),分的时间复杂度O(logn),合并的过程的复杂度是O(n)

排序方法:

  • 分:把数组分成两半,递归子数组,进行分割操作,直到分成一个数;
  • 合:把两个字数组合并成一个有序数组,直到全部子数组合并完毕,合并前先准备一个空数组,存放合并之后的结果,然后不断取出两个子数组的第一个元素,比较他们的大小,小的先进入之前准备的空数组中,然后继续遍历其他元素,直到子数组中的元素都完成遍历;

这图可能来源就是图中水印位置,不太记得了,笔记里的老图

代码实现:

public class MergeSort {
    public static void main(String[] args) {
        int[] arr = {1, 6, 2, 2, 5};
        System.out.println("原数组:");
        for (int num : arr) {
            System.out.print(num + " ");
        }
        //tmp是用于存放新排序的数组的
        int[] tmp = new int[arr.length];
        mergeSort(arr, 0, arr.length - 1, tmp);

        System.out.println();
        System.out.println("排序后:");
        for (int num : arr) {
            System.out.print(num + " ");
        }
    }

    public static void merge(int[] arr, int low, int mid, int high, int[] tmp) {
        int i = 0;
        int j = low, k = mid + 1;  //左边序列和右边序列起始索引
        while (j <= mid && k <= high) {
            if (arr[j] < arr[k]) {
                tmp[i++] = arr[j++];
            } else {
                tmp[i++] = arr[k++];
            }
        }
        //若左边序列还有剩余,则将其全部拷贝进tmp[]中
        while (j <= mid) {
            tmp[i++] = arr[j++];
        }

        while (k <= high) {
            tmp[i++] = arr[k++];
        }

        for (int t = 0; t < i; t++) {
            arr[low + t] = tmp[t];
        }
    }

    public static void mergeSort(int[] arr, int low, int high, int[] tmp) {
        if (low < high) {
            int mid = (low + high) / 2;
            // 分
            mergeSort(arr, low, mid, tmp); //对左边序列进行归并排序
            mergeSort(arr, mid + 1, high, tmp);  //对右边序列进行归并排序
            // 合
            merge(arr, low, mid, high, tmp);    //合并两个有序序列
        }
    }
}

相关习题:

  • 148. 排序链表【中等+归并排序】
  • 23. 合并K个升序链表【困难+归并(分治)】
  • 373. 查找和最小的K对数字【中等+多路归并+自定义优先队列的排序规则】
  • 786. 第 K 个最小的素数分数【困难+多路分治递归!惊艳了】
  • 378. 有序矩阵中第 K 小的元素【中等+分治+优先队列】
  • 373. 查找和最小的K对数字【中等+多路归并+自定义优先队列的排序规则】

快速排序:时间复杂度O(nlogn),递归复杂度是O(logn),分区复杂度O(n)

排序方法:(啊哈算法中讲到)

  • 第一步:设置两个指针left和right分别指向数组的头部和尾部,并且以头部的元素(6)为基准数
  • 第二步:right指针先往左移动,找到小于基准数的元素就停下,然后移动left指针
  • 第三步:left指针往右移动,找到大于基准数的元素就停下,然后交换right和left指针所值元素的值
  • 重复第二、三步,直到两个指针left和right重合
  • 第四步:两个指针重合后将基准数(6)与两个指针指向的元素值(3)交换

  1. 到这时,第一轮排序结束,此时以基准数(6)为分界点,(6)左边的数都小于等于6,(6)右边的数都大于等于6,现在我们已经将原来的序列以(6)为分界点拆成了两个序列左边的序列是3 1 2 5 4,右边的序列是9 7 10 8,接下来分别处理这两个序列,原理相同。
  2. 最终序列为1 2 3 4 5 6 7 8 9 10,到此排序完全结束(快速排序的每一轮处理其实就是将这一轮的基准数归位,直到所有的数都归位为止)

排序要注意的:

必须是右先动,否则就不是从小到大排序了;

代码实现:

?

public class QuickSort {
    public static void main(String[] args) {
        int[] arr = {1, 6, 2, 2, 5};
        System.out.println("原数组:");
        for (int num : arr) {
            System.out.print(num + " ");
        }

        quickSort(arr, 0, arr.length - 1);

        System.out.println();
        System.out.println("排序后:");
        for (int num : arr) {
            System.out.print(num + " ");
        }
    }

    public static void quickSort(int[] arr, int leftPos, int rightPos) {
        if (rightPos < leftPos) {

        } else {
            //将数列最左边第一个数字作为基准数
            int initLeftPos = leftPos;
            int initRightPos = rightPos;
            int baseNum = arr[leftPos];

            while (rightPos > leftPos) {
                //第二步:右边指针找到小于基准数的就停下
                while (arr[rightPos] >= baseNum & rightPos > leftPos) {
                    rightPos--;
                }

                //第二步:左边指针找到大于基准数的就停下
                while (arr[leftPos] <= baseNum & rightPos > leftPos) {
                    leftPos++;
                }

                //交换两个指针最终标记的数字
                if (rightPos > leftPos)
                    swap(arr, leftPos, rightPos);
            }
            //当左右两边指针重合时,将基准数与指针指向数字交换
            swap(arr, leftPos, initLeftPos);
            //指针左半边递归,以进来的数组的左边为界,右边是左右指针相同时左边一个
            quickSort(arr, initLeftPos, leftPos - 1);
            //右边同理
            quickSort(arr, rightPos + 1, initRightPos);
        }
    }

    //swap方法:将数组中leftPos和rightPos上的两个数值进行交换
    public static void swap(int[] arr, int leftPos, int rightPos) {
        int temp = arr[leftPos];
        arr[leftPos] = arr[rightPos];
        arr[rightPos] = temp;
    }
}

参考文献:

部分参考全栈潇晨搞定大厂算法面试之leetcode精讲

部分参考百度百科

归并排序(Java代码实现)_Leo的博客-CSDN博客_归并排序java

《啊哈!算法》/ 啊哈磊著. 人民邮电出版社

JAVA快速排序代码实现 - AnthonyHoo - 博客园

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2022-03-13 22:03:13  更:2022-03-13 22:07:09 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 13:55:54-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码