归并排序:
归并排序是建立在归并操作上的一种有效,稳定的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。
代码:
#include<iostream>
using namespace std;
void merge(int arr[],int left,int mid,int right){
int* temp=new int[right-left+1];
int i=left;
int j=mid+1;
int k=0;
while(i<=mid && j<=right){
if(arr[i]<=arr[j]){
temp[k]=arr[i];
i++;
k++;
}
else{
temp[k]=arr[j];
j++;
k++;
}
}
while(i<=mid){
temp[k]=arr[i];
i++;
k++;
}
while(j<=right){
temp[k]=arr[j];
j++;
k++;
}
k=0;
for(int i=left;i<=right;i++){
arr[i]=temp[k];
k++;
}
delete[] temp;
}
void merge_sort(int arr[],int left,int right){
if(left<right){
int mid=(left+right)/2;
merge_sort(arr,left,mid);
merge_sort(arr,mid+1,right);
merge(arr,left,mid,right);
}
}
int main(){
int a[100];
int n;
cin>>n;
for(int i=0;i<n;i++){
cin>>a[i];
}
merge_sort(a,0,n-1);
for(int i=0;i<n;i++){
cout<<a[i]<<" ";
}
cout<<endl;
return 0;
}
由于已分段排序,各非空段的首元素的最小值即是数组的最小值,不断从数组中取出当前最小值至辅助数组即可 使其有序,最后将其从辅助数组复制至原数组。
为保证排序的复杂度,通常将数组分为尽量等长的两段𝑚𝑖𝑑 = (𝑙 + 𝑟 )/2 。
二分查找:
首先,假设表中元素是按升序排列,将表中间位置记录的关键字与查找关键字比较,如果两者相等,则查找成功;否则利用中间位置记录将表分成前、后两个子表,如果中间位置记录的关键字大于查找关键字,则进一步查找前一子表,否则进一步查找后一子表。重复以上过程,直到找到满足条件的记录,使查找成功,或直到子表不存在为止,此时查找不成功。
代码:
#include<iostream>
using namespace std;
int binary_search(int arr[],int len,int e){
int left=0;
int right=len;
int mid;
while(left<=right){
int mid=(left+right)/2;
if(arr[mid]>e){
right=mid-1;
}
else if(arr[mid]<e){
left=mid+1;
}
else{
return mid;
}
}
return -1;
}
int main(){
int arr[100];
int n;
cin>>n;
for(int i=0;i<n;i++)cin>>arr[i];
int e;
cin>>e;
cout<<binary_search(arr,n-1,e)+1;
return 0;
}
一维前缀和数组:
前缀和可以简单理解为数列的前 𝑛 项的和,是一种重要的预处理方式,能大大降低查询的时间复杂度。
代码:
#include <iostream>
using namespace std;
int get_sum(int* sum, int L, int R) {
if (L <= 0) return sum[R];
return sum[R] - sum[L - 1];
}
int main() {
int n, q;
cin >> n >> q;
int* a = new int[n];
for (int i = 0; i < n; i++) {
cin >> a[i];
}
// 构建前缀和数组
int* sum = new int [n];
sum[0] = a[0];
for (int i = 1; i < n; i++) {
sum[i] = sum[i - 1] + a[i];
}
for (int i = 0; i < n; i++) {
cout << sum[i] << " ";
}
cout << endl;
// 查询 L - R 区间和
while (q--) {
cout << "\n请输入查询的 L 和 R" << endl;
int L;
int R;
cin >> L >> R;
cout << get_sum(sum, L, R);
}
return 0;
}
(大神的代码,非本人)
一维差分:
差分是一种和前缀和相对的策略,可以当做是求和的逆运算。
代码:
#include <iostream>
using namespace std;
void mode(int* d, int L, int R, int e) {
d[L] += e;
d[R + 1] -= e;
}
int main() {
int n, m;
cin >> n >> m;
int* a = new int[n+1];
for (int i = 0; i < n; i++) {
cin >> a[i];
}
int* d = new int[n+1];
// 构建差分数列
// 在差分序列上进行操作
// 求操作后差分序列的前缀和
for (int i = 0; i < n; i++) {
d[i] = 0;
}
while (m--) {
cout << "操作的 L 和 R 以及 数" << endl;
int L;
int R;
int e;
cin >> L >> R >> e;
mode(d, L, R, e);
}
// 构建前缀和数组
int* sum = new int[n + 1];
sum[0] = d[0];
for (int i = 1; i < n; i++) {
sum[i] = sum[i - 1] + d[i];
}
for (int i = 0; i < n; i++) {
a[i] += sum[i];
cout << a[i] << " ";
}
return 0;
}
(大神的代码,非本人)