排序算法的思想
冒泡排序
思想:从第一个待排序的数开始,和相邻的数两两比较,如果是由小到大的话就和遇到的小的交换,然后继续和后面的比较,直到所有的数据都有序,这样的话最大的数就会浮现到后面去。就像喝汽水时气泡上升的过程。
时间复杂度:O(n^2) 最好的时间复杂度O(n)
空间复杂度:O(1)
稳定性:稳定
查看代码请点下面链接https://blog.csdn.net/choudan8888/article/details/84573563
选择排序
思想:每次从待排序的数中选出一个最小的数(或者最大数)放在最前面,然后继续从剩下的数中继续找出最小的数,放在刚在那个最小数的后面,依次这样,直到所有的数有序。
时间复杂度:O(n^2) 最好最坏都是O(n^2)
空间复杂度:O(1)
稳定性:不稳定
查看代码点击下面链接https://blog.csdn.net/choudan8888/article/details/84573563
插入排序
思想:如果只有一个数,那它一定是有序的;所以我们从第二个数开始,那第二个数和前面的已经有序的数列比较,如果大于前面数列的最大值的话,就放在前面数列的最后面,如果小于最大值的话,那就需要在前面数列中找一个合适的位置来插入,并且这个插入的数列依旧是有序的,直到数列完全有序。
时间复杂度:O(n^2) 最好的时间复杂度:O(n)
空间复杂度:O(1)
稳定性:稳定
查看代码点击下面链接https://blog.csdn.net/choudan8888/article/details/86527582
希尔排序
希尔排序是插入排序的升级版,它和插入排序的思想一样,但是比插入排序快。
思想:希尔排序的思想是当隔着任意长的数据是有序的,那么这个数据整体就是有序的。给出一个定长,第一次用H和H-H的数来比,就相当于第一个数和H的数比较,后面用第二个数和H+1来比较,比较完缩小定常H,继续上面的步骤,直到定长缩小为1,数据也就有序了
时间复杂度:O(n^1.3) 最好的时间复杂度是O(n) 最坏的时间复杂度都是O(n^2)
空间复杂度:O(1)
稳定性:不稳定
查看代码点击下面链接https://blog.csdn.net/choudan8888/article/details/88379570
快速排序
思想:每一次招一个哨兵结点,用哨兵结点来和数据比较;比较的方式是这样的,用两个指针排序数组的头(不包含哨兵结点)和尾,从尾指针开始找,找到第一个比哨兵位小的放到哨兵这个位置,然后又从头指针开始找,找第一个比哨兵大的值,放到后面尾指针刚才空出来的位置,直到头指针和尾指针相遇,将哨兵结点放在这个相遇的位置,第一遍就完成了,在哨兵位以前全是比它小的,在哨兵位以后全是比它大的,如果头指针和哨兵现在这个位置中间的数多于1个,那就继续排序头指针到哨兵位置-1这个区间的,依然采用上面的方法;右边和左边一样
快速排序最关键的地方在与哨兵节点的选择,最坏的情况发生在分割时候值分割出去一个值和另外左右的数据,即取序列的首位作为哨兵结点,这完全没有达到想要的结果。所以快排最好是随机分布哨兵值,这样排序是最快的。
时间复杂度:O(nlogn) 最坏的情况 O(n^2) 最好的情况O(nlogn)
空间复杂度:O(logn)
稳定性:不稳定
查看代码点击下面链接https://blog.csdn.net/choudan8888/article/details/86525328
归并排序
思想:“归并”的含义是将两个或两个以上的有序表组合成一个新的有序表,归并排序和快排一样也采用的是分治的思想,它的基本原理是通过对若干个有序结点序列的合并为一个有序序列来实现排序的。有两个已经排好序的序列进行归并,需要先申请一片可以放的下这两个序列的空间,然后开始比对这两个序列的第一个元素,把比较小的元素放进申请好的空间中,然后用小的序列中的下一个元素和前面比较大的元素比较,谁小放谁,这样就把两个已经排好序的序列放在一个空间中,并且依然有序。
时间复杂度:O(nlogn) 最好最坏都是O(nlogn)
空间复杂度:O(n)
稳定性:稳定
查看代码点击下面链接https://blog.csdn.net/choudan8888/article/details/88420754
堆排序
堆排序(使用大堆,升序)从基本实现原理来说也是一种选择排序,它同样是确定了位置选择符合位置的元素,但是堆排序是更加优化的选择排序的版本,它利用了堆的特性。我们需要调整成为父结点的值大于子结点,且满足完全二叉树,大大提高了选择排序的效率。
时间复杂度:O(nlogn) 最好和最坏都是O(nlogn)
空间复杂度:O(1)
稳定性:不稳定
查看代码点击下面链接https://blog.csdn.net/choudan8888/article/details/100096954
基数排序
基数排序(升序)是一种非比较式的排序方式,和之前博文中提到的快排,冒泡排序,插入排序这些排序算法不一样,它没有使用任何交换的方式,它的基本思想是通过分配的方法把元素从小到大分配,以到达排序的作用。
时间复杂度:O(d(r+n)) 最好O(d(n + rd)) 最坏O(d(r + n))
空间复杂度:O(rd + n)
稳定性:稳定
排序算法的使用场景
- 若排序的规模比较小时,可以采用直接插入排序或者选择排序
- 当输入的数据基本上有序的时候,使用快速排序和插入排序
- 当排序的规模比较大的时候,可以使用堆排序,快速排序,和归并排序。堆排序的的空间复杂度小于快排,快速排序目前是认为最好的方法,当待排序的关键字是随机分布的时候,快速排序的平均时间会最短;但是两者不稳定,归并排序是一种稳定的排序,可以先将数据分成几部分,在利用插入排序对这些小部分排序,因为插入排序小规模插入还是很快的,然后在用归并排序处理,也不会造成数据的混乱(都是稳定的排序);
- 在进行大数据的处理的时候,堆排序也显现出了他自己的优势,在一千万个数中找前100小,一千万是不能在内存中放下的,我们可以建立100个结点的大根堆,先放入100个数据,之后每次放入一个元素就和上面的比较,如果小的话就删除堆里的一个元素,直到所有的数据放完,留下的就是最小的100个数
C++中的sort函数用到了哪些排序算法
在C++STL库中的sort函数,数据量很大的时候采用快速排序,分段递归排序,当分段后的数据小于某个值的时候,为了减小快速排序的递归调用带来的开销,就会改用插入排序,如果递归的层次过于深的话,还会使用堆排序。