AcWing
  • 首页
  • 活动
  • 题库
  • 竞赛
  • 应用
  • 更多
    • 题解
    • 分享
    • 问答
  • App
    New
  • 登录/注册

学习笔记-排序

作者: 作者的头像   未名湖畔的梦 ,  2023-09-26 11:00:24 ,  所有人可见 ,  阅读 85


1


1

$$排序算法$$

排序算法(英语:Sorting algorithm)是一种将一组特定的数据按某种顺序进行排列的算法.

一.快速排序:

时间复杂度为$O(logn)$

快速排序主要思想:

1.确定分界点:一般是 q[l], q[(l + r ) >> 1], q[r]
2.调整区间:对于原来某个数 falg, 使得小于等于 x 的数都在左边, 大于等于 x 的数都在右边
3.递归处理左右两端

代码实现:

const int N = 1e6 + 2;
int n, q[N];

// 快速排序 暴力做法(将小于等于x和大于等于falg的数分放到新数组左右两边中)
int a[N];
void quick_sort_1(int q[], int l, int r){
    if(l >= r) return ;

    int falg = q[l + r >> 1], x = l, y = r;

    for(int i = l; i <= r; i++){
        if(q[i] < falg) a[x ++] = q[i];
        if(q[i] > falg) a[y --] = q[i];
    }

    //现在 a[l, x - 1]都是比 falg 小, a[y + 1, r] 都比 falg 大
    for(int i = l; i < x; i ++) q[i] = a[i];
    for(int i = r; i > y; i --) q[i] = a[i];
    for(int i = x; i <= y; i ++) q[i] = falg;

    //[p,q]是falg不用再排序了
    quick_sort_1(q, l, x - 1);
    quick_sort_1(q, y + 1, r);
}

// 快速排序 优化做法(利用指针i,j使得 i 左边的数字小于等于falg, j 右边的数字大于等于falg)
void quick_sort_2(int q[], int l, int r){
    if(l >= r) return ;

    int falg = q[l + r >> 1], i = l, j = r;
    while(i <= j){
        while(q[i] < falg) i ++; // 一直找到 q[i] >= falg
        while(q[j] > falg) j --; // 一直找到 q[i] <= falg
        if(i <= j)  swap(q[i ++], q[j --]); // 交换完后记得把指针移动
    }

    quick_sort_2(q, l, j);
    quick_sort_2(q, i, r);
} 

二.归并排序:

时间复杂度为$O(logn)$

归并排序主要思想(分治):

1.确定分界点
2.递归排序l, r
3.归并,合二为一

代码实现:


int 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];
}

三.其他排序:

(1).选择排序

时间复杂度为$O(n ^ 2)$

// 选择排序:每次将序列最小值放到序列最前面
void selection_sort(int a[], int n){
    for(int i = 0; i < n; i++){
        int k = i;
        for(int j = i + 1; j < n; j++)
            if(a[j] < a[k])
                k = j;
        swap(a[i], a[k]);
    }
}

(2).冒泡排序

时间复杂度为$O(n ^ 2)$


// 冒泡排序:每次将序列最大值放到最后面
void bubble_sort(int a[], int n){
    for(int i = n - 1; i > 0; i --){
        int k = i;
        for(int j = 0; j <= i; j ++)
            if(a[j] > a[k]) 
                k = j;
        swap(a[i], a[k]);
    }
}

(3).插入排序

时间复杂度最优$o(n)$,最坏$o(n^2)$

// 插入排序:像打牌一样,每次把一个新的数放到已排好序的数组种
void insertion_sort(int a[], int n){
    for(int i = 2; i < n; i++){
        int k = a[i];
        int j = i - 1;
        while(j >= 0 && a[j] > k){
            a[j + 1] = a[j];
            j --;
        }
        a[j + 1] = k;
    }
}

(4).桶排序

时间复杂度$o(n)$,但是一般内存占用较大

// 桶排序适用于没有负数下标并且最大数不会超过数组大小的情况。
void Bucket_sort(int a[], int n){
    int vis[N];

    for(int i = 0; i < n; i++)
        vis[a[i]] ++;

    for(int i = 0; i < N; i ++)
        while(vis[i]){
            cout << i << ' ';
            vis[i] -- ;
        }
}

1 评论


用户头像
未名湖畔的梦   2个月前         踩      回复

收录至此


你确定删除吗?

© 2018-2023 AcWing 版权所有  |  京ICP备2021015969号-2
用户协议  |  隐私政策  |  常见问题  |  联系我们
AcWing
请输入登录信息
更多登录方式: 微信图标 qq图标 qq图标
请输入绑定的邮箱地址
请输入注册信息