注册 登录
编程论坛 C++教室

[原创]排序算法效率比较

wfpb 发布于 2006-07-26 15:42, 3064 次点击

为计算排序算法效率写的测试程序:
#include <iostream>
#include <ctime>
#include <fstream>
using namespace std;

class Timer
{
clock_t start_time;
public:
Timer(){start_time=clock();}

void elaspe()
/*计算时间*/
{
clock_t end_time=clock();
cout<<"It takes "<<(double)(end_time-start_time)/(double)CLK_TCK<<"seconds\n";
}
/*时间归零*/
void reset(){start_time=clock();}
};


#define maxSortNum 4 /*定义排序算法的个数(种类)*/
class CCompositor
{
int *a;
public:
CCompositor(){a=NULL;}
~CCompositor(){delete []a;}
void FileMenu();
void Initional(int i);
void GetFile(ifstream&is,int size);
void doCompose(int n);
/*这里假定只有4种排序*/
void sort_1();
void sort_2();
void sort_3();
void sort_4();
};


void CCompositor::sort_1()
{
//增加代码,完成你的算法
}

void CCompositor::sort_2()
{
//增加代码,完成你的算法
}

void CCompositor::sort_3()
{
//增加代码,完成你的算法
}

void CCompositor::sort_4()
{
//增加代码,完成你的算法
}

void CCompositor::GetFile(ifstream&is,int size)
{
//if(!is)exit(1);
delete a;a=NULL;
a=new int[size];
for(int i=0;i<size;i++)
is>>a[i];
}

void CCompositor::FileMenu()
/*列出所有不同类型的数据*/
{
cout<<" 算法比较数据文件目录\n";
cout<<" ——————————————"<<endl;
cout<<" 1. 数据长度20个, 顺序\n";
cout<<" 2. 数据长度200个, 顺序\n";
cout<<" 3. 数据长度2000个, 顺序\n";
cout<<" 4. 数据长度20个, 逆序\n";
cout<<" 5. 数据长度200个, 逆序\n";
cout<<" 6. 数据长度2000个, 逆序\n";
cout<<" 7. 数据长度20个, 随机\n";
cout<<" 8. 数据长度200个, 随机\n";
cout<<" 9. 数据长度2000个, 随机\n";
cout<<" 10.数据长度20个, 部分排序\n";
cout<<" 11.数据长度200个, 部分排序\n";
cout<<" 12.数据长度200个, 部分排序\n";
cout<<"请选择...";
}
void CCompositor::Initional(int i)
/*根据不同的文件数据进行数据加载*/
{
ifstream is;
switch(i)
{
case 1:is.open("order20.txt"); //长度20, 顺序
GetFile(is,20);break;
case 2:is.open("order200.txt"); //长度200, 顺序
GetFile(is,200);break;
case 3:is.open("order2000.txt"); //长度2000,顺序
GetFile(is,2000);break;
case 4:is.open("unOrder20.txt"); //长度20, 逆序
GetFile(is,20);break;
case 5:is.open("unOrder200.txt"); //长度200, 逆序
GetFile(is,200);break;
case 6:is.open("unOrder2000.txt"); //长度2000,逆序
GetFile(is,2000);break;
case 7:is.open("noOrder20.txt"); //长度20, 随机
GetFile(is,20);break;
case 8:is.open("noOrder200.txt"); //长度200, 随机
GetFile(is,200);break;
case 9:is.open("noOrder2000.txt"); //长度2000,随机
GetFile(is,2000);break;
case 10:is.open("partlyOrder20.txt"); //长度20, 部分排序
GetFile(is,20);break;
case 11:is.open("partlyOrder200.txt"); //长度200, 部分排序
GetFile(is,200);break;
case 12:is.open("partlyOrder2000.txt");//长度2000,部分排序
GetFile(is,2000);break;
default:cout<<"Can't find any file to associate your choice\n";
}
is.close();
}
void CCompositor::doCompose(int n)
{
switch(n)
{
case 1:sort_1();break;
case 2:sort_2();break;
case 3:sort_3();break;
case 4:sort_4();break;
}
}
int _tmain(int argc, _TCHAR* argv[])
{
CCompositor compose;
compose.FileMenu();
int choice;cin>>choice;
compose.Initional(choice);
Timer time;
for(int j=0;j<maxSortNum;j++)
{
compose.doCompose(j+1);
time.elaspe();
time.reset();
}
return 0;
}

17 回复
#2
aogun2006-07-26 16:01
wfpb很闲嘛,呵呵,我最近都忙死了,今天好不容易闲会,稍微看了下,没时间仔细看,提几点建议:
1.对于算法效率比较,比较科学的应该用cpu时间来比较,如果系统比较干净,那么可以用更精确的cpu计数
2.整个程序没有架构可言,不好扩展,排序函数和不同类型的数据种类其实都可以放在容器中,这样比较好增加,不用假定有几种排序了,就算不放容器中也可以用结构数组来存储,这是一种意识,需要注意
3.另外,代码格式还是要注意点的,如两条语句不要放在一行及变量命名规则等,养成良好的风格对于以后有很大的好处
#3
wfpb2006-07-26 16:09
我也想过用函数指针放进数组,但是忘记怎么做了
#4
wfpb2006-07-26 16:16
不同类型的数据种类其实都可以放在容器中,不是啊,这个是测试用的数据,是从文件中读取的。读进数组进行排序,用容器代替数组,对排序有帮助,所以你才建议我用容器的,是吗?

成员函数做函数指针数组怎么做,请说详细点,我这里看书只是一跳而过了
#5
aogun2006-07-26 16:36
定义成员函数的指针数组:
typedef void (CCompositor::*sort)();
sort g_x[] = {&CCompositor::sort_1, &CCompositor::sort_2, &CCompositor::sort_3};

[CODE]不同类型的数据种类其实都可以放在容器中,不是啊,这个是测试用的数据,是从文件中读取的。读进数组进行排序,用容器代替数组,对排序有帮助,所以你才建议我用容器的,是吗?[/CODE]
没,我的意思是
case 1:is.open("order20.txt"); //长度20, 顺序
......

cout<<" 1. 数据长度20个, 顺序\n";
.....

GetFile(is,20)等之间都有对应,这样话这种有对应的数据应该组织起来
#6
wfpb2006-07-26 17:58
你这个思想到是很好,就是不知道从何下手~!
is.open("order20.txt");         //文件关联
cout&lt;&lt;"      1. 数据长度20个,   顺序\n";  //一个输出语句而已
GetFile(is,20)                  //成员函数

如何把他们联系在一个容器结构中啊?

我不会。。。请指教,下次不敢再做同样蠢事
#7
woodhead2006-07-26 19:39
[QUOTE]下次不敢再做同样蠢事[/QUOTE]
不要老这样说,蠢事谁都做过,学到东西就好,谦虚但不要自卑。

如果用文件,我觉得每重只保留最长的那个文件就行了,可以只读取一部分。
#8
wfpb2006-07-26 20:06
如果用文件,我觉得每重只保留最长的那个文件就行了,可以只读取一部分。

恩,是的。
但是aogun说的容器怎么实现还是不知
#9
aogun2006-07-27 15:09

昨天没时间
一般来说,对于有很多同样格式的,并且有扩展的可能信的信息,比较普遍和合理的方法是将其所有的信息放在一个结构数组或者c++的容器中,wfpb,你的程序中的信息可集中的有很多,可以类似下面的定义:
[CODE]typedef struct _TestStruTag
{
int m_iIndex;
char * m_pszInfo;
char * m_pszFileName;
int m_iLength;
}TestStru;
TestStru g_stTest[] = {
1, "1. 数据长度20 个, 顺序", "order20.txt", 20 ,
2, "2. 数据长度200 个, 顺序", "order200.txt", 200 ,
3, "3. 数据长度2000个, 顺序", "order2000.txt", 2000,
4, "4. 数据长度20 个, 逆序", "unOrder20.txt", 20 ,
5, "5. 数据长度200 个, 逆序", "unOrder200.txt", 200 ,
6, "6. 数据长度2000个, 逆序", "unOrder2000.txt", 2000,
7, "7. 数据长度20 个, 随机", "noOrder20.txt", 20 ,
8, "8. 数据长度200 个, 随机", "noOrder200.txt", 200 ,
9, "9. 数据长度2000个, 随机", "noOrder2000.txt", 2000,
10, "10.数据长度20 个, 部分排序", "partlyOrder20.txt", 20 ,
11, "11.数据长度200 个, 部分排序", "partlyOrder200.txt", 200 ,
12, "12.数据长度200 个, 部分排序", "partlyOrder2000.txt", 200 ,
};
const int g_stTestLength = sizeof(g_stTest) / sizeof(TestStru);[/CODE]



这样的话,程序中的
[CODE] cout<<" 算法比较数据文件目录\n";
cout<<" ——————————————"<<endl;
cout<<" 1. 数据长度20个, 顺序\n";
cout<<" 2. 数据长度200个, 顺序\n";
cout<<" 3. 数据长度2000个, 顺序\n";
cout<<" 4. 数据长度20个, 逆序\n";
cout<<" 5. 数据长度200个, 逆序\n";
cout<<" 6. 数据长度2000个, 逆序\n";
cout<<" 7. 数据长度20个, 随机\n";
cout<<" 8. 数据长度200个, 随机\n";
cout<<" 9. 数据长度2000个, 随机\n";
cout<<" 10.数据长度20个, 部分排序\n";
cout<<" 11.数据长度200个, 部分排序\n";
cout<<" 12.数据长度200个, 部分排序\n";
cout<<"请选择...";[/CODE]
可以替换为:
[CODE] cout<<" 算法比较数据文件目录\n";
cout<<" ——————————————"<<endl;
for (i = 0; i < g_stTestLength; i ++)
{
cout<<" "<<g_stTest[i].m_pszInfo<<endl;
}
cout<<"请选择...";[/CODE]

[CODE]switch(i)
{
case 1:is.open("order20.txt"); //长度20, 顺序
GetFile(is,20);break;
case 2:is.open("order200.txt"); //长度200, 顺序
GetFile(is,200);break;
case 3:is.open("order2000.txt"); //长度2000,顺序
GetFile(is,2000);break;
case 4:is.open("unOrder20.txt"); //长度20, 逆序
GetFile(is,20);break;
case 5:is.open("unOrder200.txt"); //长度200, 逆序
......
}[/CODE]
可以替换为:
[CODE] for (j = 0; j < g_stTestLength; j ++)
{
if (g_stTest[j].m_iIndex == i)
{
is.open(g_stTest[j].m_pszFileName);
GetFile(is,g_stTest[j].m_iLength);
break;
}
}
if (j == g_stTestLength)
{
cout<<"Can't find any file to associate your choice\n";
}[/CODE]
这样做的好处有很多,说几点重要的:
首先,利于有对应的信息之间的正确核实,因为有联系的信息都写在一行,有利于对比,这样不会出现错误的信息对,就算出现了也很方便查找,
其次,简化了以后的代码的编写,以后的代码只需要一个循环,不会再出现多余的代码,比较简洁
再次,比较好扩展,如果你以后要加入新的信息对,只需要修改上面的g_stTest数组,其它地方都不需要修改,对于以后代码的维护起到很重要的作用,如果不这样的话,以后你要增加信息对的话要修改很多地方,稍微不小心就会漏掉,当然,你的程序现在代码量还很少,但是以后代码到了数千行,或者参与大型工程,那么要修改的地方就......

上面的方法是c中用的方法,在c++中可以用容器,比如map,index可以作为map的key,或者用其它容器都可以,当然,用数组在效率方面是很高的

#10
song42006-07-27 15:15
555555555
我实在太小了,根本看不懂
还没学数据呢
#11
wfpb2006-07-27 19:24
回复:(aogun)昨天没时间一般来说,对于有很多同样格...
谢谢了,知道怎么联系他们了,觉得这个指针放数组和相关内容的关联的确是很重要也是很必要的一个知识
#12
wfpb2006-07-28 12:58

正如你说的那样,改过以后清晰很多

[此贴子已经被作者于2006-7-28 12:59:48编辑过]

#13
wfpb2006-07-28 12:58
我按照你说的改了下:
程序代码:

#include "stdafx.h"
#include &lt;iostream&gt;
#include &lt;ctime&gt;
#include &lt;fstream&gt;
using namespace std;

class Timer
{
    clock_t start_time;
public:
    Timer(){start_time=clock();}

    void elaspe()
    /*计算时间*/
    {
        clock_t end_time=clock();
        cout&lt;&lt;"It takes "&lt;&lt;(double)(end_time-start_time)/(double)CLK_TCK&lt;&lt;"seconds\n";
    }
    /*时间归零*/
    void reset(){start_time=clock();}
};


#define maxSortNum 4    /*定义排序算法的个数(种类)*/
class CCompositor
{
    int *a;
public:
    CCompositor(){a=NULL;}
    ~CCompositor(){delete []a;}
    void FileMenu();
    void Initional(int i);
    void GetFile(ifstream&amp;is,int size);
    void doCompose(int n);
    void sort_1();
    void sort_2();
    void sort_3();
    void sort_4();
};


typedef void (CCompositor::*sort)();
sort g_x[] = {&amp;CCompositor::sort_1, &amp;CCompositor::sort_2, &amp;CCompositor::sort_3, &amp;CCompositor::sort_4};


struct SortStruct
{
    int m_iIndex;    //索引
    char* m_pChoice; //文件类型
    char* m_pFile;     //文件路径
    int m_iInfoSize; //文件大小
};


SortStruct sortArr[]={
    1, "      1. 数据长度20个,   顺序\n",    "order20.txt",            20,
        2, "      2. 数据长度200个,  顺序\n",    "order200.txt",            200,
        3, "      3. 数据长度2000个, 顺序\n",      "order2000.txt",            2000,
        4, "      4. 数据长度20个,   逆序\n",      "unOrder20.txt",            20,
        5, "      5. 数据长度200个,  逆序\n",      "unOrder200.txt",            200,
        6, "      6. 数据长度2000个, 逆序\n",      "unOrder2000.txt",        2000,
        7, "      7. 数据长度20个,   随机\n",      "noOrder20.txt",            20,
        8, "      8. 数据长度200个,  随机\n",      "noOrder200.txt",            200,
        9, "      9. 数据长度2000个, 随机\n",      "noOrder2000.txt",        2000,
        10,"      10.数据长度20个,   部分排序\n","partlyOrder20.txt",        20,
        11,"      11.数据长度200个,  部分排序\n","partlyOrder200.txt",        200,
        12,"      12.数据长度200个,  部分排序\n","partlyOrder2000.txt",    2000,
};


void CCompositor::sort_1()
{
    //增加代码,完成你的算法
}

void CCompositor::sort_2()
{
    //增加代码,完成你的算法
}

void CCompositor::sort_3()
{
    //增加代码,完成你的算法
}

void CCompositor::sort_4()
{
    //增加代码,完成你的算法
}

void CCompositor::GetFile(ifstream&amp;is,int size)
{
    //if(!is)exit(1);
    delete a;a=NULL;
    a=new int[size];
    for(int i=0;i&lt;size;i++)
    is&gt;&gt;a[i];
}


void CCompositor::FileMenu()
/*列出所有不同类型的数据*/
{
    cout&lt;&lt;"         算法比较数据文件目录\n";
    cout&lt;&lt;"      ——————————————"&lt;&lt;endl;
    for (int i=0;i&lt;sizeof(sortArr)/sizeof(SortStruct);i++)
    {
        cout&lt;&lt;sortArr[i].m_pChoice;
    }
    cout&lt;&lt;"请选择...";
}
void CCompositor::Initional(int i)
/*根据不同的文件数据进行数据加载*/
{
    ifstream is;
    is.open(sortArr[i-1].m_pFile);
    GetFile(is,sortArr[i-1].m_iInfoSize);
    is.close();
}


int _tmain(int argc, _TCHAR* argv[])
{
    CCompositor compose;
    compose.FileMenu();
    int choice;cin&gt;&gt;choice;
    compose.Initional(choice);
    Timer time;
    for(int j=0;j&lt;sizeof(g_x)/4;j++)
    {
        g_x[j];   
        time.elaspe();
        time.reset();
    }
    return 0;
}
#14
farderce2006-07-30 16:14

排个顺序还要用个函数 切

#15
blpluto2006-11-03 16:40

看了楼上的精彩评论 收益匪浅啊
不过我有个想法 既然是测试排序的效率 那应该不用如此复杂的程序
time()函数可设计为顶层函数
还有,我觉的这个程序没有必要用类,
用简单的程序就可以了 不需要封装

#16
shengwumozhe2006-11-03 17:29
以下是引用song4在2006-7-27 15:15:15的发言:
555555555
我实在太小了,根本看不懂
还没学数据呢

同感=,-

#17
cxmprogramer2007-01-19 11:20

为什么用_tmain啊,它跟main有什么区别吗?

#18
peswe2007-01-20 13:54
腾云驾雾中!!~~~~~~~~~~~~~
1