各种排序算法-上

tips:

gif动图blog

冒泡排序

选择排序

插入排序

归并排序

 

//#include <bits/stdc++.h> //编译速度慢

#include <iostream>
#include <algorithm>
#include <vector>

using namespace std;

//思考题: 给定一个序列,求如果用冒泡排序,需要交换多少次? 等价于求这个序列逆序对的个数

void bubble_sort(vector<int> &q)
{
    for(int i = q.size()-1; i > 0; i--){// 从小到大排,后面是有序的,就可以不用考虑了,所以倒着写方便;外层循环控制边界
         bool flag = false; // 加优化, 记录有无进行交换操作
         for(int j = 0; j+1 <= i; j++)// 用最靠近末端(边界)的下标去接近边界
            if(q[j] > q[j+1]){
                swap(q[j],q[j+1]);
                flag = true ;
            }
         if(!flag) break; //这个优化很重要
    }

}

void select_sort(vector<int> &q)
{
    for(int i = 0; i < q.size(); i++){
        int minIndex=i;
        for(int j = i + 1; j < q.size(); j ++)
        if(q[j] < q[minIndex]){
            minIndex = j;
        }
        int tmp = q[i];
        q[i] = q[minIndex];
        q[minIndex] = tmp;

    }
}

void insert_sort(vector<int> &q){
    for(int i = 1; i < q.size(); i++ ){ //第一个元素相当于排好序了,从1开始
        int t = q[i], j;
        for(j = i - 1; j >= 0; j--){
            if(q[j] > t){ //注意这里是t,在动态过程中,考虑在中间操作过程中是否会被修改
                q[j+1] =q[j];
            }
            else break;
        }
        q[j+1] = t;
    }
}

//更多地使用归并排序的思路解决其他问题,比如求逆序对 T:O(nlogn)
void merge_sort(vector<int> &q, int l, int r){
    if(l >= r) return;

    int mid = (l + r)/2;
    merge_sort(q, l, mid);
    merge_sort(q, mid+1, r);

    static vector<int> w;//等价于全局变量,开一个静态的空间,辅助数组
    w.clear();

    //合并两个有序序列
    int i = l,j = mid + 1;//定义两个指针,从两个序列的开始指
    while(i <= mid && j <= r){
        if(q[i] <= q[j])
            w.push_back(q[i ++]);
        else
            w.push_back(q[j ++]);

    }

    while(i <= mid) w.push_back(q[i ++]);
    while(j <= r) w.push_back(q[j ++]);

    //把有序数组放回去
    for(int i = l,j = 0; j < w.size(); i ++,j ++ ) q[i] = w[j];//推荐写两个变量,好debug
    //写代码要考虑思路的清晰性

}

//把问题分解,递归定义一个流程
//设计模式,处理流程的思考
//看问题的角度,如何把问题从组合计数的角度进行划分:比如求逆序对,左区间的逆序对(往下层递归解决),右区间的逆序对,左右区间的逆序对
//在该层是一个区间,到下一层时就不是一个区间了

int merge_nixu(vector<int> &q, int l, int r){
    if(l >= r) return 0;

    int res = 0;
    int mid = (l + r) /2;

    res += merge_nixu(q, l, mid);//这个区间的逆序对在下一层被解决
    res += merge_nixu(q, mid+1, r);

    static vector<int> w;
    w.clear();

    //关键操作,从底层往上传结果
    int i = l, j = mid+1;
    while(i <= mid && j <= r){
        if(q[i] <= q[j]){
            w.push_back(q[i ++]);
        }
        else{
            res += (mid - i + 1);
            w.push_back(q[j ++]);

        }
    }

    while(i <= mid ) w.push_back(q[i ++]);
    while(j <= r) w.push_back(q[j ++]);

    for(int i = l, j = 0; j < w.size(); i ++, j ++) q[i] =w[j];

    return res;

}

int main()
{
   int n;
   vector<int> q;

   cin >> n;
   for(int i = 0,t; i < n; i ++ ) {
    cin >> t;
    q.push_back(t);
   }

   //bubble_sort(q);
   //select_sort(q);、
   //insert_sort(q);
   //merge_sort(q, 0, q.size() - 1);
   cout<<merge_nixu(q, 0, q.size()-1)<<endl;

   for(auto x : q) cout << x << ' ';
   cout << endl;

   return 0;
}
View Code

 

 

 

//#include <bits/stdc++.h> //编译速度慢

#include <iostream>
#include <algorithm>
#include <vector>

using namespace std;

//思考题: 给定一个序列,求如果用冒泡排序,需要交换多少次

void bubble_sort(vector<int> &q)
{
    for(int i = q.size()-1; i > 0; i--){// 从小到大排,后面是有序的,就可以不用考虑了,所以倒着写方便;外层循环控制边界
         bool flag = false; // 加优化, 记录有无进行交换操作
         for(int j = 0; j+1 <= i; j++)// 用最靠近末端(边界)的下标去接近边界
            if(q[j] > q[j+1]){
                swap(q[j],q[j+1]);
                flag = true ;
            }
         if(!flag) break; //这个优化很重要
    }

}

void select_sort(vector<int> &q)
{
    for(int i = 0; i < q.size(); i++){
        int minIndex=i;
        for(int j = i + 1; j < q.size(); j ++)
        if(q[j] < q[minIndex]){
            minIndex = j;
        }
        int tmp = q[i];
        q[i] = q[minIndex];
        q[minIndex] = tmp;

    }
}

void insert_sort(vector<int> &q){
    for(int i = 1; i < q.size(); i++ ){ //第一个元素相当于排好序了,从1开始
        int t = q[i], j;
        for(j = i - 1; j >= 0; j--){
            if(q[j] > t){ //注意这里是t,在动态过程中,考虑在中间操作过程中是否会被修改
                q[j+1] =q[j];
            }
            else break;
        }
        q[j+1] = t;
    }
}

//更多地使用归并排序的思路解决其他问题,比如求逆序对 T:O(nlogn)
void merge_sort(vector<int> &q, int l, int r){
    if(l >= r) return;

    int mid = (l + r)/2;
    merge_sort(q, l, mid);
    merge_sort(q, mid+1, r);

    static vector<int> w;//等价于全局变量,开一个静态的空间,辅助数组
    w.clear();

    //合并两个有序序列
    int i = l,j = mid + 1;//定义两个指针,从两个序列的开始指
    while(i <= mid && j <= r){
        if(q[i] <= q[j])
            w.push_back(q[i ++]);
        else
            w.push_back(q[j ++]);

    }

    while(i <= mid) w.push_back(q[i ++]);
    while(j <= r) w.push_back(q[j ++]);

    //把有序数组放回去
    for(int i = l,j = 0; j < w.size(); i ++,j ++ ) q[i] = w[j];//推荐写两个变量,好debug
    //写代码要考虑思路的清晰性

}

int main()
{
   int n;
   vector<int> q;

   cin >> n;
   for(int i = 0,t; i < n; i ++ ) {
    cin >> t;
    q.push_back(t);
   }

   //bubble_sort(q);
   //select_sort(q);、
   //insert_sort(q);
   merge_sort(q, 0, q.size() - 1);

   for(auto x : q) cout << x << ' ';
   cout << endl;

   return 0;
}
View Code

 

posted @ 2019-05-20 23:18  SUMay  阅读(150)  评论(0)    收藏  举报