冒泡排序和插入排序(简单排序方法完结)

Posted 算法零基础学习

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了冒泡排序和插入排序(简单排序方法完结)相关的知识,希望对你有一定的参考价值。

       冒泡排序

      如果你学过C语言(尤其是谭老先生的那本书),相信第一个排序方法就是冒泡排序,记得当时我学C语言的时候,完全是自学,那真是酸爽啊。算法什么的都不了解,甚至对指针,结构体都不会,直到大二下学期开始学习数据结构,当时不懂也得懂,经常自己跑到路灯底下写算法。在那段时间里,数据结构学的飞快,什么线性表,栈,队列,二叉树,图基本上都搞了一遍,印象最深的是哈夫曼树,先是看懂,在用C语言写出来,在讲给老师听。如此循环往复,还拿动态规划研究最短路径,我跑到gitee上找了一波还找到一些:

https://gitee.com/yxs12015242579/algorithmic_code/attach_files

还拿C写了个小系统冒泡排序和插入排序(简单排序方法完结)冒泡排序和插入排序(简单排序方法完结)冒泡排序和插入排序(简单排序方法完结),估计那个时候是C语言的运用的巅峰时期了,拿指针一顿瞎怼,指挥内存空间,要不说我这个人比较笨,到大二我才会用这些东西。只能说我在慢慢的进步,还是比不了那些大神。先天不足,后天来补吧,坚持正确的方向,不停的努力就好了。在写数据结构的时候也让我思考了很多底层的东西,比如说有借有还,再借不难,你借了电脑的内存空间是不是应该还给人家啊?在java中很简单,由垃圾回收机制替你完成。在C语言中你得自己写调用free函数,现在计算机内存大,少的4G大的8G,16G。所以写代码的时候很少会考虑内存的问题,只关心程序能不能运行,不考虑占用的内存,这其实不好。还是建议大家多考虑一下底层的东西,哪怕多想一下,优化一下算法,让它占用的内存更小,跑的更快。在想的时候,就能深化自己的内功,早日从码农变成一个程序员

    sorry,又跑远了,我们接着回来说冒泡排序。冒泡排序的思路:

(1)比较相邻的元素。如果第一个比第二个大,就交换他们两个。

(2)对每一对相邻元素做同样的工作,从开始第一对到结尾的最后一对。在这一点,最后的元素应该会是最大的数。

(3)针对所有的元素重复以上的步骤,除了最后一个。

(4)持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。

因此我们可以很轻松的将算法写出,代码如下:

static void sort(int []array){ for(int i=array.length-1;i>0;i--){ for(int j=0;j<i;j++){ if(array[j]>array[j+1]){          swap(array,j,j+1);//交换两个元素的值 printArray(array);//打印出来 } } } }

对于这个算法我是如何写出来的呢,过程是这样的。

先写下标为1和下标为0之间的关系,在写下标为2和下标为1之间的关系操作.....写完之后,将其变为循环。其实对于零基础和我这样的小白来讲,写算法,就是有简单到深入,这和开发程序一样,先实现静态的,在实现动态的。我们看一下整体的类:BubbleSort

public class BubbleSort { public static void main(String[] args) { int []array={9,6,1,3,5,7,2,4,8}; printArray(array); sort(array); printArray(array); } //冒泡排序算法 public static void sort(int []array){ for(int i=array.length-1;i>0;i--){ for(int j=0;j<i;j++){ if(array[j]>array[j+1]){ swap(array,j,j+1);      printArray(array); } } } } static void printArray(int []array){ System.out.print("数组元素:"); for(int i=0;i<array.length;i++){ System.out.print(array[i]+" "); } System.out.println(""); }static void swap(int []array,int min,int max){ int temp=array[min]; array[min]=array[max]; array[max]=temp; }}

验证一下算法:

冒泡排序和插入排序(简单排序方法完结)

从对角线上看就可以发现该算法的奥秘。我们拿验证器检验一下,看看跑1亿条数据会怎么样?

冒泡排序和插入排序(简单排序方法完结)

我们一起来分析一下冒泡排序的时间复杂度(以后如果说时间复杂度就是指的平均时间复杂度):

public static void sort(int []array){ for(int i=array.length-1;i>0;i--){ for(int j=0;j<i;j++){ if(array[j]>array[j+1]){ swap(array,j,j+1); printArray(array); } } } }

在上述代码中我们可以看到,外层循环 for(int i=array.length-1;i>0;i--)进行了n次,内存循环进行了Sum(n-1,n-2,n-3,n-4,....,1)次,这和次数的求解岂不是so easy,运用数学的等差数列求和公式:

冒泡排序和插入排序(简单排序方法完结)

求得时间复杂度为:O(n^2/2)也是就是O(n^2),空间复杂度:因为算法没用到额外的空间,所以空间复杂度为O(1),因为冒泡排序是相邻两个元素交换位置,所以很稳定。

插入排序

       说完了冒泡排序,我们先来来看看插入排序(这个排序方法是很重要的!面试的时候,面试官可能不会问你选择排序,冒泡排序,但是很有可能问你插入排序,快速排序,尤其是大厂,60%的题目都是算法,这是内功,别人比不了你的东西!)。


插入排序的原理:

      插入排序(Insertion sort)是一种简单直观且稳定的排序算法。如果有一个已经有序的数据序列,要求在这个已经排好的数据序列中插入一个数,但要求插入后此数据序列仍然有序,这个时候就要用到一种新的排序方法——插入排序法,插入排序的基本操作就是将一个数据插入到已经排好序的有序数据中,从而得到一个新的、个数加一的有序数据,算法适用于少量数据的排序,时间复杂度为O(n^2)。是稳定的排序方法。插入算法把要排序的数组分成两部分:第一部分包含了这个数组的所有元素,但将最后一个元素除外(让数组多一个空间才有插入的位置),而第二部分就只包含这一个元素(即待插入元素)。在第一部分排序完成后,再将这个最后元素插入到已排好序的第一部分中。

插入排序的思路:每步将一个待排序的记录,按其关键码值的大小插入前面已经排序的文件中适当位置上,直到全部插入完为止。

代码如下:

static void sort(int []array){ for(int j=1;j<array.length;j++){ for(int i=j;i>0;i--){ if(array[i]<array[i-1]) swap(array,i,i-1); }      } }

完整的程序如下:

public class InsertionSort { public static void main(String[] args) { int []array={9,6,1,3,5,7,2,4,8}; printArray(array); sort(array); } //插入排序算法 static void sort(int []array){ for(int j=1;j<array.length;j++){ for(int i=j;i>0;i--){ if(array[i]<array[i-1]) swap(array,i,i-1); } printArray(array); } /*  if(array[2]<array[1]) swap(array,2,1); if(array[1]<array[0]) swap(array,1,0); */ } static void printArray(int []array){ System.out.print("数组元素:"); for(int i=0;i<array.length;i++){ System.out.print(array[i]+" "); } System.out.println(""); } static void swap(int []array,int min,int max){ int temp=array[min]; array[min]=array[max]; array[max]=temp; }}

验证一下:

冒泡排序和插入排序(简单排序方法完结)

        过程很简单,第一次将下标为1的元素和下标为0的数组元素进行比较处理,排好序之后,数组的前两个元素已经有序。将下标为2的数组元素插入到前面已经有序的数组中。以此类推。

看形象化的了解一下过程:

冒泡排序和插入排序(简单排序方法完结)

我们使用验证器取1亿条数据对插入排序进行验证!

冒泡排序和插入排序(简单排序方法完结)


       对于这个算法时间复杂度为O(n^2),空间复杂度为O(1);

       改进!这个算法可以在优化吗?答案是肯定的,而且优化方法不止一种,比如加入二分法思想,个人认为二分法是一个特别有用的思想,比如说你在图书馆要找java编程思想这本书,我们在一堆书中开始找了,一种方法从第一本书开始找,那估计运气好的话很快就可以找到。但是这忒慢了。假如有几百万本书,找起来猴年马月能找完?另一种思路我知道书是有序排放的那么我可以从中间的位置开始找,拿书名用英文字母来举例子:A~Z。

①我现在从最中间的那个M开始找,发现是,J在M的前面啊.

②接下来我从A~M的最中间的位置找,最中间的位置是F,发现J在F后边,③接下来从F~M中找此时最中间的位置是i,J在i的后面。

④我在从i~M中找,此时此时最中间的位置是K,J在K的前面。

⑤那我就从I~K之间找,中间的就是J。找到了!

是不是贼快?
有兴趣可以在我写的排序算法上改进,使用二分插入法排序。写完可以发我的邮箱 3301068083@foxmail.com ,在之后的文章中,将你的算法展示给大家看!

现在我给大家提供另一种思路(灵感来自顺序表的插入操作,很快数据结构-线性表就上线了!冒泡排序和插入排序(简单排序方法完结)):

      使用临时变量保存要插入的值,然后将比临时变量大的值挨个往后挪,之后将临时变量放进去,这可以减少交换了。算法如下:

static void sort(int []array){ for(int j=1;j<array.length;j++){ int temp=array[j],i=j;        //依次将数组元素往后移动。        for(;i>0 && temp<array[i-1]; i--){ array[i]=array[i-1]; } //从前面排好的有序的数组中找到临时变量的位置。 array[i]=temp; } }

看看改进后的插入排序算法的速度:

希望大家在看完之后,帮忙转发一下,在此深表谢意,您的每一次转发都是我前进的动力。


以上是关于冒泡排序和插入排序(简单排序方法完结)的主要内容,如果未能解决你的问题,请参考以下文章

插入排序(直接插入排序希尔排序);交换排序(冒泡排序快速排序);选择排序(简单选择排序堆排序);归并排序和基数排序;基于关键词比较的排序算法下界分析

算法初等排序前篇[插入和冒泡排序]

排序算法总结

排序算法

冒泡排序?了解一下!

排序算法系列1--简单排序(选择,冒泡,直接插入)