梳排序 C++版

一、梳排序

1、梳排序

在冒泡排序的基础上先根据元素之间的步长(或者称间隔)对数据做一些预处理,在正式排序之前把较大的一些数据移到数组的底部,在每次移动中步长越来越小直到步长等于1为止,然后再使用冒泡排序。大量试验表明步长因子选择1.3最合适,这种处理后性能上和快速排序不相上下。

2、优缺点

优点:速度比冒泡快很多和快速排序并肩
缺点:1、多了预处理过程 2、算法逻辑复杂度比冒泡高
时间复杂度:最坏的情况下为O(n^2) 空间复杂度:O(n)+辅助变量所占空间

二、测试代码

#include <iostream>
#include <vector>

using namespace std;

/***********************
梳排序:在冒泡排序的基础上先根据元素之间的步长(或者称间隔)对数据做一些预处理,
在正式排序之前把较大的一些数据移到数组的底部,在每次移动中步长越
来越小直到步长等于1为止,然后再使用冒泡排序。大量试验表明步长因子
选择1.3最合适,这种处理后性能上和快速排序不相上下。
优点:速度比冒泡快很多和快速排序并肩
缺点:1、多了预处理过程 2、算法逻辑复杂度比冒泡高
时间复杂度:最坏的情况下为O(n^2) 空间复杂度:O(n)+辅助变量所占空间
************************/
template<typename T>
void swapData(T &data1,T &data2)
{
    T temp = data1;
    data1 = data2;
    data2 = temp;
}

// 实现方法一
template<typename T>
void combSort1(T data[],int n)
{
    int step = n,j,k;
    while(step>1)
    {
        for(j=n-1; j>=step; j--)
        {
            k = j-step;
            if(data[j] < data[k])
            {
                swapData(data[j],data[k]);
            }
        }
        // 重置步长,当step!>1时结束预处理数据阶段
        step = int(step/1.3);
    }

    // 冒泡排序
    bool flag = true;
    for(int i=0; i<n-1&&flag; i++)
    {
        for(j=n-1,flag=false; j>i; --j)
        {
            if(data[j]<data[j-1])
            {
                swapData(data[j],data[j-1]);
                flag = true;
            }
        }
    }
}

// 实现方法二
template<typename T>
void combSort2(vector<T> &data)
{
    int step = data.size(),j,k;
    while(step>1)
    {
        for(j=data.size()-1; j>=step; j--)
        {
            k = j-step;
            if(data[j]<data[k])
            {
                swapData(data[j],data[k]);
            }
        }
        // 重置步长,当step!>1时结束预处理数据阶段
        step = int(step/1.3);
    }

    // 冒泡排序
    bool flag = true;
    for(int i=0; i<data.size()-1&&flag; i++)
    {
        for(j=data.size()-1,flag=false; j>i; j--)
        {
            if(data[j]<data[j-1])
            {
                swapData(data[j],data[j-1]);
                flag = true;
            }
        }
    }
}

// 实现方法三,此方法实际上是方法二中增加一些打印信息以方便理解程序的执行过程
template<typename T>
void combSort3(vector<T> &data)
{
    int step = data.size(),j,k;

    cout << "交换前的元素排序:";
    for(auto iter : data)
    {
        cout << iter;
    }
    cout << endl;

    while(step>1)
    {
        bool isSwap = false; // 仅用于测试代码使用的标志

        for(j=data.size()-1; j>=step; j--)
        {
            k = j-step;
            if(data[j]<data[k])
            {
                cout << "发生交换的两个元素:" << data[j] << "&" << data[k] << endl;
                swapData(data[j],data[k]);
                isSwap = true;
            }
        }

        if(isSwap)
        {
            cout << "交换后的元素排序:";
            for(auto iter : data)
            {
                cout << iter;
            }
            cout << endl;
        }

        // 重置步长,当step!>1时结束预处理数据阶段
        step = int(step/1.3);
        cout << "步长是:" << step << endl;
    }

    // 冒泡排序
    bool flag = true;
    for(int i=0; i<data.size()-1&&flag; i++)
    {
        for(j=data.size()-1,flag=false; j>i; j--)
        {
            if(data[j]<data[j-1])
            {
                swapData(data[j],data[j-1]);
                flag = true;
            }
        }
    }
}

int main()
{
    int tempArr[] = {0,4,3,5,6,7,9,8,2,1};
    int arrSize = sizeof(tempArr)/sizeof(tempArr[0]);
    cout << "arrSize=" << arrSize << endl;
    //combSort1(tempArr,arrSize);
    vector<int> tempVec(tempArr,tempArr+arrSize);
    //combSort2(tempVec);
    combSort3(tempVec);
    cout << "================排序前tempArr===============" << endl;
    for(int i=0; i<arrSize; i++)
    {
        cout << tempArr[i];
    }
    cout << "\n================排序完成tempVec===============" << endl;
    for(auto iter:tempVec)
    {
        cout << iter;
    }
    cout << "\nHello World!" << endl;
    return 0;
}

三、测试结果

在这里插入图片描述

posted @ 2018-11-04 16:37  ISmileLi  阅读(44)  评论(0)    收藏  举报