【插入排序】直接插入排序、折半插入排序、希尔排序
直接插入排序
核心就是遍历数组,从后向前插入到先前一个已经有序的子序列中。每次都遵循“边比较边插入”,是一个\(O(n^2)\)的算法
点击查看代码
#include<iostream>
#include<vector>
using namespace std;
void InsertSort(vector<int> &grid) {
int size = grid.size() - 1;
if (size <= 1) return;
for (int i = 2; i <= size; i++) {
grid[0] = grid[i];
int j;
for (j = i - 1; grid[0] < grid[j]; j--) {
grid[j + 1] = grid[j];
}
grid[j + 1] = grid[0];
}
}
int main() {
int m, n;
cin >> m;
vector<int> a(m + 1);
for (int i = 1; i <= m; i++) {
cin >> n;
a[i] = n;
}
InsertSort(a);
for (int i = 1; i <= m; i++) {
cout << a[i] << endl;
}
}
折半插入排序
是直接插入排序的改进,改进的点就是将“边比较边插入”改成了先找到插入点,之后一次性插入。而对于找到插入点,用的就是折半查找。下面的用的是左闭右闭,使用左闭右开的可自行更改。同样,折半插入也是一个\(O(n^2)\)的算法
折半插入改进之后使得排序的比较次数改变,取决于表中元素个数n,而移动次数不变,仍然取决于初始状态。
点击查看代码
#include<iostream>
#include<vector>
using namespace std;
void InsertSort(vector<int> &grid) {
int size = grid.size() - 1;
if (size <= 1) return;
for (int i = 2; i <= size; i++) {
grid[0] = grid[i];
int left = 1;
int right = i - 1;
while (left <= right) {
int mid = (left + right) / 2;
if (grid[mid] > grid[0]) {// tar位于左区间,mid是左区间的右边界,更新右边界
right = mid - 1;
} else if (grid[mid] < grid[0]) { // tar位于右区间,mid为右区间的左边界,更新左边界
left = mid + 1;
}
}
for (int j = i - 1; j >= left; j--) {
grid[j + 1] = grid[j];
}
grid[left] = grid[0];
}
}
int main () {
int m, n;
cin >> m;
vector<int> a(m + 1);
for (int i = 1; i <= m; i++) {
cin >> n;
a[i] = n;
}
InsertSort(a);
for (int i = 1; i <= m; i++) {
cout << a[i] << endl;
}
}
希尔排序
希尔排序的就是在前面的部分引入了一个增量的概念,剩下的部分都就是将直接插入排序中递增1改为递增一个增量。所以,因为增量的引入,在dk比较大的时候,就像是在两两交换,但是在dk较小能将整个数组间隔开多个的时候,这些间隔开的数之间就是直接插入排序。
因为希尔排序这种多间隔的增量方式,使得希尔排序是一个不稳定的算法
点击查看代码
#include<iostream>
#include<vector>
using namespace std;
void ShellSort(vector<int> &grid) {
int size = grid.size() - 1;
if (size <= 1) return;
int dk, i, j;
for (dk = size/2; dk >= 1; dk/=2) {
for (i = dk + 1; i <= size; i++) {
if (grid[i] < grid[i - dk]) { // 如果grid[i] < grid[i - dk]才要进行排序,下面开始寻找插入位置
// 此时前面的部分相当于一个部分有序序列
grid[0] = grid[i];
for (j = i - dk; j > 0 && grid[0] < grid[j]; j-=dk) { //每次的增量是dk
grid[j + dk] = grid[j];
}
grid[j + dk] = grid[0];
}
}
}
}
int main() {
int m, n;
cin >> m;
vector<int> a(m + 1);
for (int i = 1; i <= m; i++) {
cin >> n;
a[i] = n;
}
ShellSort(a);
for (int i = 1; i <= m; i++) {
cout << a[i] << endl;
}
}