基础篇——常见排序算法总结(一)冒泡算法

新人小白学习和总结一下常见的排序算法。

排序算法分类
按照排序过程中数据的保存形式的不同,可将排序分为内部排序外部排序两大类。
如果排序过程不需要访问外存,就称之为内部排序(外存也就是计算机配备的存储容量更大的磁盘存储器和光盘存储器)。其实,所有排序过程都是在内存里面做的,但是外部排序需要做与外界的内外存交换,也就是说,内部排序消耗的是时间复杂度,外部排序消耗的是空间复杂度。当待排序的文件很大时,计算机内存不够大,所以需要进行内外存交换。
网上盗图如下:
这里写图片描述
排序算法的稳定性
排序的过程中,会碰到如下情况,比如当排序的俩个数值相等时,比如序列{2,5,8,2,3,2},如果排序后这些元素2的相对位置不变,即对于一个已经排序好的序列{2,2,2,3,5,8},排序算法还会不会改变上述元素的相对位置,如果不改变的话,那这个算法是稳定的,否则是不稳定的。
常见排序算法如下:
这里写图片描述
稳定的排序算法有:插入排序、冒泡排序、归并排序和基数排序。
快排、希尔、选择排序和堆排序是不稳定的算法。

1.冒泡算法(所学第一个排序算法)

#include<iostream>
int main()
{
    int a[10] = { 2,12,5,6,1,2,25,11,254,12};
    int swap = 0;
    //冒泡从小到大排序
    for (int i = 0; i < 9; i++)
        for (int j = 0; j < 9 - i; j++)
        {
            if (a[j] > a[j + 1])
            {
                swap = a[j + 1];
                a[j + 1] = a[j];
                a[j] = swap;
            }
        }

    for (int i = 0; i < 10; i++)
        std::cout << a[i] << "\n";
    //冒泡从大到小排序
    for (int i = 0; i < 9; i++)
        for (int j = 0; j < 9 - i; j++)
        {
            if (a[j] < a[j + 1])
                swap = a[j];
            a[j] = a[j + 1];
            a[j + 1] = swap;
        }
    for (int i = 0; i < 10; i++)
        std::cout << a[i] << "\n";

    return 0;
    }

光看是没用的,还得自己写,光是这个排序我还出了不少错误。。。。。。
时间复杂度O(n的平方)
最大时间复杂度1+2+3+…+(n-1)(判断一次(包括判断后的执行语句)算一次运算)
所以:最坏时间复杂度为O(n^2)
然而,根据资料显示,冒泡算法的最好时间复杂度为O(n),但是正序情况下难道不是也要比较O(n^2)次么,按照上述的我写的冒泡算法确实不是O(n),但是可以做一个小改进,就是如何在所有的排序顺序都对的时候,返回一个值,终止循环?

int main(){
int a[10] = { 2,12,5,6,1,2,25,11,254,12 };
    int swap = 0;
    bool choice=true;
    //改进冒泡算法
    for (int i = 0; i < 9; i++)
    {   for (int j = 0; j < 9 - i; j++)

            choice = true;
            if (a[j] > a[j + 1])
            {
                swap = a[j + 1];
                a[j + 1] = a[j];
                a[j] = swap;
                choice = false;
            }
            //如果经过一次冒泡过程,没发生交换
            if (choice == true)
                return  0;

        }

1.2定向冒泡算法
为了改进冒泡算法,提出了定向冒泡算法(鸡尾酒排序)
为什么叫鸡尾酒排序呢,因为这种改进算法是气泡从左到右,得到序列尾部的最大值后,又从右到左,可以得出头部的最小值。鸡尾酒是需要不断翻转的,这种比喻很生动。

int main(){
int a[10] = { 2,12,5,6,1,2,25,11,254,12 };

    //如果是10个数 则最多4个来回确定4个最小的和4个最大的数 ,然后再进行一次比较
    //如果按n分成奇数偶数感觉好麻烦 就做2*int((n+1)/2)次循环比较

    int swap = 0;
    for (int j = 0; j < 10 - 1; j++)
    {
        if(j % 2 == 0 && j < (10 - 1))          //i为偶数 从左到右排序
            for (int i = 0; i < 9 - j; i++)
            {
                if (a[i] > a[i + 1])
                {
                    swap = a[i];
                    a[i] = a[i + 1];
                    a[i + 1] = swap;
                }
            }

        if( j % 2 == 1 && j < 9)        //i为奇数,从右往左排序
            for (int i = 9 - j; i > 0; i--)

            {
                if (a[i] < a[i - 1])
                {
                    swap = a[i];
                    a[i] = a[i - 1];
                    a[i - 1] = swap;
                }
            }
    }

下面是加了标记后的鸡尾酒算法

int main()
{
    int a[10] = { 2,12,5,6,1,2,25,11,254,12 }
    //如果是10个数 则最多4个来回确定4个最小的和4个最大的数 ,然后再进行一次比较
    //如果按n分成奇数偶数感觉好麻烦 就做2*int((n+1)/2)次循环比较
    bool choice = false;
    int swap = 0;
    for (int j = 0; j < 10 - 1; j++)
    {
        choice = true;
        if(j % 2 == 0 && j < (10 - 1))          //i为偶数 从左到右排序
            for (int i = 0; i < 9 - j; i++)
            {
                if (a[i] > a[i + 1])
                {
                    swap = a[i];
                    a[i] = a[i + 1];
                    a[i + 1] = swap;
                    choice = false;
                }
            }

        if( j % 2 == 1 && j < 9)        //i为奇数,从右往左排序
            for (int i = 9 - j; i > 0; i--)

            {
                if (a[i] < a[i - 1])
                {
                    swap = a[i];
                    a[i] = a[i - 1];
                    a[i - 1] = swap;
                    choice = false;
                }
            }
        if (choice == true)
            return 0;

    }
        for (int i = 0; i < 10; i++)
            std::cout << a[i] << "\n";

    return 0;

}

定向冒泡排序,能稍稍增加排序算法的性能,但总的来说效率不高。

本人水平比较差,欢迎批评指正~

posted @ 2018-04-27 21:00  弹吉他的小刘鸭  阅读(124)  评论(0编辑  收藏  举报