排序——选择排序 + 插入排序
1. 选择排序
1.1 算法思想
选择排序应该说是最简单的排序算法,它的核心思想是不断地选择剩余元素中最小者。
选择排序的过程是:首先,找到数组中最小的元素,然后将它与数组中的第一个元素交换位置(如果第一个元素是最小的元素,则和自己交换);接着,从剩下的元素中找到最小的元素,将它与数组中的第二个元素交换位置。如此往复,直到将整个数组排序。
1.2 代码
class Selection {
public:
void data_sort(vector<int> &a) {
int i, j, k;
for(i=0; i<a.size()-1; ++i) {
j = i; // j是最小元素的索引
for(k=i+1; k<a.size(); ++k) {
if(a[k] < a[j]) {
j = k;
}
}
k = a[j];
a[j] = a[i];
a[i] = k;
}
}
};
1.3 算法分析
对于长度为N的数组,选择排序:
(1)时间复杂度为 N 2 N^2 N2;
(2)空间复杂度为 1;
(3)不是稳定排序;
(4)是原地排序。
2. 插入排序
2.1 算法思想
插入排序从数组的最左端开始,依次往右:对于当前的索引,其左边的所有元素都是有序的,但它们的最终位置还不确定,为了给更小的元素腾出空间,它们可能会被移动。当索引到达数组的右端时,数组排序就完成了。
2.2 代码
class Insertion {
public:
// 将a[]按升序排列
void data_sort(vector<int>&a) {
int i, j, k;
for(i=1; i<a.size(); ++i) {
j = i;
k = a[i];
// 将a[i]前面比它小的数往后移
while(j - 1 >= 0 && a[j-1] > k) {
a[j] = a[j-1];
j--;
}
a[j] = k; // 将a[i]插进来
}
}
};
2.3 算法分析
命题:插入排序(1)所需的交换操作和数组中倒置的数量相同;(2)需要的比较次数大于等于倒置的数量,小于等于倒置的数量加上数组的大小再减一。
证明:(1)每次交换都改变了两个顺序颠倒的元素的位置,当倒置数量为0时,数组就有序了;(2)每次交换都对应着一次比较,且 1 到 N-1 之间的每个 i 都可能需要一次额外的比较(例如,其实整个数组在一开始就是有序的,那么进行的 N-1 次比较都是额外的)。
对于长度为N的数组,插入排序:
(1)时间复杂度介于 N N N 和 N 2 N^2 N2 之间;
(2)空间复杂度为 1;
(3)是稳定排序;
(4)是原地排序。