#include<iostream>
using namespace std;
#include<vector>
#include<algorithm>
void insert_sort(vector<int>& arr)
{
/*
* 注意稳定性的保护
* 可以用折半优化比较次数,但是元素移动是没有办法的
* 用链表存储的数据,虽然元素移动减少了,但是比较次数还是O(n^2)
* 不过当元素基本有序时,链表的效率就很高;数组的效率也会得到提升
*/
int n = arr.size();
for (int i = 1; i < n; i++)
{
if (arr[i - 1] > arr[i])
{
int key = arr[i];
int j;
for (j = i - 1; j >= 0 && arr[j] > key; j--)
arr[j+ 1] = arr[j];
arr[j + 1] = key;
}
}
}
void shell_sort(vector<int>& arr)
{
/*
* 希尔排序:基于插入排序优化(插入排序在元素基本有序时效率较高,那么我们缩小数组长度,让其经过一次遍历后的到基本有序,从而利用好这一特性)
* 把待排序的数组,拆分成相距距离为d的视为一个组,对每个小组进行插入排序
* 只适用于数组,不能用于链表,因为每次都要根据下标快速定位到下一个子表中,链表存储是无法做到的
*/
int n = arr.size();
int d = n / 2;
while (d >= 1) {
for (int i = d; i < n; i++)//i++不用变 for (int i = 1; i < n; i++)
{
if (arr[i - d] > arr[i]) //if (arr[i - 1] > arr[i])
{
int key = arr[i];
int j;
for (j = i - d; j >= 0 && arr[j] > key; j-=d) //减1都变成减d for (j = i - 1; j >= 0 && arr[j] > key; j--)
arr[j+ d] = arr[j];//从后往前把元素后移
arr[j + d] = key;
}
}
d /= 2;
}
}
void bubble_sort(vector<int>& arr)
{
/*具有稳定性,O(n^2)
* 可以用于链表
*/
int n = arr.size();
for (int i = 0; i < n-1 ; i++)//n-1趟
{
bool flag = false;
for (int j = 1; j < n-i; j++)//把大的元素往后冒,每趟的元素都会减少,因为一趟会确定一个元素的顺序位置
{
if (arr[j] < arr[j - 1])
{
swap(arr[j], arr[j - 1]);
flag = true;//说明本次遍历进行了交换
}
}
if (flag)return;//如果一趟排序没有交换任何元素,说明数组已经有序
}
}
void merge(vector<int>& vec, int left, int mid, int right, vector<int>& temp)
{
int i, j, k;
for (i = left, j = mid, k = left; i < mid && j < right; k++)
{
if (vec[i] < vec[j])
temp[k] = vec[i++];
else temp[k] = vec[j++];
}
while(j < right)
temp[k++] = vec[j++];
while (i < mid)
temp[k++] = vec[i++];
}
void merge_sort(vector<int>& vec,int left,int right,vector<int>& temp)
{
if (right - left <= 1)
return;
int mid = (left + right) / 2;
merge_sort(vec, left, mid, temp);
merge_sort(vec, mid, right, temp);
merge(vec, left, mid, right, temp);
vec = temp;
}
int paration(vector<int>& vec, int left, int right)
{
int key = vec[left];//把最左侧结点提出,下面while先去移动right,找小于key的
while (left < right)
{
while (left < right && vec[right] >= key) right--;
vec[left] = vec[right];
while (left < right && vec[left] <= key) left++;//在上面相当于right此时被提出
vec[right] = vec[left];
}
vec[left] = key;//给枢轴位置赋key
return left;
}
void qsort(vector<int>& vec,int left,int right)
{
/*时空复杂度都和递归栈深度相关
* 最好情况O(nlogn),一般也是这样
* 最坏情况,每次qsort得到的枢轴将数都只能划走一个元素,就成了单边树
* 此时递归深度就是n,时间复杂度就是O(n^2)
* 不稳定
*/
if (right - left < 1)
return;
int pviot = paration(vec,left,right);
qsort(vec,left, pviot-1);
qsort(vec,pviot + 1, right);
}
//[ left, right]
//void qsort(vector<int>& arr,int left ,int right)
//{
// int i = left;
// int j = right;
// int key = arr[right];
// while (i < j)
// {
// while (arr[i] < key)//小于枢轴key,指针i一直向后移动
// {
// i++;
// }
// while (arr[j] > key)//大于枢轴,指针j向前移动
// {
// j--;
// }
//
// //上面的两步都没有边界判断,会越界吗?
// //不会,因为while的判断条件是arr[i] < key,只有小于才会移动,那么极限情况key刚好是最大值,
// //i==right-1时就会移动到right,此时i继续+1,这时while判断就会失败因为两值相等,所以i就停在了right
//
// if (i <= j)
// {
// //上面先移动i,故而最后情况是:i停在了一个大于等于key的值,j停在了一个小于等于key的值,此时交换两值
// //每次都是i先移动,能不能让j先移动呢,是可以的,但是只有i<=j这才合法,才会交换
// swap(arr[i], arr[j]); // i==j时,不用swap但是要i++,j--
// i++;
// j--;
// }
// }
//
// if (j > left)
// qsort(arr, left, j);//上面在最后的i==j时,i和j都已近各自向前向后移动了,这里就不用区间-1
// if (i < right)
// qsort(arr, i, right);
//}
//void qsort(vector<int>& arr, int left, int right)//[left,right],极简快排
//{
// int key = arr[right], i = left, j = right;
// while (i < j)
// {
// while (arr[i] < key)i++;
// while (arr[j] > key)j--;
// if (i <= j)swap(arr[i++], arr[j--]);
// }
// if (j > left)qsort(arr, left, j);
// if (i < right)qsort(arr, i, right);
//}
void choice_sort(vector<int>& arr)
{
/*
* 可用于链表,不稳定
*/
int n = arr.size();
for (int i = 0; i < n - 1; i++)
{
int min_pos = 0;
for (int j = i + 1; j < n; j++)
{
if (arr[min_pos] > arr[j])
j = min_pos;
}
swap(arr[min_pos], arr[i]);
}
}
void adjustdown(vector<int>& arr, int parent, int end)
{
int child = parent * 2 + 1;
while (child < end)
{
if (child + 1 < end && arr[child + 1] > arr[child])
child++;
if (arr[parent] < arr[child])
swap(arr[parent], arr[child]);
parent = child;
child = parent * 2 + 1;
}
}
void heap_sort(vector<int>& arr)
{
/*
* 堆结构:在完全二叉树中,根 <= 左、右(小根堆)
* 把所有非叶子结点都检查一遍,是否满足大根堆的要求,如不满足,进行调整
* 调整要调到叶节点才算结束
* 不稳定,O(nlogn)
*/
int n = arr.size();
for (int root = n / 2; root >= 0; root--)
adjustdown(arr, root, n - 1);
int end = n - 1;
while (end > 0)
{
swap(arr[end], arr[0]);
adjustdown(arr, 0,end);
end--;
}
}
int main()
{
vector<int> vec{ 98, 2, 123, 435, 1, 5, 62, 12, 634, 5, 9, 999 };
//shell_sort(vec);
auto temp = vec;
merge_sort(vec, 0, vec.size(), temp);
//qsort(vec, 0, vec.size()-1);
heap_sort(vec);
//bubble_sort(vec);
for_each(vec.begin(), vec.end(), [](int x) {cout << x << " "; });
return 0;
}
再谈排序
最新推荐文章于 2024-07-24 19:27:00 发布