排序(1)--冒泡,简单选择,快速,简单插入

排序是底层常用的算法。整理下知识,以便以后复习。

1:冒泡排序算是最简单的排序方法了,简单易懂。从第一个数开始,将每一个数与它之后的数进行比较,然后将较大的数放在后面,依次循环比较,一轮比较结束后,最大的数就会被排放到最后,就像冒泡一样,最大(最小)的数从底层挤到的最后面(最前)。后面就简单了,排除已经排序好的数后(范围-1),进行下一次循环即可。比较次数固定,交换次数不固定。

2:简单选择排序,这个排序也是相当容易理解的一种。对序列进行一次迭代,首先一个指针指针向第一个元素,然后开始比较指针所指元素与序列内所有元素,如果指针所指元素较大,则将指针指向较小的元素,一轮循环后,指针指向的元素就是此次循环的最小数,将最小数与第一个位置的数进行交换,至此,第一个数就是最小的数了。然后从第二个数开始,重复之前的动作。

         两个算法在我看来思路相同,都是一轮循环比较,找出最大或最小的值,然后排除这个值以后,进行下一次循环。只是冒泡使用交换来确定最大最小元素。而选择排序则使用额外指针(下标,临时时变量都行)来指向最大最小的元素。

两者最大区别可能就是一个稳定,一个不稳定。稳定则需要多次交换。两种复杂度都为O(n~2)。但不稳定算法性能要优于稳定算法(交换次数少)。

选择排序是不稳定的,因为每次交换都有可能打破原来相等对象的顺序。比如:  6,8,6,7,3.。  第一次循环后,3和6会进行交换,第一个6就会被排序到第二个6的后面,这就打破了顺序。

冒泡排序是稳定的,由于是前一个数与后一个数进行比较。循环到一定阶段,相等的数就会被排到一起,而相等的数之间是不进行交换的,还是按照原来的次序。

3.快速排序:这是一种相当常用的算法,他使用的是一种递归的思想,将复杂问题简单化。最简单的排序就是1个数,这个就不需要排序(结束条件)。2个数进行排序,以第一个数为基准,比他大的放后面。

         这样,将一个序列的数按一个基准(一般第一或最后一个数)分为两部分,前面的都比他小,后面的都比他大,然后对这两个部分再次以相同方式进行划分(以各自序列的第一个最后一个数为基准划分)。依次递归,最后分到只有一个数,则不需要划分了,同时也排序完成了。

使用递归后,思路就简单了,思路就是,划分成两部分A,B-------A,B分别递归划分;

所以唯一要解决的问题就是如何划分了。使用的方法是使用两个指针分别指向头部和尾部。从一头开始查找,定位到第一个不符合要求的数。这时开始从另外一头开始查找,也定位到第一个不符合要求的数。此时,两个指针所指向的数都是不符合自己序列的数(大于,小于基准数),于是将两个数进行交换,这样,两个数就都符合自己序列要求了。重复以上步骤,就这样,两个指针相向进行移动,疏通各自序列,保证序列符合要求。

          结束循环的条件就是两个指针指向同一个数。

          比较这个数和基准数,如果是属于基准所在分序列要求的(比如,选取第一个数位基准,则基准所在分序列要求是<=基准。反之则是>=基准),则交换此数与基准数。如果是不符合的,则将基准数交换成这个数附近符合基准序列的数(如果基准是第一,则选择这个数之前的数,如果基准是最后,则选择这个数之后的数)。总而言之,就是将基准数移动到序列中心。

至此,序列之前的数都小于基准,序列之后的数都大于基准数。

快速排序由于是两个指针向着中心运动,第一次排序(未递归之前)就可能会导致相等元素位置反向,所以这是一个不稳定的算法。如9,6,6,1,7,4,3,2,5假设以5为基准,第一次2与9交换,第二次第一个6与3交换,第三次第二个6与4进行交换,此时两个相等的6顺序颠倒了。

快速排序平均时间复杂度为O(nlogn),优于简单选择排序。


4.简单插入排序:这也是一种比较容易理解和实现的算法。它的思想是,将一个元素插入到有序的元素序列中,形成的还是有序的序列。实现方式就是使用一个数字n代表有序数列的值,初始为 1,也就是初始时只有一个数是有序的,然后将第n+1(未排序数列的最开始的数)插入到前面的有序数列中,将n自增一。然后重复开始插入第n+1个数。

这个算法每部迭代流程是  :找到插入位置---将数插入。

一般查找插入位置,数组使用二分查找法相当快,链表使用普通查找。而插入的话,如果底层是数组,则需要用一个临时值保存需要插入的数,然后再插入位置之后的向后移动一个位置直到需要插入的原始位置,最后替换插入位置的元素。比如   3,7,11,5,9。假设正在插入5,则7,11都要向后挪动一个位置 变成 3,7,7,11,9。最后用5替换第三个位置的7。

如果底层是链表的话,则可以取出这个节点,插入到相应位置。

底层为数组时插入花销大(需要后移元素),但是查找快(二分)。而链表则是插入相当快,但是查找比较慢(可以通过使用二叉树链表来代替线性链表,降低查找时间)。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值