您的位置:首页 > 理论基础 > 数据结构算法

七种排序方法(稳定性、空间复杂度、时间复杂度)分析总结

2018-01-14 19:36 465 查看

冒泡排序:

冒泡排序只在相邻元素大小不符合要求时才调换他们的位置, 它并不改变相同元素之间的相对顺序, 因此它是稳定的排序算法.

由于冒泡排序中只有缓存的temp变量需要内存空间, 因此空间复杂度为常量O(1).

最坏的情况是每次都需要交换, 共需遍历并交换将近n²/2次, 时间复杂度为O(n²). 最佳的情况是内循环遍历一次后发现排序是对的, 因此退出循环, 时间复杂度为O(n)

对于冒泡排序为什么最佳情况可以得到O(n)复杂度的解释:

普通双层for循环确实是任意情况都是O(n²),但是可以对代码进行轻微的修改得到O(n),修改后的代码如下:

void bubbleSort(int arr[]) {
boolean didSwap;
for(int i = 0, len = arr.length; i < len - 1; i++) {
didSwap = false;
for(int j = 0; j < len - i - 1; j++) {
if(arr[j + 1] < arr[j]) {
swap(arr, j, j + 1);
didSwap = true;
}
}
if(didSwap == false)
return;
}
}


选择排序:

每次从未排序的数中选择最小的与未排序的第一个交换,破坏了相对顺序(比如未排序的第一个是3,第二个也是3,第三个是2也是未排序中最小的,此时交换第三个和第一个,会破坏第一个和第二个之间的相对顺序),所以不是稳定的排序

空间复杂度为常量O(1)(同冒泡排序只有交换的时候临时变量需要空间)

无论是哪种情况,哪怕原数组已排序完成,它也将花费将近n²/2次遍历来确认一遍,时间复杂度为O(n²)

插入排序:

每次交换不改变其他元素间的相对顺序,因此是稳定的排序算法

空间复杂度为常量O(1)

最坏的情况是每次都需要交换, 共需遍历并交换将近n²/2次, 时间复杂度为O(n²),最好的情况是已经排序好,只要遍历一次,不需要交换,时间复杂度为O(n)

希尔排序:

相同的元素会分到不同的子序列,可能会破坏相对顺序,故为不稳定的排序算法

空间复杂度为常量O(1)(内部是插入排序)

最坏情况和平均时间复杂度都是O(nlog2 n),最好情况不确定

归并排序:

分割和归并的时候都不会改变相对顺序,故是稳定的排序算法

需要一个辅助数组,空间复杂度是O(n),递归需要保存的空间为O(log2 n),所以加起来仍然是O(n)

假设数组长度为n,那么拆分数组共需log2 n,, 又每步都是一个普通的合并子数组的过程,
4000
时间复杂度为O(n), 故其综合时间复杂度为O(nlog2 n)

通过自上而下的递归实现的归并排序, 将存在堆栈溢出的风险。

快速排序:

同选择排序相似, 快速排序每次交换的元素都有可能不是相邻的, 因此它有可能打破原来值为相同的元素之间的顺序. 因此, 快速排序并不稳定

首先就地快速排序使用的空间是O(1);而真正消耗空间的就是递归调用了,因为每次递归就要保持一些数据;最优的情况下空间复杂度为O(log2 n),每一次都平分数组;最差的情况下空间复杂度为O( n ),退化为冒泡排序的情况

平均时间复杂为O(nlog2 n),最糟糕时将达到O(n²)的时间复杂度

堆排序:

并不是邻近交换,故为不稳定排序

不需要辅助数组,空间复杂度为O(1)

建立堆的过程, 从n/2 一直处理到0, 时间复杂度为O(n),调整堆的过程是沿着堆的父子节点进行调整, 执行次数为堆的深度log2 n,一共要执行n次,加起来时间复杂度未O(nlog2 n)

图片总结



参考

八大排序算法总结与java实现

七种常见经典排序算法总结(C++实现)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  数据结构与算法
相关文章推荐