排序算法是算法中很重要的一块,尝试使用Java,Python,C++来予以实现,也为后边借鉴提供参考。
排序算法的重要属性——稳定性
当待排序记录的关键字均不相同的时,排序结果是唯一的,否则排序结果是不唯一。
在待排序的文件中,若存在多个关键字相同的记录,经过排序后,这些具有相同关键字的记录之间的相对次序保持不变,该排序方法是稳定;若具有相同关键字之间的相对次序发生变化,则称这种排序方法是不稳定的。
算法的稳定性如下表,摘自《Java面试宝典》这本书有很多纰漏,希望这个图没有。
稳定的排序
算法 | 时间复杂度 | 空间复杂度 |
---|---|---|
气泡排序(bubbleSort) | 最差、平均都是O(n^2),最好O(n) | 1 |
插入排序(insertSort) | 最差、平均都是O(n^2),最好O(n) | 1 |
归并排序(mergeSort) | 最差、平均和最好都是O(nlogn) | O(n) |
桶排序(bucketSort) | O(n) | O(k) |
基数排序(radixSort) | O(dn) (d是常数) | O(n) |
二叉树排序(binarySort) | O(nlogn) | O(n) |
不稳定的排序
算法 | 时间复杂度 | 空间复杂度 |
---|---|---|
选择排序(selectSort) | 最差、平均都是O(n^2) | 1 |
希尔排序(shellSort) | O(nlogn) | 1 |
d堆排序(heapSort) | 最差、平均和最好都是O(nlogn) | 1 |
快速排序(bucketSort) | 平均是O(nlogn), 最坏都是O(n^2) | O(logn) |
接下来对一些排序算法予以代码实现并做简单的解释
1. 冒泡算法
*冒泡算法有两种形式,
一种是列表的头部向后扫描,也就是说排好序的部分是列表的尾部。
另一种是列表的尾部向前扫描,也就是说排好序的部分是列表的头部。*
Java version
// Sort.java
package com.nokia.sorts;
import java.util.List;
public interface Sort <T extends Comparable<T>> {
public List<T> sort(List<T> data);
}
// BubbleSort.java
package com.nokia.sorts;
import java.util.List;
public class BubbleSort<T extends Comparable<T>> implements Sort<T> {
// from head to tail to bubble sort
@Override
public List<T> sort(List<T> data) {
if (null == data || data.size() <= 1) {
return data;
}
// outer cycle will cycle from index [data.size() - 1, 0), then the outer interator will decrease itself by one, then the tail part list will be ok by one time bubble sort, which need n-1 times bubble sort.
for (int i = data.size() - 1; i > 0; --i) {
for (int j = 0; j < i; ++j) {
if (data.get(j).compareTo(data.get(j + 1)) > 0) {
T temp = data.get(j);
data.set(j, data.get(j + 1));
data.set(j + 1, temp);
}
}
}
return data;
}
// from tail to head with bubble sort
public List<T> anotherSort(List<T> data) {
if (null == data || data.size() <= 1) {
return data;
}
// here is reverse from the above one.
for (int i = 0; i < data.size() - 1; ++i) {
for (int j = data.size() - 1; j > i; --j) {
if (data.get(j - 1).compareTo(data.get(j)) > 0) {
T temp = data.get(j - 1);
data.set(j - 1, data.get(j));
data.set(j, temp);
}
}
}
return data;
}
}
C++ version
// C++ template function, which can define the sorted data type, which can genertic the sort method.
// This C++ version of the bubbleSort method is same with the Java version of from tail to head to scan the list, apart from that, I add one flag, which to indicate if there is no exchange operation in one cycle bubble sort, that means the sort is finished, which will save the time.
template<class T>
template<class T>
void BubbleSort(T* data, int length)
{
bool flag = true;
for (int i = 0; i < length - 1 && flag; ++i)
{
flag = false; // yes, this flag.
for (int j = length - 1; j > i; --j)
{
if (data[j] < data[j - 1])
{
Exchange(data[j], data[j - 1]);
flag = true;
}
}
}
}
// this function used for to swap two variables, which can also be implements by the std::swap method, please reference it by yourself.
template <class T>
void Exchange(T &data1, T &data2)
{
T temp;
temp = data1;
data1 = data2;
data2 = temp;
}
Python version
def bubbleSort(data):
length_of_data = len(data)
for i in range(length_of_data - 1):
for j in range(length_of_data - 1, i, -1):
if (data[j-1] > data[j]):
temp = data[j-1]
data[j-1] = data[j]
data[j] = temp