首页 新闻 论坛 群组 Blog 文档 下载 读书 Tag 网摘 搜索 .NET Java 游戏 视频 人才 外包 培训 数据库 书店 程序员
中国软件网
欢迎您:游客 | 登录 注册 帮助
  • 构造一个体现出stl::sort不稳定性的测试用例 [已结帖,结帖人:laomai]
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • laomai
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    • 结帖率:
    发表于:2008-04-24 21:48:38 楼主
      最近在学习stl中的算法函数sort。根据我的个人理解,标准并未保证这个函数的排序一定是稳定的(stable_sort一定是稳定)。于是我写了一个程序来测试sort的稳定性。但是由于我手上目前只有vs系列的编译器,而他们对sort的内部实现是稳定的,因此没得到我想要的结果,希望大家能帮忙把我的程序在你的机器上测试一下,如果能得到最后的输出,请将测试用例或者结果及运行环境告诉我,谢谢!
        以下是我的测试程序
    /*本程序的目的是构造出一个不稳定的sort函数的输入数据*/
    #include <algorithm>
    #include <functional>
    #include <iostream>
    #include <vector>
    #include <cstdlib>
    #include <ctime>

    using namespace std;

    //
    typedef struct {
    int index;  //下标
    int value;    //值
    }Data;
    bool operator==(const Data& lhs, const Data& rhs){
    return lhs.value == rhs.value;
    }

    bool operator <(const Data& lhs, const Data& rhs){
    return lhs.value < rhs.value;
    }

    //判断数组中是否有相等值,数组应该已经排好序
    bool HasSameValue(const vector <Data>& src){
    if (adjacent_find(src.begin(), src.end()) != src.end()){
    cout < <"has same value." < <endl;
    return true;
    }
    else
    {
    cout < <"no same value." < <endl;
    return false;
    }
    }

    bool IsGreaterIndex(const Data& lhs, const Data& rhs){
    return (lhs.value == rhs.value
    && lhs.index > rhs.index);

    }

    //判断等值元素中是否有下标递减的情况,
    bool HasReverseIndex(const vector <Data>& src){
    if (adjacent_find(src.begin(), src.end(), IsGreaterIndex) != src.end()){
    cout < <"has great index." < <endl;
    return true;
    }
    else
    {
    cout < <"no great index." < <endl;
    return false;
    }
    }


    const int NUMBER = 100;
    const int SIZE=10;
    const int RANNUM = 4;
    void ResetData(vector <Data>& src){
    int i=0;
    vector <int> ran(RANNUM);
    for(i=0; i <RANNUM; ++i){
    ran[i] = rand()%NUMBER;
    }
    for(i=0; i <SIZE; ++i){
    src[i].index = i;
    src[i].value = ran[rand()%RANNUM];
    }
    }
    void Print(const vector <Data>& src){
    cout < <'{';
    int i=0;
    for(i=0; i <SIZE; ++i) {
    cout < <'(' < <src[i].value < <',' < <src[i].index < <"),";
    if ((i+1)%5==0)
    cout < <" } " < <endl;
    }
    }

    int main(int argc ,char* argv[]){
    srand(static_cast <unsigned int>(time(NULL)));
    vector <Data>  src(SIZE), temp(SIZE);
    do{
    ResetData(src);
    cout < <"src: " < <endl;
    Print(src);
    temp = src;
    sort(src.begin(), src.end());
    cout < <"after sort: " < <endl;
    Print(src);
    }while(!HasSameValue(src) || !HasReverseIndex(src));
        return 0;
    }
     
    200  修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • Treazy
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-04-24 21:54:221楼 得分:0
    先占个坑
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • Chiyer
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    • 5

      4

      5

    发表于:2008-04-24 21:55:192楼 得分:0
    村长竟然不会用代码格式贴 - -b
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • baihacker
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    • 4

    发表于:2008-04-24 22:00:333楼 得分:100
    C/C++ code
    VC6 src: {(1,0),(73,1),(73,2),(73,3),(73,4), } (73,5),(1,6),(28,7),(1,8),(76,9), } after sort: {(1,0),(1,6),(1,8),(28,7),(73,1), } (73,2),(73,3),(73,4),(73,5),(76,9), } has same value. no great index. src: {(65,0),(65,1),(0,2),(77,3),(77,4), } (77,5),(0,6),(65,7),(95,8),(65,9), } after sort: {(0,2),(0,6),(65,0),(65,1),(65,7), } (65,9),(77,3),(77,4),(77,5),(95,8), } has same value. no great index. src: {(44,0),(3,1),(53,2),(44,3),(44,4), } (44,5),(3,6),(3,7),(98,8),(3,9), } after sort: {(3,1),(3,6),(3,7),(3,9),(44,0), } (44,3),(44,4),(44,5),(53,2),(98,8), } has same value. no great index. src: {(39,0),(39,1),(76,2),(35,3),(76,4), } (35,5),(35,6),(35,7),(76,8),(35,9), } after sort: {(35,3),(35,5),(35,6),(35,7),(35,9), } (39,0),(39,1),(76,2),(76,4),(76,8), } has same value. no great index. src: {(4,0),(4,1),(37,2),(40,3),(40,4), } (40,5),(40,6),(40,7),(4,8),(40,9), } after sort: {(4,0),(4,1),(4,8),(37,2),(40,3), } (40,4),(40,5),(40,6),(40,7),(40,9), } has same value. no great index. src: {(63,0),(97,1),(97,2),(97,3),(63,4), } (63,5),(17,6),(63,7),(97,8),(15,9), } after sort: {(15,9),(17,6),(63,0),(63,4),(63,5), } (63,7),(97,1),(97,2),(97,3),(97,8), } has same value. no great index. Press any key to continue devc++4.9.9.0 src: {(66,0),(66,1),(66,2),(66,3),(0,4), } (0,5),(4,6),(66,7),(66,8),(0,9), } after sort: {(0,4),(0,5),(0,9),(4,6),(66,0), } (66,1),(66,2),(66,3),(66,7),(66,8), } has same value. no great index. src: {(85,0),(77,1),(49,2),(77,3),(85,4), } (6,5),(77,6),(6,7),(6,8),(85,9), } after sort: {(6,5),(6,7),(6,8),(49,2),(77,1), } (77,3),(77,6),(85,0),(85,4),(85,9), } has same value. no great index. src: {(94,0),(57,1),(57,2),(57,3),(57,4), } (9,5),(9,6),(57,7),(9,8),(94,9), } after sort: {(9,5),(9,6),(9,8),(57,1),(57,2), } (57,3),(57,4),(57,7),(94,0),(94,9), } has same value. no great index. src: {(27,0),(26,1),(26,2),(11,3),(27,4), } (16,5),(11,6),(27,7),(16,8),(26,9), } after sort: {(11,3),(11,6),(16,5),(16,8),(26,1), } (26,2),(26,9),(27,0),(27,4),(27,7), } has same value. no great index. src: {(38,0),(25,1),(25,2),(25,3),(14,4), } (25,5),(14,6),(25,7),(14,8),(14,9), } after sort: {(14,4),(14,6),(14,8),(14,9),(25,1), } (25,2),(25,3),(25,5),(25,7),(38,0), } has same value. no great index. src: {(71,0),(36,1),(71,2),(36,3),(36,4), } (4,5),(4,6),(36,7),(41,8),(71,9), } after sort: {(4,5),(4,6),(36,1),(36,3),(36,4), } (36,7),(41,8),(71,0),(71,2),(71,9), } has same value. no great index. vs2008 src: {(57,0),(46,1),(66,2),(57,3),(66,4), } (66,5),(85,6),(66,7),(46,8),(85,9), } after sort: {(46,1),(46,8),(57,0),(57,3),(66,2), } (66,4),(66,5),(66,7),(85,6),(85,9), } has same value. no great index. src: {(93,0),(93,1),(22,2),(27,3),(36,4), } (27,5),(93,6),(27,7),(93,8),(93,9), } after sort: {(22,2),(27,3),(27,5),(27,7),(36,4), } (93,0),(93,1),(93,6),(93,8),(93,9), } has same value. no great index. src: {(31,0),(31,1),(31,2),(66,3),(31,4), } (31,5),(31,6),(66,7),(66,8),(31,9), } after sort: {(31,0),(31,1),(31,2),(31,4),(31,5), } (31,6),(31,9),(66,3),(66,7),(66,8), } has same value. no great index. src: {(26,0),(78,1),(2,2),(2,3),(87,4), } (78,5),(2,6),(26,7),(87,8),(26,9), } after sort: {(2,2),(2,3),(2,6),(26,0),(26,7), } (26,9),(78,1),(78,5),(87,4),(87,8), } has same value. no great index. src: {(67,0),(36,1),(67,2),(66,3),(36,4), } (62,5),(36,6),(66,7),(66,8),(66,9), } after sort: {(36,1),(36,4),(36,6),(62,5),(66,3), } (66,7),(66,8),(66,9),(67,0),(67,2), } has same value. no great index. src: {(61,0),(11,1),(48,2),(86,3),(61,4), } (86,5),(61,6),(11,7),(61,8),(86,9), } after sort: {(11,1),(11,7),(48,2),(61,0),(61,4), } (61,6),(61,8),(86,3),(86,5),(86,9), } has same value. no great index. 请按任意键继续. . . template<class _RanIt, class _Diff> inline void _Sort(_RanIt _First, _RanIt _Last, _Diff _Ideal) { // order [_First, _Last), using operator< _Diff _Count; for (; _ISORT_MAX < (_Count = _Last - _First) && 0 < _Ideal; ) { // divide and conquer by quicksort pair<_RanIt, _RanIt> _Mid = std::_Unguarded_partition(_First, _Last); _Ideal /= 2, _Ideal += _Ideal / 2; // allow 1.5 log2(N) divisions if (_Mid.first - _First < _Last - _Mid.second) { // loop on second half std::_Sort(_First, _Mid.first, _Ideal); _First = _Mid.second; } else { // loop on first half std::_Sort(_Mid.second, _Last, _Ideal); _Last = _Mid.first; } } if (_ISORT_MAX < _Count) { // heap sort if too many divisions std::make_heap(_First, _Last); std::sort_heap(_First, _Last); } else if (1 < _Count) std::_Insertion_sort(_First, _Last); // small } template<class _RanIt> inline void sort(_RanIt _First, _RanIt _Last) { // order [_First, _Last), using operator< _DEBUG_RANGE(_First, _Last); std::_Sort(_CHECKED_BASE(_First), _CHECKED_BASE(_Last), _Last - _First); }
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • Treazy
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-04-24 22:01:144楼 得分:50
    C/C++ code
    gcc 3.4.4 始终运行,无法停止
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • baihacker
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    • 4

    发表于:2008-04-24 22:05:345楼 得分:0
    加一个int i = 0;和 while (...&&i++ <5)
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • yuanchuang
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-04-24 22:06:056楼 得分:0
    BS
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • Treazy
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-04-24 22:10:117楼 得分:0
    不给我100分,我就 bs 你
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • Chiyer
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    • 5

      4

      5

    发表于:2008-04-24 22:10:398楼 得分:0
    引用 7 楼 Treazy 的回复:
    不给我100分,我就 bs 你
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • baihacker
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    • 4

    发表于:2008-04-24 22:11:509楼 得分:0
    1.稳定性比较
    插入排序、冒泡排序、二叉树排序、二路归并排序及其他线形排序是稳定的
    选择排序、希尔排序、快速排序、堆排序是不稳定的
    2.时间复杂性比较
    插入排序、冒泡排序、选择排序的时间复杂性为O(n2)
    其它非线形排序的时间复杂性为O(nlog2n)
    线形排序的时间复杂性为O(n);
    3.辅助空间的比较
    线形排序、二路归并排序的辅助空间为O(n),其它排序的辅助空间为O(1);
    4.其它比较
    插入、冒泡排序的速度较慢,但参加排序的序列局部或整体有序时,这种排序能达到较快的速度。
    反而在这种情况下,快速排序反而慢了。
    当n较小时,对稳定性不作要求时宜用选择排序,对稳定性有要求时宜用插入或冒泡排序。
    若待排序的记录的关键字在一个明显有限范围内时,且空间允许是用桶排序。
    当n较大时,关键字元素比较随机,对稳定性没要求宜用快速排序。
    当n较大时,关键字元素可能出现本身是有序的,对稳定性有要求时,空间允许的情况下,宜用归并排序。
    当n较大时,关键字元素可能出现本身是有序的,对稳定性没有要求时宜用堆排序
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • healer_kx
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-04-24 22:12:4210楼 得分:0
    我师父太有学习热情了。。。
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • hbqing_ting
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-04-24 22:24:4311楼 得分:0
    好复杂啊!
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • Chiyer
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    • 5

      4

      5

    发表于:2008-04-24 22:28:1112楼 得分:0
    复杂好啊!
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • akirya
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-04-25 14:34:5613楼 得分:0
    复杂,不懂
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • sheenl
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-04-25 15:24:0914楼 得分:50
    这样的方法, 你永远看不到不稳定的情况的。
    没看错的话, 你的数组才10个元素。 而vs2005的sort算法, 32元素以内的时候采用插入排序, 32元素以上采用
    快速排序和插入排序共同工作, 所以实际上你的排序是插入排序完成的, 是稳定的排序。

    注: vc6.0 和 sgi stl则是以16作为阀值, 16元素以下采用插入排序, 16元素以上采用快速排序和插入排序共同
    工作。
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • babyvox1999
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-04-25 16:02:1315楼 得分:0
    引用 11 楼 hbqing_ting 的回复:
    好复杂啊!
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • con_con
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-04-25 18:57:2616楼 得分:0
    引用 14 楼 sheenl 的回复:
    这样的方法, 你永远看不到不稳定的情况的。
    没看错的话, 你的数组才10个元素。 而vs2005的sort算法, 32元素以内的时候采用插入排序, 32元素以上采用
    快速排序和插入排序共同工作, 所以实际上你的排序是插入排序完成的, 是稳定的排序。

    注: vc6.0 和 sgi stl则是以16作为阀值, 16元素以下采用插入排序, 16元素以上采用快速排序和插入排序共同
    工作。


    有道理
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • SummerHeart
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    • 3

    发表于:2008-04-25 18:57:3317楼 得分:0
    牛人。学习了。正好也刚学习STL,不过还没到算法。先学了。呵呵。
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • hastings
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-04-25 20:39:1718楼 得分:0
    无耻占位。
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • laomai
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-04-26 08:21:2319楼 得分:0
    引用 14 楼 sheenl 的回复:
    这样的方法, 你永远看不到不稳定的情况的。
    没看错的话, 你的数组才10个元素。 而vs2005的sort算法, 32元素以内的时候采用插入排序, 32元素以上采用
    快速排序和插入排序共同工作, 所以实际上你的排序是插入排序完成的, 是稳定的排序。

    注: vc6.0 和 sgi stl则是以16作为阀值, 16元素以下采用插入排序, 16元素以上采用快速排序和插入排序共同
    工作。

    多谢sheenl的指点,我前天在飞雪的帮助下也找到了这个原因。
    在vc6下把数组扩到20就得到了我希望的结果。
    准备结贴了。
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • DelphiNew
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-04-26 17:46:5920楼 得分:0
    你只能看源代码来确认,很不幸。。。
    因为,无数个测试样本的成功也只能是必要条件,而不是充分条件~~
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • huang_8228
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-04-28 23:17:3221楼 得分:0
    路过
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • jieao111
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-08-31 17:54:0922楼 得分:0
    C/C++ code
    #include <algorithm> #include <functional> #include <iostream> #include <vector> #include <cstdlib> #include <ctime> using namespace std; // typedef struct { int index; //下标 int value; // }Data; bool operator==(const Data& lhs, const Data& rhs){ return lhs.value == rhs.value; } bool operator <(const Data& lhs, const Data& rhs){ return lhs.value < rhs.value; } //判断数组中是否有相等值,数组应该已经排好序 bool HasSameValue(const vector <Data>& src){ if (adjacent_find(src.begin(), src.end()) != src.end()){ cout < <"has same value." < <endl; return true; } else { cout < <"no same value." < <endl; return false; } } bool IsGreaterIndex(const Data& lhs, const Data& rhs){ return (lhs.value == rhs.value && lhs.index > rhs.index); } //判断等值元素中是否有下标递减的情况, bool HasReverseIndex(const vector <Data>& src){ if (adjacent_find(src.begin(), src.end(), IsGreaterIndex) != src.end()){ cout < <"has great index." < <endl; return true; } else { cout < <"no great index." < <endl; return false; } } const int NUMBER = 100; const int SIZE=10; const int RANNUM = 4; void ResetData(vector <Data>& src){ int i=0; vector <int> ran(RANNUM); for(i=0; i <RANNUM; ++i){ ran[i] = rand()%NUMBER; } for(i=0; i <SIZE; ++i){ src[i].index = i; src[i].value = ran[rand()%RANNUM]; } } void Print(const vector <Data>& src){ cout < <'{'; int i=0; for(i=0; i <SIZE; ++i) { cout < <'(' < <src[i].value < <',' < <src[i].index < <"),"; if ((i+1)%5==0) cout < <" } " < <endl; } } int main(int argc ,char* argv[]){ srand(static_cast <unsigned int>(time(NULL))); vector <Data> src(SIZE), temp(SIZE); do{ ResetData(src); cout < <"src: " < <endl; Print(src); temp = src; sort(src.begin(), src.end()); cout < <"after sort: " < <endl; Print(src); }while(!HasSameValue(src) ¦ ¦ !HasReverseIndex(src)); return 0; }
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • jieao111
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-08-31 17:54:2823楼 得分:0
    C/C++ code
    #include <algorithm> #include <functional> #include <iostream> #include <vector> #include <cstdlib> #include <ctime> using namespace std; // typedef struct { int index; //下标 int value; // }Data; bool operator==(const Data& lhs, const Data& rhs){ return lhs.value == rhs.value; } bool operator <(const Data& lhs, const Data& rhs){ return lhs.value < rhs.value; } //判断数组中是否有相等值,数组应该已经排好序 bool HasSameValue(const vector <Data>& src){ if (adjacent_find(src.begin(), src.end()) != src.end()){ cout < <"has same value." < <endl; return true; } else { cout < <"no same value." < <endl; return false; } } bool IsGreaterIndex(const Data& lhs, const Data& rhs){ return (lhs.value == rhs.value && lhs.index > rhs.index); } //判断等值元素中是否有下标递减的情况, bool HasReverseIndex(const vector <Data>& src){ if (adjacent_find(src.begin(), src.end(), IsGreaterIndex) != src.end()){ cout < <"has great index." < <endl; return true; } else { cout < <"no great index." < <endl; return false; } } const int NUMBER = 100; const int SIZE=10; const int RANNUM = 4; void ResetData(vector <Data>& src){ int i=0; vector <int> ran(RANNUM); for(i=0; i <RANNUM; ++i){ ran[i] = rand()%NUMBER; } for(i=0; i <SIZE; ++i){ src[i].index = i; src[i].value = ran[rand()%RANNUM]; } } void Print(const vector <Data>& src){ cout < <'{'; int i=0; for(i=0; i <SIZE; ++i) { cout < <'(' < <src[i].value < <',' < <src[i].index < <"),"; if ((i+1)%5==0) cout < <" } " < <endl; } } int main(int argc ,char* argv[]){ srand(static_cast <unsigned int>(time(NULL))); vector <Data> src(SIZE), temp(SIZE); do{ ResetData(src); cout < <"src: " < <endl; Print(src); temp = src; sort(src.begin(), src.end()); cout < <"after sort: " < <endl; Print(src); }while(!HasSameValue(src) ¦ ¦ !HasReverseIndex(src)); return 0; }
    修改 删除 举报 引用 回复