2023-11-23
算法
00
请注意,本文编写于 359 天前,最后修改于 44 天前,其中某些信息可能已经过时。

目录

一、快速排序
j划分
i划分
二、归并排序
三、二分查找
整数二分
做法1
做法2
浮点数二分

本节主要介绍快速排序、归并排序、二分查找。

一、快速排序

更详细解释可看此链接:AcWing

j划分

c++
#include <iostream> using namespace std; const int N = 1e6 + 10; int n; int q[N]; void quick_sort(int q[], int l, int r) { if (l >= r) return; //递归的终止情况 //第一步:分成子问题 int x = q[(l + r) >> 1], i = l - 1, j = r + 1; while (i < j) { do i++; while (q[i] < x); do j--; while (q[j] > x); if (i < j) swap(q[i], q[j]); } //第二步:递归处理子问题 quick_sort(q, l, j); quick_sort(q, j + 1, r); //第三步:子问题合并.快排这一步不需要操作,但归并排序的核心在这一步骤 } int main() { scanf("%d", &n); for (int i = 0; i < n; i++) scanf("%d", &q[i]); quick_sort(q, 0, n - 1); for (int i = 0; i < n; i++) printf("%d ", q[i]); return 0; }

i划分

c++
#include <iostream> using namespace std; const int N = 1e6 + 10; int n; int q[N]; void quick_sort(int q[], int l, int r) { if (l >= r) return; //递归的终止情况 //第一步:分成子问题 int x = q[(l + r + 1) >> 1], i = l - 1, j = r + 1; while (i < j) { do i++; while (q[i] < x); do j--; while (q[j] > x); if (i < j) swap(q[i], q[j]); } //第二步:递归处理子问题 quick_sort(q, l, i - 1); quick_sort(q, i, r); //第三步:子问题合并.快排这一步不需要操作,但归并排序的核心在这一步骤 } int main() { scanf("%d", &n); for (int i = 0; i < n; i++) scanf("%d", &q[i]); quick_sort(q, 0, n - 1); for (int i = 0; i < n; i++) printf("%d ", q[i]); return 0; }

二、归并排序

c++
#define _CRT_SECURE_NO_WARNINGS #include <iostream> using namespace std; const int N = 1000010; int n; int q[N], tmp[N]; void merge_sort(int q[], int l, int r) { if (l >= r) return; int mid = l + r >> 1; merge_sort(q, l, mid), merge_sort(q, mid + 1, r); int k = 0, i = l, j = mid + 1; while (i <= mid && j <= r) if (q[i] <= q[j]) tmp[k++] = q[i++]; else tmp[k++] = q[j++]; while (i <= mid) tmp[k++] = q[i++]; while (j <= r) tmp[k++] = q[j++]; for (int i = l, j = 0; i <= r; i++, j++) q[i] = tmp[j]; } int main() { scanf("%d", &n); for (int i = 0; i < n; i++) scanf("%d", &q[i]); merge_sort(q, 0, n - 1); for (int i = 0; i < n; i++) printf("%d ", q[i]); return 0; }

三、二分查找

整数二分

做法1

c++
#include <iostream> using namespace std; const int N = 100010; int n, m; int q[N]; int main() { scanf("%d%d", &n, &m); for (int i = 0; i < n; i++) scanf("%d", &q[i]);//要求q[N]由小到大 while (m--) { int x; scanf("%d", &x); int l = 0, r = n - 1; while (l < r) { int mid = l + r >> 1; if (q[mid] >= x) r = mid;//q[mid]>=x,则x在mid左边(包含mid),所以r=mid else l = mid + 1;//否则,q[mid]<=x,则x在mid右边,所以l=mid+1 }//多次二分循环,找出区间左端点 if (q[l] != x) cout << "-1 -1" << endl;//如果q[l]!=x,说明不存在x else { cout << l << ' '; int l = 0, r = n - 1; while (l < r) { int mid = l + r + 1 >> 1;//+1避免陷入死循环 if (q[mid] <= x) l = mid;//(包含mid) else r = mid - 1; }//多次二分循环,找出区间右端点 cout << l << endl; } } return 0; }

做法2

c++
#include <iostream> using namespace std; const int N = 1e5 + 10; int q[N]; int SL(int l, int r, int x) { while (l < r) { int mid = l + r >> 1; if (q[mid] >= x) r = mid; else l = mid + 1; } return l; } int SR(int l, int r, int x) { while (l < r) { int mid = l + r + 1 >> 1; if (q[mid] <= x) l = mid; else r = mid - 1; } return r; } int main() { int n, m; scanf("%d%d", &n, &m); for (int i = 0; i < n; ++i) scanf("%d", &q[i]); while (m--) { int x; scanf("%d", &x); int l = SL(0, n - 1, x);//查找左边界,并返回下标1 if (q[l] != x) cout << "-1 -1" << endl;//如果找不到,返回-1 -1 else { cout << l << ' ';//如果找到了,输出左下标 cout << SR(0, n - 1, x) << endl;//输出右下标 } } return 0; }

浮点数二分

c++
#include <iostream> using namespace std; int main() { double x; cin >> x; double l = 0, r = x; while (r - l > 1e-8) { double mid = (l + r) / 2; if (mid * mid >= x) r = mid; else l = mid; } printf("%lf\n", l); return 0; }

本文作者:Travis

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 Travis 许可协议。转载请注明出处!