20170328_请说出各个排序算法的时间复杂度和稳定性

20170328_请说出各个排序算法的时间复杂度和稳定性,以及快排的原理

1、排序算法的分类:

(1)常见的排序算法分为四大类,分别是插入排序交换排序选择排序归并排序

(2)而其中,插入排序又可以分为直接插入排序法和希尔排序法;

交换排序可以分为冒泡排序法和快速排序法;

选择排序可以分为简单选择排序法和堆排序法;

对于归并排序,常用的是两路归并排序法。

2、各个排序算法的时间复杂度和稳定性概况:

     20170328_请说出各个排序算法的时间复杂度和稳定性_第1张图片

3、排序的深入探讨:

(1)直接插入排序法:InsertSort()

a、依次将无序区序列中的每一个元素,按照关键码的大小插入到一个已经排好序的有序区序列中,直到全部元素都排好序为止。

(2)希尔排序法:ShellSort()

a、先将整个无序区元素分割成若干个子序列(分割原则是:相隔某个“增量”的元素)。

b、在每一个子序列内部分别进行直接插入排序。

c、待整个序列基本有序(基本有序的意思是指“增量”足够小)时,再对全体元素进行一次直接插入排序,即可完成希尔排序法。

PS:由于希尔排序法是对相隔若干距离的元素进行直接插入排序,因此可以形象的称希尔排序为“跳着插入法”。

(3)冒泡排序法:BubbleSort()

a、依次的两两比较相邻元素的关键码,如果是反序,则交换它俩的位置。

b、这样每次遍历后,“最大”的元素就“沉”到最后面了。

c、重复N 次遍历,即可使整个元素有序。

      PS1:改进1:在某次遍历中,如果发现没有元素交换,则说明整个元素序列已经有序。因此可以设置标志位 flag 来判断此次遍历是否有元素的交换从而判断外面的大循环是否要继续循环遍历。

      PS2:改进2:记录下来某次遍历时最后发生元素交换的位置 position ,在这个位置之后的元素显然都已经有序,下次遍历时无需再考虑它们。因此可以通过记录下来最后进行元素交换的位置即可判断出下次遍历的范围。

(4)快速排序法:Partition()+ QuickSort()

      简介:快速排序的着眼点是

      在冒泡排序中,元素的比较和交换是在相邻位置进行的,元素每次交换只能前移或后退一个位置,因而总的比较次数和移动次数很多。

      在快速排序中,元素的比较和交换是从整个待排序元素区的两端向中间进行的关键码大的元素一次就能从前面移动到后面去,关键码小的元素也可以一次性从后面移动到前面去,这样的话就大大减少了元素的比较次数和交换次数。

(5)简单选择排序法:SelectSort()

a、第 i 趟排序通过 n - i  次关键码的比较,在 n - i + 1 个元素里找到关键码最小的元素,然后把它和第 i 个元素交换作为有序区的第 i 个元素。

b、直到完成第 n -1 趟的排序即可。

(6)堆排序法:Sift()+ HeapSort()

a、首先,将待排序元素序列构造成一个大根堆

b、然后,选出整个待排序元素的最大元素,即堆顶元素,将它从堆顶位置移走(通常做法是将它与堆中的最后一个元素交换),并且将剩余的元素再次调整为大根堆。

c、依此类推,重复上面的操作,直到堆中只有一个元素为止。

(7)两路归并排序法:Merge()+ MergePass()+ MergeSort()

简介:归并排序主要分为两步:

a、分序列(divide):每次把序列一分为二,然后分到只有两个元素的子序列。

b、合数列(Merge):依此的两两合并两个已经内部有序的子序列,直至所有子序列均被合并过。

PS :用非递归和递归都可以实现。

PS:

a、将两个相邻的有序子序列进行归并成一个大的有序子序列,即,完成一次归并。

b、从头到尾的完成一趟归并操作。

c、开始时,有序序列的长度是1,结束时有序序列的长度是n。因此使用有序序列的长度来控制排序过程的结束。




你可能感兴趣的:(C++程序员面试宝典)