以下是一些插入排序的代码
1.插入排序
1.直接插入排序
// 升序
// 最坏:O(N^2) 逆序
// 最好:O(N) 顺序有序
void InsertSort(vector<int>& a, int n)
{
for (int i = 1; i < n; i++)
{
int end = i - 1;
int tmp = a[i];
// 将tmp插入到[0,end]区间中,保持有序
while (end >= 0)
{
if (tmp < a[end])
{
a[end + 1] = a[end];
--end;
}
else
{
break;
}
}
a[end + 1] = tmp;
}
}
//一个一个插入 一个 一个排序
2.折半插入排序
折半插入排序本质上就是 插入排序 +二分查找
// 折半插入排序函数
void binaryInsertionSort(std::vector<int>& arr) {
int n = arr.size();
for (int i = 1; i < n; ++i) {
int key = arr[i];
int left = 0, right = i - 1;
// 二分查找插入位置
while (left <= right) {
int mid = left + (right - left) / 2;
if (arr[mid] > key) {
right = mid - 1;
}
else {
left = mid + 1;
}
}
// 将元素后移
for (int j = i - 1; j >= left; --j) {
arr[j + 1] = arr[j];
}
// 插入元素
arr[left] = key;
}
}
3.希尔排序
//希尔排序
void ShellSort(vector<int>&a, int n)
{
/*int gap = 3;
for (int j = 0; j < gap; j++)
{
for (int i = j; i < n - gap; i += gap)
{
int end = i;
int tmp = a[i + gap];
while (end >= 0)
{
if (tmp < a[end])
{
a[end + gap] = a[end];
end -= gap;
}
else
{
break;
}
}
a[end + gap] = tmp;
}
}*/
// gap > 1 预排序
// gap == 1 直接插入排序
int gap = n;
while (gap > 1)
{
//gap /= 2;
gap = gap / 3 + 1;//除2是不用+1的 因为你能保证最后gap一定是1 gap为1就是直接插入排序 但是/3就不能保证了!
for (int i = 0; i < n - gap; i++)
{
int end = i;
int tmp = a[i + gap];
while (end >= 0)
{
if (tmp < a[end])
{
a[end + gap] = a[end];
end -= gap;
}
else
{
break;
}
}
a[end + gap] = tmp;
}
//PrintArray(a, n);
}
}
希尔排序的这两种实现方式的时间复杂度是一模一样的 只是遍历的方式不一样
2.选择排序
1.直接选择排序
void Swap(int& a, int& b) {
int temp = a;
a = b;
b = temp;
}
// 直接选择排序函数
void SelectSort(int* a, int n) {
for (int i = 0; i < n - 1; ++i) {
int minIndex = i;
for (int j = i + 1; j < n; ++j) {
if (a[j] < a[minIndex]) {
minIndex = j;
}
}
if (minIndex != i) {
Swap(a[i], a[minIndex]);
}
}
}
可以对其进行优化 比如我一次选两个数出来
但是这个时候swap的时候要确认一下特殊情况
同时如果是有序的就可以直接break了 不用那么麻烦
void Swap(int* p1, int* p2)
{
int tmp = *p1;
*p1 = *p2;
*p2 = tmp;
}
void BubbleSort(int* a, int n)
{
for (int j = 0; j < n; j++)
{
bool exchange = false;
for (int i = 1; i < n-j; i++)
{
if (a[i - 1] > a[i])
{
Swap(&a[i - 1], &a[i]);
exchange = true;
}
}
if (exchange == false)
{
break;
}
}
}
2.堆排序
// 左右子树都是大堆/小堆
void AdjustDown(int* a, int n, int parent)
{
int child = parent * 2 + 1;
while (child < n)
{
// 选出左右孩子中大的那一个
if (child + 1 < n && a[child + 1] > a[child])
{
++child;
}
if (a[child] > a[parent])
{
Swap(&a[child], &a[parent]);
parent = child;
child = parent * 2 + 1;
}
else
{
break;
}
}
}
//堆排序
void HeapSort(int* a, int n)
{
// 建堆 -- 向下调整建堆 -- O(N)
for (int i = (n - 1 - 1) / 2; i >= 0; --i)
{
AdjustDown(a, n, i);
}
// 自己先实现 -- O(N*logN)
int end = n - 1;
while (end > 0)
{
Swap(&a[end], &a[0]);
AdjustDown(a, end, 0);
--end;
}
}
3.交换排序
1.冒泡排序
//冒泡排序
// 最坏:O(N^2)
// 最好:O(N)
void BubbleSort(int* a, int n)
{
for (int j = 0; j < n; j++)
{
bool exchange = false;
for (int i = 1; i < n - j; i++)
{
if (a[i - 1] > a[i])
{
Swap(&a[i - 1], &a[i]);
exchange = true;
}
}
if (exchange == false)
{
break;
}
}
}