排序
冒泡排序
1.虽然容易理解,但是容易TLE;
2.冒泡排序就是每次排序至少能将一个数放在它应该出现的位置,所以如果有n个元素,则需要n-1次排序;
冒泡排序_代码模板
#include<bits/stdc++.h>
using namespace std;
int n;
int arr[100000] = { 0 };
void maopao_sort(int arr[], int sz)
{
for (int i = 0; i < sz - 1; i++)
{
for (int j = 0; j < sz - 1 - i; j++)
{
if (arr[j] > arr[j + 1])
{
swap(arr[j], arr[j + 1]);
}
}
}
}
int main()
{
scanf("%d", &n);
for (int i = 0; i < n; i++)
{
scanf("%d", &arr[i]);
}
maopao_sort(arr, n);
for (int i = 0; i < n; i++)
{
printf("%d ", arr[i]);
}
return 0;
}
快速排序
本质是分治,一般情况下在算法竞赛中很难用到(毕竟大部分排序题都是一个sort就能解决的问题),基本上只有面试官在面试时会让你手打;
快速排序_基本思路
1.选择中心轴pivot(我个人喜欢将pivot直接放在最左最右,但是可能刚好处理不了个数为100000的数组);
2.将大于pivot的值放在其右,小于的放在其左;
3.分别对pivot左右两子序列重复上述操作。
快速排序_操作步骤
1.为了方便,选取最左边的数字为中心轴pivot,并将其放在一边,并在原位置设定一个left指针,从左往右读取,在最右边设计一个right指针,从右往左读取;
例如下图,我们选择19为pivot,然后把19单独提出来,再把最左定为left(因为19被拿走了,所以这里left指向的是一个空数组),最右定为right

2.如果left发现比pivot大的数字,就把该数字放在right上,反之则不移动该数字,跳过right的当前回合,left读取下一位,right同left一样移动法则;
如下图

因为L为空,所以从R先开始,8<19,8挪到L的位置

R移动了数字,回合结束,L往前走一格

97>19,97挪到R位置,L回合结束

R往前走一格,1 < 19 , 1挪到L处

R回合结束,L往前走一格,9 < 19,符合条件,不挪动9

L获得一个额外的回合,17 < 19 , 17不动

L再获得一个额外的回合,再走一格,与R重合
3.最终,left和right会在该序列的某一处相遇,把pivot放在该位置,这就完成了第一次排序,后面再对左右子序列重复以上操作即可。如果有左或右子序列只有一个或无元素,则无需再对该序列进行排序;


快速排序_代码模板
#include<bits/stdc++.h>
using namespace std;
int n;
int arr[100005];
void quicksort(int arr[], int l, int r)
{
if (l >= r)//判断没有或者是否只有一个元素
{
return;//说明该序列或左右子序列完成快排
}
int left = l;
int right = r;
int pivot = arr[left];//定中心轴
while (left < right)//如果左比右小
{
while (left < right && arr[right] >= pivot)
{
right--;//右指针必须大于左指针下标,并且如果所代表数大于中心轴,则移动至下一位
}
if (left < right)//防止left = right特判被误判
{
arr[left] = arr[right];//把右边的数移动到左指针的位置
}
while (left < right && arr[left] <= pivot)//同理
{
left++;
}
if (left < right)
{
arr[right] = arr[left];
}
}
if (left >= right)//在左右指针交合之处丢下中心轴
{
arr[left] = pivot;
}
quicksort(arr, l, right - 1);//对左右子序列不断进行快排
quicksort(arr, left + 1, r);
}
int main()
{
cin >> n;
for (int i = 0; i < n; i++)
{
cin >> arr[i];
}
quicksort(arr, 0, n - 1);
for (int i = 0; i < n; i++)
{
printf("%d ", arr[i]);
}
return 0;
}
归并排序_基本思路
1.先将序列中的每个数字单独设为一组;
2.再将每两个组合中的数字合并为一个组合,保证组合后的数字是有序的;
3.重复第二步,直到只剩下一组。
归并排序_具体步骤
1.将序列中的每个数字单独设为一组

2.两两合并,并保持有序


3.再将得到的组合再次两两合并


4.继续两两合并


归并排序_代码模板
#include<bits/stdc++.h>
using namespace std;
const int N = 100000;
int n;
int arr[N] = { 0 };
int tmp[N];
void merge_sort(int arr[], int l, int r)
{
if (l >= r)//左右指针重合,返回
{
return;
}
int mid = (l + r) / 2;
merge_sort(arr, l, mid);//递归排序左边
merge_sort(arr, mid + 1, r);//递归排序右边
//以下归并,把结果放入tmp
int k = 0;
int i = l, j = mid + 1;//i为左边最开始点,j为右边最开始点;
while (i <= mid && j <= r)//当左半边和右半边都没有循环空的话;
{
if (arr[i] <= arr[j])
{
tmp[k++] = arr[i++];//把每一个小的放在我们当前位置上去;
}
else
{
tmp[k++] = arr[j++];
}
}
while (i <= mid)//这两个while是如果有一边没有循环完的话,直接接入答案;
{
tmp[k++] = arr[i++];
}
while (j <= r)
{
tmp[k++] = arr[j++];
}
for (i = l, j = 0; i <= r; i++, j++)
{
arr[i] = tmp[j];//把存在tmp的结果赋值回arr;
}
}
int main()
{
scanf("%d", &n);
for (int i = 0; i < n; i++)
{
scanf("%d", &arr[i]);
}
merge_sort(arr, 0, n - 1);
for (int i = 0; i < n; i++)
{
printf("%d ", arr[i]);
}
return 0;
}
sort
唯一真神
sort相关模板
sort(a + 0 , a + n);//从a[0]拍到a[n - 1];
is_sorted(a + 0 , a + n);//判断从a[0]到a[n - 1]是否为升序,若为升序,返回true;否则返回false
#include<bits/stdc++.h>
using namespace std;
int n;
int a[100005];
int main()
{
cin >> n;
for(int i = 0 ; i < n ;i++)
{
cin >> a[i];
}
int *p = is_sorted_until(a , a + n);
cout << p - a << endl;//有p - a个数字遵循升序排列(要从下标0开始排为最好);
cout << *p << endl;//*p直接表示那个数字打断了排列,如果没有打断的,会返回0;
return 0;
}

浙公网安备 33010602011771号