Vector与List在对序列元素进行增删操作时性能的比较
Posted akynazh
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Vector与List在对序列元素进行增删操作时性能的比较相关的知识,希望对你有一定的参考价值。
我们知道vector结构 与 list结构 在对序列元素进行增删操作时的性能有差异,现在我们在实际的学生成绩管理程序中进行测试比较。
习题来源:《accelerated C++》P85: 习题5-2:
编写完整的新版计算学生成绩的程序,并且使用vector抽取不及格的学生的记录。然后再编写一个使用list的版本。对与100行,1000行,10000行的输入文件,分别比较这两个版本的性能差异。
ps: 由于只有extract_fails函数部分涉及对序列元素的增删操作,所以测试点为使用extract_fails函数的部分代码。每种规模的测试共进行5次。
两者测试点处代码是相同的:
clock_t start = clock();
fail_students = extract_fails(students);
clock_t end = clock();
cout << "time = " << (double)(end-start)/CLOCKS_PER_SEC<< "s" << endl;
基于vector结构的extract_fails函数:
vector<Student_info> extract_fails(vector<Student_info>& students)
vector<Student_info> fail;
vector<Student_info>::iterator iter = students.begin();
while(iter != students.end())
if(fgrade(*iter))
fail.push_back(*iter);
iter = students.erase(iter);//使得iter指向被删除元素之后跟着的元素
else
++iter;
return fail;
改写后的基于list结构的extract_fails函数:
list<Student_info> extract_fails(list<Student_info>& students)
list<Student_info> fail;
list<Student_info>::iterator iter = students.begin();
while(iter != students.end())
if(fgrade(*iter))
fail.push_back(*iter);
iter = students.erase(iter);//使得iter指向被删除元素之后跟着的元素
else
++iter;
return fail;
vector测试结果:
100组数据: 0.001s 0.001s 0.001s 0.001s 0.001s
1000组数据: 0.024s 0.023s 0.022s 0.024s 0.023s
10000组数据: 2.232s 2.243s 2.146s 2.141s 2.235s
list测试结果:
//100数据: 0.000s 0.000s 0.000s 0.000s 0.000s(数值太小以至于精度不够)
//1000数据: 0.001s 0.001s 0.001s 0.001s 0.001s
//10000数据: 0.009s 0.008s 0.007s 0.007s 0.008s
现象与分析:对比vector的测试结果,可以发现,list结构在对序列元素进行增删操作时时间明显快于vector,并且随着数据规模的增大,时间差异体现的更加明显。
结论:(1)list结构更适用于序列的增删操作(在这部分操作上时间复杂度明显低于vector)。
(2)随着数据规模增大,list的性能优势体现的更加明显。**
附上改写后的基于list结构的代码:
#include<algorithm>//sort
#include<iomanip>//setprecision
#include<ios>//streamsize
#include<iostream>
#include<string>
#include<list>
#include<stdexcept>//domain_error
using namespace std;
struct Student_info
string name;
double midterm,final;
list<double> homework;
; //学生结构体
//计算中值的函数
double median(list<double> LIST)
if(LIST.size()==0)
throw domain_error("median of an empty vector");
LIST.sort();
list<double>::iterator iter = LIST.begin();
if(LIST.size()%2 != 0)
list<double>::size_type i = 0;
while(i != LIST.size()/2)
i++;
iter++;
return *iter;
else
list<double>::size_type i = 0;
while(i != LIST.size()/2)
i++;
iter++;
return (*iter+*(++iter))/2;
//三个计算grade的函数,利用了重载,这里省略了函数内容。
double grade(double midterm,double final,double homework)
double grade(double midterm,double final,const list<double>& hw)
double grade(const Student_info& s)
//两个输入成绩的函数,同样利用了重载,省略了函数内容。
istream& read_hw(istream& in,list<double>& hw)
istream& read(istream& is, Student_info& s)
bool compare(const Student_info& x,const Student_info& y)
return x.name<y.name;
//用于sort的第三个参数,谓词,用于按名字进行的排名
//判断最终成绩是否及格
bool fgrade(const Student_info& s)
return grade(s) < 60;
//测试点函数
//剔除不及格学生,并且得到不及格学生的名单fail
list<Student_info> extract_fails(list<Student_info>& students)
list<Student_info> fail;
list<Student_info>::iterator iter = students.begin();
while(iter != students.end())
if(fgrade(*iter))
fail.push_back(*iter);
iter = students.erase(iter);//使得iter指向被删除元素之后跟着的元素
else
++iter;
return fail;
int main()
list<Student_info> students, fail_students;
Student_info record;
string::size_type maxlen = 0;
while(read(cin,record))
maxlen=max(maxlen,record.name.size());
students.push_back(record);
//找出最长的名字长度
//同样的,对extract_fails函数部分进行测试
//测试点
clock_t start = clock();
fail_students = extract_fails(students);
clock_t end = clock();
cout << "time = " << (double)(end-start)/CLOCKS_PER_SEC<< "s" << endl;
//根据名字进行排序
students.sort(compare);
fail_students.sort(compare);
cout << "students who have passed:" << endl << endl;
list<Student_info>::iterator iter1 = students.begin(),
iter2 = fail_students.begin();
while(iter1 != students.end())
cout << (*iter1).name << string(maxlen + 1 - (*iter1).name.size(), ' ');
try
double final_grade = grade(*iter1);
streamsize prec = cout.precision();
cout << setprecision(3) << final_grade//保留三位有效数字
<< setprecision(prec) << endl;
catch(domain_error e)
cout << e.what();
cout<<endl;
iter1++;
cout << "students who have failed:" << endl << endl;
while(iter2 != fail_students.end())
cout << (*iter2).name << string(maxlen + 1 - (*iter2).name.size(), ' ');
try
double final_grade = grade(*iter2);
streamsize prec = cout.precision();
cout << setprecision(3) << final_grade
<< setprecision(prec) << endl;
catch(domain_error e)
cout << e.what();
cout << endl;
iter2++;
return 0;
注:参考书籍《accelerated C++》
以上是关于Vector与List在对序列元素进行增删操作时性能的比较的主要内容,如果未能解决你的问题,请参考以下文章