排序:快排,归并排序
二分:整数,浮点数

1,快速排序大排列

​785.快速排序测试​

https://www.acwing.com/problem/content/787

算法学习(1)快速排序/归并排序/二分_i++

常规递归查找(不可以)

#include<iostream>
using namespace std;

const int N = 100001;
int Partion(int[], int, int);
void Qsort(int a[], int low, int high) {
if (low < high) {
int p = Partion(a, low, high);
Qsort(a, low, p - 1);
Qsort(a, p + 1, high);
}
}
int Partion(int a[], int low, int high) {
int p = a[low];
while (low < high) {
while (low < high && a[high] >= p) high--;
a[low] = a[high];
while (low < high && a[low] <= p) low++;
a[high] = a[low];
}
a[low] = p;
return low;
}
int main() {
int a[N];
int size = 0;
cin >> size;
for (int i = 0; i < size; i++) {
cin >> a[i];
}
Qsort(a, 0, size - 1);
for (int i = 0; i < size; i++) {
cout << a[i] << " ";
}
}

递归法改进(可以)

算法学习(1)快速排序/归并排序/二分_i++_02

#include<iostream>
using namespace std;

const int N = 100001;
int a[N] = { 0 };


void Qsort(int a[], int low, int high) {
if (low >= high)
return;

int p = a[(low + high) >> 1], i = low - 1, j = high + 1; // j >= l,i<=r-1

while (i < j) {
//a[0..i-1] <= p, a[i] >= p
do
i++;
while (a[i] < p);

// a[j+1..r] >= p, a[j] <= p
do
j--;
while (a[j] > p);

if (i < j)
swap(a[i], a[j]);
}
Qsort(a, low, j);
Qsort(a, j + 1, high);
}

int main() {
int size;
cin >> size;
for (int i = 0; i < size; i++) {
cin >> a[i];
}
Qsort(a, 0, size - 1);
for (int i = 0; i < size; i++) {
cout << a[i] << " ";
}
}

#include<iostream>
using namespace std;

const int N = 100001;
int a[N] = { 0 };

void Qsort(int a[], int low, int high) {
if (low >= high)
return;

int i = low - 1, j = high + 1, p = a[(low + high + 1) >> 1];//

while (i < j) {
do
i++;
while (a[i] < p);

do
j--;
while (a[j] > p);


if (i < j)
swap(a[i], a[j]);
}

Qsort(a, low, i-1);
Qsort(a, i, high);
}

int main() {
int size = 0;
cin >> size;
for (int i = 0; i < size; i++) {
cin >> a[i];
}
Qsort(a, 0, size - 1);
for (int i = 0; i < size; i++) {
cout << a[i] << " ";
}
}

方法分析:https://www.acwing.com/solution/content/16777/

2、归并排序

​787.归并排序测试​

​https://www.acwing.com/problem/content/description/789​算法学习(1)快速排序/归并排序/二分_i++_03

常规递归查找(不可以)

#include<iostream>
using namespace std;

const int N = 100000;
int a[N],s[N];

// 比较放入
void Merge(int a[], int b[], int low, int high);
// 比较排序
void Msort(int a[], int b[], int low, int high);

void Msort(int a[], int b[], int low, int high) {
int t[N] = { 0 };
//第一步:分成子问题
if (low == high) {
b[low] = a[high];
}else {
int mid = (low + high) >> 1;
//第二步:递归处理子问题
Msort(a, t, low, mid);
Msort(a, t, mid + 1, high);
//第三步:子问题合并
Merge(t, b, low, high);
}
}
void Merge(int a[], int b[], int low, int high) {
int mid = (low + high) >> 1;
int i = low, j = mid + 1,k=low;
while (i <= mid && j <= high) {
b[k++] = (a[i] <= a[j] ? a[i++] : a[j++]);
}
while (i <= mid) b[k++] = a[i++];
while (j <= high) b[k++] = a[j++];
}
int main() {
int size = 0;
scanf_s("%d", &size);
for (int i = 0; i < size; i++) {
cin >> a[i];
}
Msort(a, s, 0,size-1);
for (int i = 0; i < size; i++) {
cout << s[i] << " ";
}
}

算法学习(1)快速排序/归并排序/二分_i++_04

递归法改进

#include<iostream>
using namespace std;

const int N = 100000;
// 输入
int a[N],i,j;

void MergeSort(int a[], int low, int high) {
if (low >= high) return;
int mid = (low + high) >> 1;
MergeSort(a, low, mid);
MergeSort(a, mid + 1, high);
i = low, j = mid + 1;
int k = 0;
int* tmp = (int*)malloc(sizeof(int) * (high - low + 1));
while (i <= mid && j <= high) {
tmp[k++] = a[i] < a[j] ? a[i++] : a[j++];
}
while (i <= mid)
tmp[k++] = a[i++];
while (j <= high)
tmp[k++] = a[j++];
for (i = 0; i < high - low + 1; i++) {
a[low + i] = tmp[i];
}
free(tmp);
}
int main() {
int size = 0;
cin >> size;
for (i = 0; i < size; i++) {
cin >> a[i];
}
MergeSort(a, 0, size - 1);
for (i = 0; i < size; i++) {
cout << a[i] << " ";
}
}

3、二分法查找

​789. 数的范围​

​https://www.acwing.com/problem/content/791/​算法学习(1)快速排序/归并排序/二分_#include_05

整数二分的模板:

// 判断mid是否满足性质 
bool check(int);

int bsearch_1(int l, int r) {
while (l < r) {
int mid = l + r >> 1;
if (check(mid))
r = mid;
else
l = mid + 1;
}
return l;
}

int bsearch_2(int l, int r) {
while (l < r) {
int mid = l + r + 1 >> 1;
if (check(mid))
l = mid;
else
r = mid - 1;
}
return l;
}
#include<iostream>
using namespace std;
const int N = 100010;
int q[N];

int main() {
int n, m, i, x;
cin >> n >> m;
for (i = 0; i < n; i++) {
cin >> q[i];
}
// 需要写两个二分,一个需要找到 >= x的第一个数,另一个需要找到 <= x的最后一个数
while (m--) {
cin >> x;
int l = 0, r = n - 1;
int mid;

while (l < r) {
mid = (l + r) >> 1;
if (q[mid] >= x)
r = mid;
else
l = mid + 1;
}

if (q[l] != x) {
cout << "-1 -1" << endl;
continue;
}
else {
cout << l << " ";
l = 0, r = n - 1;
while (l < r) {
mid = (l + r+1) >> 1;
if (q[mid] <= x)
l = mid;
else
r = mid - 1;
}
cout << l << endl;
}
}
return 0;
}

浮点数二分的模板

例如 求浮点数开方:

#include<iostream>
using namespace std;
int main() {
double x,mid;
cin >> x;
double l = 0, r = x;
while (r - l > 1e-6) { // 保留四位小数
mid = (l + r) / 2;
if (mid * mid >= x)
r = mid;
else
l = mid;
}
cout << l << endl;
}

​数的三次方:​

​https://www.acwing.com/problem/content/description/792/​算法学习(1)快速排序/归并排序/二分_#include_06
二分法:

#include<iostream>
#include <iomanip>
using namespace std;
// x^3 =n -> x=?
void test_half() {
double n;
cin >> n;
//结果保留6位小数 −10000≤n≤10000
double precision = 1e-8;
double l = -10000, r = 10000, mid = 0;
while (r - l > precision) {
mid = (l + r) / 2;
if (mid * mid * mid >= n)
r = mid;
else
l = mid;
}
// 或 printf("%.6f", l);
cout<< setiosflags(ios::fixed) << setprecision(6)<< l << endl;
}

int main() {
test_half();
}

牛顿法

#include<iostream>
#include <iomanip>
#include<math.h>
using namespace std;
void test_newton() {
double n;
cin >> n;
//结果保留6位小数 −10000≤n≤10000
double precision = 1e-8;
double x0 = 1 , x1;
x1 = x0 - (x0 * x0 * x0 - n) / (3 * x0 * x0);
while (fabs(x1 - x0) >= precision) {
x0 = x1;
x1 = x0 - (x0 * x0 * x0 - n)/ (3 * x0 * x0) ;
}
cout << setiosflags(ios::fixed) << setprecision(6) << x1 << endl;
}
int main() {
test_newton() ;
}