在我的情况下更好的是:矢量或列表?

时间:2014-12-04 15:50:09

标签: c++ list sorting vector

我有一个函数可以读取文件夹中的文件(我正在使用boost)。我也试图只保留2个文件(它们是日志文件,因此它们被轮换,我不想在第三个文件中保留旧的logs = logs)。我将文件的名称存储在列表中,但由于读取不是按创建时间顺序完成的,因此我需要对列表进行排序。

我知道

  

矢量擅长:

     
      
  • 按位置索引(恒定时间)访问各个元素。
  •   
  • 以任意顺序(线性时间)迭代元素。
  •   
  • 从结尾添加和删除元素(常量摊销时间)。
  •   

  

列出容器的优点:

     
      
  • 在容器中的任何位置高效插入和移除元素   (恒定时间)。
  •   
  • 容器内或甚至不同容器之间的高效移动元素和元素块(恒定时间)。
  •   
  • 以正向或反向顺序(线性时间)迭代元素。
  •   

我不确定执行此操作的最佳方式是什么:使用列表或向量?

我要

  • 使用向量并对其进行升序排序,从末尾删除,添加新元素(最后),重新排序等; 或
  • 使用列表并升序排序,从头开始删除,最后添加新元素,度假等;

  • 只在开头需要排序,因为我插入的每个文件名都是最后创建的吗?
  • 如果对列表/向量进行排序,那么诉诸它的时间是什么时候?
  • 如果我使用std::is_sorted,是不是每次都不排序?

更多信息:

因为boost的文件轮换没有“删除文件,如果太多”状态,只有“磁盘上有足够的空间”,我已经实现了保留最后两个文件的步骤,或者每次删除最旧的文件新的一个创建,有2个日志文件。因此,每次创建新的日志文件时,我都会验证文件列表,如果有足够的(2个或更多),则只删除较旧的日志文件。由于文件名称为logs_%N.log,我无法知道文件logs_X1.log是否早于logs_X2.log

  

例如:我重新启动应用程序,有文件logs_51.log,logs_52.log,哪一个将被删除?假设它将删除logs_51.log并创建logs_0.log,如果我再次重新启动它,将会有logs_52.log和logs_0.log。现在要删除哪一个?)

这就是我需要排序的原因,因为应用程序可能会重新启动,我读取现有文件,完成具有更多空间的文件,然后创建一个新文件。

3 个答案:

答案 0 :(得分:3)

对于这种特殊情况,容器将有~2个元素,它并不重要。枚举文件和删除文件所花费的时间将比您选择的算法和数据结构慢几个数量级。只需将文件名放在std::vector中,使用std::sort(将对日志文件名进行排序,使最早的名称排在第一位),然后删除N-2个第一项。完成工作。

但是对于一些一般建议:

这些天的一般建议似乎是std::vector优于std::list,即使很多事情std::list似乎也会有好处,主要是因为它&# 39;连续存储,对缓存更友好。

可以构建基准,以便显示std::list更快,但如果您为所有内容选择std::vector,那么您将不会出错!

如果您需要随着时间的推移维护容器并始终需要能够删除最小/最大的元素,std::priority_queue可能是个好主意。

如果您需要在容器中找到N个最小/最大的项目,std::partial_sort是执行此操作的算法;它会比一个完整的std::sort更快,因为它不会浪费精力来整理你不关心的元素。

但是像这样的所有一般性能问题一样,唯一正确的答案必须是"尝试并看到"我很害怕!

编辑:我最初建议boost::circular_buffer,因为问题听起来像是什么,但现在很清楚它不是一个好建议,因为订单需要由排序,而不是按顺序排序。

答案 1 :(得分:0)

这里没有人知道,这家伙需要比较2个文件的名称,而不是数据结构课程

使用字符串:: compare来比较文件,是的,它会比较日志文件末尾的那些数字,所以不要担心

这是它的工作原理

 value=String.Compare(filenameA,filenameB)



  If value<0 then print("filenameA is smaller than filenameB")
  If value>0  then print("a is bigger than b") 
  If value=0  then print("a equals b")
哦,关于数据结构选择,您不需要关心效率或性能问题 我的意思是你只是按名称索引2个文件,一个简单而简单的数组就可以解决这个问题

这是一个如何做的例子

putNewFileMethod(FileType* arrayofFiles,FileType MynewFile)`
{



String nameOfFile0=arrayOfFiles[0].method_that_retrieves_the_filename();
String nameOfFile1=arrayOfFiles[1].method_that_retrieves_the_filename();//you can search for a method of this kind in the docs of the api you are using,`

int value=String.Compare(nameOfFile0,nameOfFile1);

      If( value<0)
        arrayOfFiles[0]=MynewFile;
else    arratOfFiles[1]=MynewFile;


}

补充说明:

你可以使用2个位置的圆形阵列,这些位置不需要对文件进行排序,但你提到了一些关于重新启动应用程序的内容,所以我想这对你来说不是最佳解决方案, (如果你想要一个圆形数组/缓冲区的例子,请告诉我)

数据结构不具备构建排序功能,至少大多数都是如此,所以你只需要做一个自己的

答案 2 :(得分:0)

实际上我使用Boost以最后修改的方式对文件进行排序:

bool Logger::compareAccessTime(const std::string& path1In, const std::string& path2In)
{
    return (fs::last_write_time(fs::path(path1In)) < fs::last_write_time(fs::path(path2In)));
}

其中fs = boost::filesystem

因为我使用了一个字符串列表,所以我没有更改整个代码,但在初始化列表时添加了list::sort(compareAccessTime)。我只在应用程序的开头需要它,因为我在最后添加并从开始删除。