zoukankan      html  css  js  c++  java
  • 常见的排序算法——交换排序

    一、冒泡排序

    #include <iostream>
    using namespace std;
    
    void print_array(int a[], int n)
    {
        for(int i = 0; i < n; i++)
            cout << a[i]  << " " ;
        cout << endl;
    }
    
    
    void bubble_sort(int a[], int n)
    {    
        for(int i = 0; i < n; i++)
        {            
            for(int j = n - 1; j > i; j--)        //冒泡排序,从后面到前面两两比较,将小数慢慢放到首位置
            {
                if(a[j] < a[j-1])
                {
                    int tmp = a[j];
                    a[j] = a[j-1];
                    a[j-1] = tmp;
                }
            print_array(a, 9);
            }        
        }
    }
    
    
    int main()
    {
        int a[] = {7,3,5,8,9,1,2,4,6};
        cout << "before sort:";
        print_array(a, 9);
    
        bubble_sort(a, 9);
        cout << "after sort :";
        print_array(a, 9);
        
        return 0;
    }

    说明:

      冒泡排序是依次比较相邻两个数,将小数放在前面,大数放在后面。

      第一趟:比较第1第2两个数,小数放在前面,大数放在后面;然后比较第2第3个数,小数放在前面,大数放在后面......到最后一个数。第一趟结束,最大的数放在了最后。

      第二趟:比较第1第2两个数,小数放在前面,大数放在后面;然后比较第2第3个数,小数放在前面,大数放在后面......到倒数第二个数。第二趟结束,新的最大数放在了倒数第二。

      ......

      多次循环,完成排序。因为排序过程是小数往前放,大数往后放,相当于气泡上升,所以称为冒泡排序。

      冒泡排序是稳定的,时间复杂度O(n^2)。

    二、快速排序

    (参考资料:

    https://www.jianshu.com/p/7631d95fdb0b Python的快速排序算法,类似于左右指针法

    https://www.jianshu.com/p/1246ab5f8799 这篇比上面一篇的思想更好,不用考虑最后基准值的排列情况 

    https://blog.csdn.net/xy913741894/article/details/59110569 概括了几种不同的快速排序方法等等其他内容,左右指针法,前后指针法,挖坑法

    ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

    1.挖坑法:

    数据:

    刚开始,将最右边设置为“坑”。同时设置left指向第一个元素2,right指向最后一个元素5。

    1. 如果v[left] <= pivot,那么left指针右移直到v[left] > pivot停下,那么此时需要填坑,将v[right]也就是pivot初始坑填满,v[right] = v[left],并且此时设置v[left]为坑;
    2. 现在我们移动right,如果v[right] >=pivot,right指针左移直到v[right] < pivot停下,同理此时填坑,v[left] = v[right],并且设置v[right]为坑;
    3. 重复1,2过程直到left,right相遇,此时将v[right] = pivot填满,最后返回right。

    图示:

    void quick_sort_fill(int s[], int l, int r)
    {
        int left = l, right = r;
        int pivot = s[right];
        
             //递归的时候这个判断一定要有
        if(left < right)
        {
            while(left < right)
            {        
                while(s[left] < pivot && left < right)
                {
                    left++;
                }        
                s[right] = s[left];
            //cout << "before    :";
            //print_array(s, 10);
                while(s[right] >= pivot && left < right)
                {
                    right--;
                }        
                s[left] = s[right];    
            //cout << "sort OVER :";
            //print_array(s, 10);
    
            }
            s[left] = pivot;    
    
            quick_sort(s, l, left - 1);
            quick_sort(s, left + 1, r);
        }
    }

    2.左右指针法:

    数据:

    刚开始设置基准值pivot为最右边的元素也就是5。设置left指向第一个元素2,right指向最后一个元素5。

    1. 如果v[left] < pivot,将left指针右移,直到v[left] > pivot
    2. 如果v[right] > pivot,将left指针左移,直到v[left] < pivot
    3. 此时交换v[left]和v[right]
    4. 继续重复1,2,3的过程知道left和right相遇,此时left == right,交换v[left]和pivot的值,返回left或者right

    注:这种方法是找 left > pivot, right < pivot,然后交换left和right;

    另一种方法:找 left > pivot,交换left 和pivot;找 right < pivot,交换right 和 pivot。

    //上述的方法:交换left和right
    void
    quick_sort_leftright(int s[], int l, int r) { int left = l, right = r; int pivot = s[right]; if(left < right) { while(left < right) { while(left < right && s[left] < pivot) { left++; } while(left < right && s[right] >= pivot) { right--; } int middle = s[left]; s[left] = s[right]; s[right] = middle; } int middle2 = s[left]; s[left] = pivot; s[r] = middle2; cout << "before :"; print_array(s, 10); quick_sort_leftright(s, l, left-1); quick_sort_leftright(s, left+1, r); } }

    3.前后指针法:

    数据:

    刚开始设置cur指向第一个元素2,prev指向空。

    1. 如果v[cur] < pivot,那么让prev指针右移  =>  如果prev==cur,则 => 3;如果prev不等于cur,那么交换v[cur]和v[prev]的值 => 3
    2. 如果v[cur] >= pivot,那么 => 3
    3. cur指针右移
    4. 重复1,2的过程直到cur指针指到最右边
    5. 让prev再右移一次,最后交换pivot(也就是v[cur])和v[prev]的值,返回prev

     

    void quick_sort_frontback(int s[], int l, int r)
    {
        int prev = l - 1, cur = l;
        int pivot = s[r];
    
        if(cur < r)
        {
            while(cur < r)
            {
                if(s[cur] < pivot)
                {
                    ++prev;
                    if(prev != cur)                
                    {
                        int middle = s[cur];
                        s[cur] = s[prev];
                        s[prev] = middle;
                    }
                }
                cur++;
            }
            int middle2 = s[cur];
            s[cur] = s[++prev];
            s[prev] = middle2;
            
            quick_sort_frontback(s, l, prev-1);
            quick_sort_frontback(s, prev+1, r);
        }
    }

    说明:

      基本思想:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都小于另外一部分的所有数据,然后再递归进行排序。

      最坏时间O(n^2),平均运行时间O(nlogn)。快速排序被认为是当前最优秀的内部排序方法。

  • 相关阅读:
    3524: [Poi2014]Couriers -- 主席树
    bzoj 2190: [SDOI2008]仪仗队 -- 欧拉函数
    模板 -- 树链剖分
    bzoj 1823: [JSOI2010]满汉全席 -- 2-sat
    bzoj 1704: [Usaco2007 Mar]Face The Right Way 自动转身机 -- 贪心
    bzoj 1231: [Usaco2008 Nov]mixup2 混乱的奶牛 -- 状压DP
    redis 主从复制
    redis 事务
    redis持久化——AOF
    redis 持久化 ——RDB
  • 原文地址:https://www.cnblogs.com/Brickert/p/10758493.html
Copyright © 2011-2022 走看看