0x00排序专题

0x00-排序专题

冒泡排序

参考:https://zhuanlan.zhihu.com/p/126354159

冒泡排序(Bubble Sort) 最为简单的一种排序,通过重复走完数组的所有元素,通过打擂台的方式两个两个比较,直到没有数可以交换的时候结束这个数,再到下个数,直到整个数组排好顺序。因一个个浮出所以叫冒泡排序。双重循环时间 O(n^2)

算法描述:

  • 比较相邻两个数据如果。第一个比第二个大,就交换两个数

  • 对每一个相邻的数做同样1的工作,这样从开始一队到结尾一队在最后的数就是最大的数。

  • 针对所有元素上面的操作,除了最后一个。

  • 重复1~3步骤,知道顺序完成。

代码

//
// Created by majoe on 2020/8/19.
//

/**
 * 输入:
 * 5
 * 2 3 4 5 1
 */

#include <bits/stdc++.h>
using namespace std;
const int N = 1e5+10;
int n;
int a[N];
//打印数组
void print(int *a, int len){
    for (int i = 0; i < len; ++i) {
        cout << a[i] << " ";
    }
    cout << endl;
}

/**
 * 冒泡排序
 * @param a 排序数组
 * @param len 数组长度
 */
void bubbleSort(int *a,int len){
    //经过len-1轮
    for (int i = 0; i < len-1 ; ++i) {
        //flag是否发生过交换
        bool flag = false;
        for (int j = 0; j < len-i-1 ; ++j) {
            if(a[j] > a[j+1]) {
                swap(a[j],a[j+1]);
                flag = true;
            }
        }
        //没有交换过,说明已经有序直接跳出
        if(!flag) return;
    }
}

int main(){
    cin >> n;
    for (int i = 0; i < n; ++i) {
        cin >> a[i];
    }
    bubbleSort(a,n);
    print(a,n);
    return 0;
}

选择排序

选择排序(Select Sort) 是直观的排序,通过确定一个 Key 最大或最小值,再从带排序的的数中找出最大或最小的交换到对应位置。再选择次之。双重循环时间复杂度为 O(n^2)
算法描述:

  • 在一个长度为 N 的无序数组中,第一次遍历 n-1 个数找到最小的和第一个数交换。
  • 第二次从下一个数开始遍历 n-2 个数,找到最小的数和第二个数交换。
  • 重复以上操作直到第 n-1 次遍历最小的数和第 n-1 个数交换,排序完成。

代码:

//
// Created by majoe on 2020/8/19.
//

/**
 * 输入:
 * 5
 * 2 3 4 5 1
 */

#include <bits/stdc++.h>
using namespace std;
const int N = 1e5+10;
int n;
int a[N];

//打印数组
void print(int *a, int len){
    for (int i = 0; i < len; ++i) {
        cout << a[i] << " ";
    }
    cout << endl;
}

/**
 * 选择排序
 * @param a
 * @param len
 */
void selectSort(int *a, int len){
    int min;
    //选择未排序数组最小的元素的下标,和未排序数组第一个元素交换
    for (int i = 0; i < len-1; ++i) {
        min = i;
        for (int j = i+1; j < len ; ++j) {
            //打擂台,找到最小值的下标
            if(a[min] > a[j]) min = j;
        }
        swap(a[i],a[min]);
    }
}

int main(){
    cin >> n;
    for (int i = 0; i < n; ++i) {
        cin >> a[i];
    }
    selectSort(a,n);
    print(a,n);
    return 0;
}

快速排序

参考:https://www.zhihu.com/search?type=content&q=%E9%80%89%E6%8B%A9%E6%8E%92%E5%BA%8F

快速排序(QuickSort)是排除稳定性因素后最常用的排序。给看官介绍两种使用方法,一种值直接在我文件 stdlib.h 头文件中的 qsort 函数实现是和正常写代码一样的。通过使用qsort(数组名,长度,sizeof(第一个数长度),compInc/comoDec) 进行实现数组的排序。后面的是通过递归调用的形式。
算法描述:

  • 从数列中挑出一个元素作为基准。
  • 重新排列数列,把所有的比基准小的放在基准前面,反之放在后面(一样大可任意一边)完成后基准处在分区的中间位置。
  • 通过递归调用把小于基准元素和大雨基准元素的子序列进行排序。
//
// Created by majoe on 2020/8/19.
//
/**
 * 输入:
 * 5
 * 2 3 4 5 1
 */
#include <bits/stdc++.h>
using namespace std;
const int N = 1000001;
int n;
int a[N];

void print(){
    for (int i = 0; i < n; ++i) {
        cout << a[i] << " ";
    }
}
/**
 * 快速排序
 * @param st  左端点
 * @param ed  右端点
 */
void qsort(int st, int ed){
    if(st >= ed) return;
    int mid  = (st+ed)/2;
    //swap(a[st],a[mid]);
    int l = st,r= ed;
    //基准值
    int temp = a[l];
    while (l < r){
        while(l < r && temp <= a[r]   ) r --;
        a[l] = a[r];
        while(l < r && temp >= a[l]  ) l ++;
        a[r] = a[l];
    }
    a[l] = temp;
    qsort(st,l-1);
    qsort(l+1,ed);
}

 

int main(){
    cin >> n;
    for (int i = 0; i < n; ++i) {
        cin >> a[i];
    }
    qsort(0,n-1);
    print();
    return 0;
}

归并排序

归并排序,是创建在归并操作上的一种有效的排序算法。算法是采用分治法(Divide and Conquer)的一个非常典型的应用,且各层分治递归可以同时进行。归并排序思路简单,速度仅次于快速排序,为稳定排序算法,一般用于对总体无序,但是各子项相对有序的数列。

归并排序是用分治思想,分治模式在每一层递归上有三个步骤:

  • 分解(Divide):将n个元素分成个含n/2个元素的子序列。
  • 解决(Conquer):用合并排序法对两个子序列递归的排序。
  • 合并(Combine):合并两个已排序的子序列已得到排序结果。

//
// Created by majoe on 2020/8/19.
//

#include <bits/stdc++.h>
using namespace std;
const int N = 1e5+10;
int n;
int a[N],b[N]; //a为原数组,b为备份数组


/**
 * 归并排序
 * @param a 数组
 * @param l 左边界
 * @param r 右边界
 * @param b 额外的数组
 */
void msort(int l,int r){
    if(l == r) return; //跳出条件
    //切分操作
    int mid = (l+r)>>1, i=l,j=mid+1;
    msort(l,mid);
    msort(j,r);

    //合并操作,先放入备份数组里
    for (int k = l; k <=r ; ++k) {
        if(j>r || i<=mid && a[i]<=a[j]) b[k] = a[i++];
        else b[k] = a[j++];
    }
    for(int k=l;k<=r;k++) a[k]=b[k];
}

void print(int *a, int len){
    for (int i = 0; i < len; ++i) {
        cout << a[i] << " ";
    }
    cout << endl;
}


int main(){
    cin >> n;
    for (int i = 0; i < n; ++i) {
        cin >> a[i];
    }
    msort(0,n-1);
    print(a,n);
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值