Java语法 | 排序算法入门

Posted 查老师的讲义

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java语法 | 排序算法入门相关的知识,希望对你有一定的参考价值。

还没关注查老师?赶紧按蓝字

Java语法 | 排序算法入门
Java语法 | 排序算法入门

前言

C: 在这个时代,算法,虽说不是家喻户晓吧,但也算是大多数人常挂在嘴上的新名词。

诸如:美颜算法、人脸识别算法、推荐算法、压缩算法 .... ,我们也会经常听到有人在感叹算法的强大。

"x音,是新时代的精神鸦片。"(推荐算法)

"好厉害啊!我就在x宝看了看书包,然后一大堆书包推荐就来了。"(推荐算法)

"拍照记得给我开美颜啊!!"(美颜算法)

Java语法 | 排序算法入门

我们在前两篇入门了数据结构,数据结构和算法不分家,本篇,查老师带你入门一下算法。

算法简介

算法概述

那何谓算法呢?

算法(Algorithm)是指解题方案的准确而完整的描述,是一系列解决问题的清晰指令,算法代表着用系统的方法描述解决问题的策略机制。也就是说,能够对一定规范的输入,在有限时间内获得所要求的输出。不同的算法可能用不同的时间、空间或效率来完成同样的任务。一个算法的优劣可以用空间复杂度与时间复杂度来衡量 。[1]

想理解什么是算法,我们要先设想一个场景。几千年前,一位祖先凭着他对已故祖母如何做面包的记忆,尝试自己做面包。但是,他真的不知道该怎么做。他犹豫着,一开始先将麦仁放入沸水中,然后对自己说,这也许是个糟糕的想法。这位祖先的困境,正是我们都会面临的情况——遇到某一个问题,却又不知道该如何解决。我们想着解决方法,去尝试,反复探索实验,顺便有了一点点意外发现,直至成功……或者失败。

然而,真正的面包师并不是这样做的。他们不会给每炉面包都重制一个烘焙食谱,因为他们已经掌握并牢记了面包的烘焙方法。多亏了面包食谱,面包师可以每天给我们提供面包。事实上,人类文明的发展不仅源于有些人的发明创造,也因为另有人“复制”了这些发明,才使其得以改进。

但是,我们忘却了面包食谱的宝贵之处。首先,食谱降低了不确定性:多亏了它,面包师知道,除非突遭一场灾难,否则面包将会在晚餐时准备好。有了这个食谱,不需要什么想象力或是天赋,任何人都可以做面包。就拿两位作者来说,我们对面包烘焙没有任何天赋,但仍可以从网页上找到恰巴提的食谱,运用适当的和面力度,借助更富有想象力和才华的面包师们写下的方法,做出面包。最终,这个食谱成为了人类遗产中的一部分,在几千年的历史长河中,代代相传。

食谱就是一个算法,我们就此有了“算法”概念的初步定义:一个算法是解决一个问题的进程。我们并不需要每次都发明一个解决方案。

从这个定义不难看出,自人类历史初期,我们就一直在发明、使用和传播着各种各样的“算法”,用来烹饪、雕琢石器、钓鱼、种植扁豆及小麦,等等。[2]

查老师有话说: 按照查老师来理解,算法就是为了解决某个具体需求而提供的解题方法。在之后学习工作中,用别人写的算法,写自己的业务算法都是家常便饭,不用把它理解的过于抽象和高大上。

排序算法

排序算法无论是生活中,还是在算法启蒙中都扮有非常重要的角色,而且在面试的时候,大厂最爱的就是各种排序算法的思想或代码手写。

所谓排序算法,即通过特定的算法因式将一组或多组数据按照既定模式进行重新排序。这种新序列遵循着一定的规则,体现出一定的规律,因此,经处理后的数据便于筛选和计算,大大提高了计算效率。对于排序,我们首先要求其具有一定的稳定性,即当两个相同的元素同时出现于某个序列之中,则经过一定的排序算法之后,两者在排序前后的相对位置不发生变化。换言之,即便是两个完全相同的元素,它们在排序过程中也是各有区别的,不允许混淆不清。[3]

排序算法也有很多种解决思路,常见的有:冒泡排序、选择排序、插入排序、快速排序、堆排序、归并排序、希尔排序、基数排序等。

接下来,查老师将带你入门三种排序算法,也算是对我们小白入门数据结构的一个补充部分,不过在本篇查老师不会带你去介绍算法的时间复杂度及空间复杂度等内容,仅仅是对排序思想和基本实现做一个介绍。

冒泡排序

概述

冒泡排序可以说是排序算法中最为简单的一种。

它重复地走访过要排序的元素列,依次比较两个相邻的元素,如果顺序(如从大到小、首字母从Z到A)错误就把他们交换过来。走访元素的工作是重复地进行直到没有相邻元素需要交换,也就是说该元素列已经排序完成。

这个算法的名字由来是因为越小的元素会经由交换慢慢“浮”到数列的顶端(升序或降序排列),就如同碳酸饮料中二氧化碳的气泡最终会上浮到顶端一样(这是因为组成小气泡的二氧化碳比水要轻,所以小气泡可以一点一点向上浮动。),故名“冒泡排序”。[4]

Java语法 | 排序算法入门

排序思想

核心思想: 相邻元素做比较,两两比较小靠前。

1.将相邻的两个元素进行比较,比较完后,按照元素大小进行移位,小的移动到前面,大的移动到后面。2.每一轮比较完后,"最大的元素" 将被移位到最后。在下一轮比较的时候,这个 "最大的元素" 就不需要再参与比较了。3.重复进行上述步骤,经过 N - 1 轮比较之后,排序完成。(N:代表的是要比较的元素个数)

Java语法 | 排序算法入门

代码实现

int[] arr = {97862};
        
// 外层循环:N - 1
for (int i = 0; i < arr.length - 1; i++) {
    // 内层循环:N - 1 - i
    // - 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;
        }
    }
}

选择排序

概述

它是一种简单直观的排序算法。

它的工作原理是:第一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,然后再从剩余的未排序元素中寻找到最小(大)元素,然后放到已排序的序列的末尾。

以此类推,直到全部待排序的数据元素的个数为零。选择排序是不稳定的排序方法。[5]

排序思想

核心思想: 打擂台求最小值思路。

1.第一次比较的时候,先将 "第一个元素" 假定为最小元素值。2.然后将第一个元素依次和后面的所有元素进行比较大小,如果后面的元素比第一个元素小,则进行交换。3.每一轮比较完后,"最小的元素" 将被移位到 "第一个元素位置"。在下一轮比较的时候,这个 "最小的元素" 就不需要再参与比较了。4.重复的进行上面步骤,经过 N - 1 轮比较之后,排序完成。(N:代表的是要比较的元素个数)

代码实现

int[] arr = {97862};
        
// 外层循环:N - 1
for (int i = 0; i < arr.length - 1; i++) {
    // 内层循环:打擂台求最小值思路
    // 初始值 i + 1 是为了排除自己和自己比较的问题(第一个元素要和第二个元素开始比较)
    for (int j = i + 1; j < arr.length; j++) {
        if (arr[j] < arr[i]) {
            int temp = arr[j];
            arr[j] = arr[i];
            arr[i] = temp;
        }
    }
}

查老师有话说: 在选择排序中,包含了我们前面所学到的打擂台求最大值、最小值思路,可以回顾一下。

插入排序

概述

一般也称为直接插入排序。对于少量元素的排序,它是一个有效的算法。

插入排序是一种最简单的排序方法,它的基本思想是将一个记录插入到已经排好序的有序表中,从而一个新的、记录数增1的有序表。在其实现过程使用双层循环,外层循环对除了第一个元素之外的所有元素,内层循环对当前元素前面有序表进行待插入位置查找,并进行移动。[6]

排序思想

核心思想: 在有序数列中做插入,并保持住有序。

1.首先将第一个元素就看作是一个已经排序好的数列,后面的其他元素则看作未排序数列。

{{a1}, {a2, a3, a4, ..., an}}

2.然后将第二个元素在已经排序好的数列中,做插入动作。即在已经排序好的数列中,从后向前依次查找符合升序规律的位置,并插入到该位置。

这样新的已经排序好的数列就变为了:{{a1, a2}, {a3, a4, ..., an}}

3.重复这个步骤,直到排序结束。

代码实现

int[] arr = {97862};
        
for (int i = 1; i < arr.length; i++) {
    for (int j = i; j > 0; j--) {
        // 在有序数列中查找位置做插入,并保持有序。
        if (arr[j] < arr[j - 1]) {
            int temp = arr[j];
            arr[j] = arr[j - 1];
            arr[j - 1] = temp;
        }
    }
}

参考文献

[1]百度百科. 算法[EB/OL]. https://baike.baidu.com/item/算法. 2021.1.20

[2]瑟格·阿比特博, 吉尔·多维克. 算法小时代:从数学到生活的历变[M]. 人民邮电出版社,2018:1-10.

[3]李明达,何丽丽. 论排序算法的效率[J]. 中国管理信息化,2018,21(5):162-164.

[4]百度百科. 冒泡排序[EB/OL]. https://baike.baidu.com/item/冒泡排序. 2021.1.20

[5]Ajay Kumar.Data Structure for C Programming:Firewall Media,2004:268-270

[6]百度百科. 插入排序[EB/OL]. https://baike.baidu.com/item/插入排序. 2021.1.20

后记

本篇的作业请微信搜索关注: 查老师的讲义 ,然后回复 排序算法入门作业 即可。

我们在本篇初步讲解了目前这个阶段你能学得会,且在算法基础中最为熟知的三种排序算法,但仅仅上述这些排序算法,就已经让我们感受到了计算机科学家们的心血结晶。

它们各有各的特点,各有各的精妙之处,想要玩转它们,还需要我们多多花费一些时间。

查老师有话说: 对于技术的学习,查老师一贯遵循的步骤是:先用最最简单的 demo 让它跑起来,然后学学它的最最常用 API 和 配置让自己能用起来,最后熟练使用的基础上,在空闲时尝试阅读它的源码让自己能够洞彻它的运行机制,部分问题出现的原因,同时借鉴这些技术实现来提升自己的代码高度。

所以在查老师的文章中,前期基本都是小白文,仅仅穿插很少量的源码研究。当然等小白文更新多了,你们还依然喜欢,后期会不定时专门对部分技术的源码进行解析。

以上是关于Java语法 | 排序算法入门的主要内容,如果未能解决你的问题,请参考以下文章

排序算法入门之希尔排序(java实现)

7种基本排序算法的Java实现

Java排序算法-Java入门|Java基础课程

排序算法入门之快速排序(java实现)

Java基础入门五)之方法以及递归算法

排序算法入门之归并排序(java实现)