三、排序算法总结(C++版本)

一、引言

对于各种排序算法也算是有了一定的了解,所以这里做一个总结。

二、冒泡排序法。

       这是比较经典的排序算法,主要是通过内外两层的循环比较,使得乱序变为顺序。

下面是一个测试代码

#include <iostream>
#include <vector>
using namespace std;
int main()
{
    vector<int> L(10);
    for(int i=0;i<L.size();i++)
    {
        L[i] = 10 - i;
    }
    int temp = 0;
    for (int i = 0; i < L.size(); i++)
        for (int j = L.size()-1; j >= (i+1); j--)
        {
            if (L[j-1] > L[j ])
            {
                temp = L[j];
                L[j] = L[j - 1];
                L[j - 1] = temp;
            }
        }
    for (int j = 0; j < L.size(); j++)
    {
        cout << "the number is " << L[j] << endl;
    }
}

初始化为10-1,最后冒泡排序法的的结果为升序排列。

下面是算法的运行过程。

在第一次循环里面(即i=0的时候):

每一次比较之后数据变化如下:

三、排序算法总结(C++版本)

 随着 i 的增大,蓝色区域扩展如下:

三、排序算法总结(C++版本)

   最后达到有序状态。

从上面的分析可以看出来:

其时间复杂度:O(n 2) (这里的时间,主要花费在了比较运算上面,所以计算的是循环里面的比较次数)

空间复杂度: O(n)  (即所有的变量占用的空间)

算法稳定性上来说,属于稳定算法(即两个相同的元素经过排序之后的 先后顺序不变)。

二直接插入排序

插入排序的算法思想是,将待排序的数据看做两个部分,一部分是有序数据A,一部分是无序数据B, 最开始的时候A的规模是0, B是整个的待排序数据。

之后对于B中的每一个数据,按照顺序插入到A中,直至整个过程完成。

例如,对于一个待排序数组来说,过程如下:

#include <iostream>
using namespace std;
void Sorted(int* x, int length);
int main(void)
{
    int a[5]={2,1,3,6,4};
    Sorted(a,5);
    for(int i=0;i<5;i++)
        cout<<"-----------"<<a[i]<<endl;
    return 0;
}

void Sorted(int* x, int length)
{
    for(int i=1; i<length;i++ )
    {
        int temp=x[i];
        int j=i-1;
        while( j>=0 && temp<x[j])
        {
            x[j+1]=x[j];
            x[j]=temp;
            j--;
        }
     } 
}

在上面的例子里面:

1 a[5]={2,1,3,6,4};

在每一步的运算过程中,其数据的变化如下:

三、排序算法总结(C++版本) 三、排序算法总结(C++版本)  三、排序算法总结(C++版本)

 三、排序算法总结(C++版本)三、排序算法总结(C++版本)

上述描述了比较的过程。

柱状图表表示了每一个位置的数字大小,蓝色区域为无序部分,黄色部分为经过一次运算之后的有序部分。

其主要步骤是,选择无序部分的第一个元素,将其插入到黄色的有序部分里面去,这样黄色区域扩展,而蓝色区域则是不断地减小,直至所有的区域变为有序状态。

复杂度分析:

  可以看到,上述过程,主要操作是比较操作,然后是赋值操作,其中赋值操作的所花费的时间更长

  在最好的情况下,整个数据正好是升序排列的,这个时候比较操作是(n-1),赋值操作 复杂度为0

  在最坏的情况下,整个数据是降序排列的,这个时候比较次数是  n*(n-1)/2 次,赋值操作是4*n*(n-1)/2, 主要的时间花在了赋值的操作上,时间复杂度为O(n2)

  稳定性来说,这个算法是不稳定的,即相同的两个元素,在排序前和排序之后,先后次序可能发生了改变。

三、选择排序

  选择排序的思想与上面的插入排序相同,将数据分为有序部分和无序部分。

  在无序部分里面选择出最值(比如说是最大值,放到有序部分),这样经过不断的选择无序部分的最大值,使得有序部分不断的扩展,无序部分不断地缩小,最后得到整个有序数据序列。

  具体代码如下:

#include <iostream>
using namespace std;
void Sorted(int* x, int length);
int main(void)
{
    int a[5] = { 4,1,3,2,6};
    Sorted(a, 5);
    for (int i = 0; i < 5; i++)
        cout << "-----------" << a[i] << endl;
    return 0;
}

void Sorted(int* x, int length)
{
    int max = 0;
    int len = length - 1;
    
    for (int i = 0; i <= length-1; i=i+1)
    {
        max = x[0];
        int j = 0;
        int number = 0;
        for (j = 1; j <= len; j++)
        {
            if (max < x[j])
            {
                max = x[j];
                number = j;
            }
        }
        int temp = x[len];
        x[len] = max;
        x[number] = temp;
        len--;
    }
}

其每一次的比较过程如下:

三、排序算法总结(C++版本) 三、排序算法总结(C++版本)三、排序算法总结(C++版本)

三、排序算法总结(C++版本)三、排序算法总结(C++版本)三、排序算法总结(C++版本)

如图可以看到,有序的黄色区域在不断的扩展,无序部分在逐渐减少。

复杂度:

最好情况:全是升序排列,这个时候只需要(n-1)次比较

最坏情况:全是降序排列,这个时候需要(n-1)*n/2次比较,(n-1)次互换操作,时间复杂度在O(n) (这里只是考虑了互换操作), 比冒泡排序法快

  稳定性:不稳定

相关推荐