2021年05月13日 23:45 __ _ _ _ _

你需要知道,人的事业就如同浪潮,如果你踩到浪头,功名随之而来;而一旦错失,则终其一生都将受困于浅滩与悲哀。

——《洛克菲勒写给儿子的38封信》

大家好哇,这里是小编记录算法模板的宝地啦,其中也会包含小编平时学习的一些心得。现在,让我们一起进入算法的世界吧~

1.快速排序

快速排序 是在冒泡排序基础上的改进,其基本思想是 基于分治
在写代码之前最好是找到自己要写代码的大致步骤:

  1. 找分界点:可以是数据的两端或中间,当然随机值也可。

  2. 调整区间:使得一个区间的数据小于一个值,另一个区间的值大于一个值。

  3. 递归处理:分别对两个区间进行递归处理。

To:在找分界点时,当数据加强后最好是不要选择两边端点的值,之前小编便遇到过内存过载的ERROR。
按照教材上说的,我们在进行快排时会使用两个数组,用于存放两个区间的值,存放之前还会对之前的数据进行扫描,对于时间复杂度和空间复杂度都是不小的开销。

y总提供了一种优美的解决方案,即 用两个指针分别指向数据集的两端i、j,再取其分界点x。
大致思路
是i和j分别向中间走,其中当i大于x时便停下来,j小于x时也是【假设从小到大排序】。然后当i和j两个指针都停下来,便交换两边的值。最后当两个指针相遇时,便确保了一个区间的值是小于x的,另一个区间的值大于x的。
快速排序例子: 输入格式输入共两行,第一行包含整数 n。 第二行包含 n 个整数(所有整数均在 1∼10的9次方范围内),表示整个数列。** 输出格式
输出共一行,包含 n个整数,表示排好序的数列。 数据范围 1≤n≤100000 输入样例: 5 3 1 2 4 5 输出样例: 1 2 3 4 5 源代码: **


#include <iostream>
const int N=1e6+10;int a[N];
void Sorttest(int l,int r){     if(l>=r){         return ;     }     //判断数据集     int i=l-1,j=r+1;     int x=a[(l+r)/2];     //取中间值     while(i<j){         do i++;while(a[i]<x);         do j--; while(a[j]>x);         if(i<j){             std::swap(a[i],a[j]);             //交换数据         }     }         Sorttest(l,j);Sorttest(j+1,r);         //分别处理两个区间的数据}int main(){using namespace std;    int n,i;    cin>>n;    //输入排序数据集    for(i=0;i<n;i++){        scanf("%d",&a[i]);    }//Sorttest函数进行排序    Sorttest(0,n-1);//使用循环输出排序后的数据    for(i=0;i<n;i++){        printf("%d ",a[i]);    }return 0;}

快速排序模板:


void Sorttest(int l,int r){     if(l>=r){         return ;     }     int i=l-1,j=r+1;     int x=a[(l+r)/2];     while(i<j){         do i++;while(a[i]<x);         do j--; while(a[j]>x);         if(i<j){             std::swap(a[i],a[j]);         }     }         Sorttest(l,j);Sorttest(j+1,r);}

To:可能会有人问为啥会有模板,在处理大部分排序时,模板都能起到很大的作用,平时可以多敲敲模板,关于临界值的处理则需要自己去记忆了。

2.归并排序

归并排序是一种稳定的排序,而快速排序则是一种不稳定的,归并排序也基于分治。

To:原序列中2个数相同,位置不发生变化我们便说这个排序是稳定的;反之则是不稳定的。

大致思路步骤为:

  1. 确定分界点,即mid=(l+r)/2。

  2. 递归排序左边和右边。

  3. 归并:合二为一,将排序后的数据合并,也是归并排序中最重要的一个环节。

在归并排序中,我们也用到 两个指针
,分别指向排好序数据的最左端,并开始比较,值小的就拿出来【以从小到大排序】放入另一个数组中,依次比较,如果遇到相等的数,我们倾向于将第一个序列的值先放入另一个数组中;如果当第一个指针指向序列的最后一个值时,我们便把另一个序列直接补到数组后面。

归并排序例子:
输入格式输入共两行,第一行包含整数 n。 第二行包含 n 个整数(所有整数均在 1∼10的9次方范围内),表示整个数列。** 输出格式
输出共一行,包含 n个整数,表示排好序的数列。 数据范围 1≤n≤100000 输入样例: 5 3 1 2 4 5 输出样例: 1 2 3 4 5 源代码: **


#include<iostream>using namespace std;
const int N = 1000010;int a[N], temp[N], n;
void Sorttest(int a[], int l, int r) {    if (l >= r) {        return;    }//判断数据集    int mid = l + r >> 1;//取中间值    Sorttest(a, l, mid);    Sorttest(a, mid + 1, r);//递归左右两边    int k = 0, i = l, j = mid + 1;    while (i <= mid && j <= r)        if (a[i] <= a[j]) {            temp[k++] = a[i++];        } else {            temp[k++] = a[j++];        }//排序:比较大小,将较小的数据放入temp数组中    while (i <= mid) temp[k++] = a[i++];    while (j <= r) temp[k++] = a[j++];//判断某一个序列是否未放入temp数组中,并将其放入    for (i = l, j = 0; i <= r; i++, j++) {        a[i] = temp[j];    }}
int main() {    scanf("%d", &n);    for (int i = 0; i < n; i++) {        scanf("%d", &a[i]);    }
    Sorttest(a, 0, n - 1);
    for (int i = 0; i < n; i++) {        printf("%d ", a[i]);    }    return 0;}

归并排序模板:


void Sorttest(int a[], int l, int r) {    if (l >= r) {        return;    }
    int mid = l + r >> 1;
    Sorttest(a, l, mid);    Sorttest(a, mid + 1, r);
    int k = 0, i = l, j = mid + 1;    while (i <= mid && j <= r)        if (a[i] <= a[j]) {            temp[k++] = a[i++];        } else {            temp[k++] = a[j++];        }    while (i <= mid) temp[k++] = a[i++];    while (j <= r) temp[k++] = a[j++];    for (i = l, j = 0; i <= r; i++, j++) {        a[i] = temp[j];    }}

平时也可多敲敲模板哦!

**最后的话:****刷题要找自己的不足,然后去专攻。 ** ** **

为你,千千万万遍.

往期推荐:

洛谷 || 奖学金(排序) 2021-05-08

洛谷 || 车厢重组(排序) 2021-05-06

四月碎碎念 || 给自己一个空间~ 2021-04-30

一键三连,就差你了

预览时标签不可点

阅读




__