C++ 编写一个函数的两个版本,一个用于“引用”;“清晰性”;一个是“一”;“速度”;

C++ 编写一个函数的两个版本,一个用于“引用”;“清晰性”;一个是“一”;“速度”;,c++,C++,我的教授布置了家庭作业,写了一个函数,它接受一个整数数组,并将所有的零排序到数组的末尾,同时保持当前非零整数的顺序。制约因素包括: 无法使用STL或其他模板化容器。 必须有两个解决方案:一个强调速度,另一个强调清晰 为了提高速度,我编写了这个函数: #include <iostream> #include <cstdio> #include <cstdlib> using namespace std; void sortArray(int array[],

我的教授布置了家庭作业,写了一个函数,它接受一个整数数组,并将所有的零排序到数组的末尾,同时保持当前非零整数的顺序。制约因素包括:

无法使用STL或其他模板化容器。 必须有两个解决方案:一个强调速度,另一个强调清晰

为了提高速度,我编写了这个函数:

#include <iostream>
#include <cstdio>
#include <cstdlib>
using namespace std;

void sortArray(int array[], int size)
{
    int i = 0;
    int j = 1;
    int n = 0;
    for (i = j; i < size;)
    {
        if (array[i] == 0)
        {
            n++;
            i++;
        }
        else if (array[i] != 0 && j != i)
        {
            array[j++] = array[i++];
        }
        else
        {
            i++;
            n++;
        }
    }
    while (j < size)
    {
        array[j++] = 0;
    }
}

int main()
{
    //Example 1
    int array[]{20, 0, 0, 3, 14, 0, 5, 11, 0, 0};
    int size = sizeof(array) / sizeof(array[0]);
    sortArray(array, size);
    cout << "Result :\n";
    for (int i = 0; i < size; i++)
    {
        cout << array[i] << " ";
    }
    cout << endl << "Press any key to exit...";
    cin.get();
    return 0;
}
#包括
#包括
#包括
使用名称空间std;
void排序数组(int数组[],int大小)
{
int i=0;
int j=1;
int n=0;
对于(i=j;i(我觉得你的问题几乎是偏离主题的,我从Linux的角度来回答它,我建议使用Linux学习C++编程;如果你使用其他的东西,你会把我的建议修改到你的操作系统上)

速度 关于速度,您应该有两种互补的方法

第一个(某种程度上是“理论的”)是分析(即思考)你的算法,并给出它的渐近性

第二种方法(仅“实用”,而且通常是实用的)是和您的程序。不要忘记使用enabled编译(例如,使用
g++-Wall-O2
with)。使用运行时间超过半秒的基准测试(因此处理大量数据,例如数百万个数字)并重复多次(例如,在Linux上使用命令)。您也可以使用C++11或(如果您从某个文件中读取一个大数组,或者使用或构建一个伪随机数的大数组,那么您肯定希望单独测量读取或填充数组的时间,以及从数组中移出零的时间).另见

(你需要处理大量数据——超过一百万个项目,也许几百万个项目——因为计算机速度非常快;一个典型的“基本”操作——a——只需不到一纳秒,而且你在一次运行中有很多不确定性,请参阅)

清晰 关于清晰性,这有点主观,但您可以尝试使代码可读且简洁。添加一些好的注释也会有所帮助。 命名时要小心:这不完全是您的程序正在做的事情(它更像是移动零而不是排序数组).

速度和复杂性一样快吗? 由于您需要查看数组中的所有元素,因此有一个循环遍历范围
[0,N)
,其中N表示输入的大小,因此您的解决方案是
O(N)

进一步阅读:


关于清晰性 在我看来,在实现您所展示的功能时,不需要有两种选择。如果您将变量重命名为更合适的(描述性)名称,那么您当前的解决方案应该足够清晰,可以算作performant和clear

您当前的方法可以用简单的英语以非常清晰的方式编写:

伪解释
  • 将write_索引设置为0
  • 将0的个数设为0
  • 对于
    数组中的每个元素
    • 如果元素为
      0
    • 将0的数量增加1
    • 否则
    • 将元素值写入由write_索引表示的位置
    • 将write_索引增加1
  • 数组
    0的末尾写入0的个数
s 通过上面的解释,我们可以很快看出,
sortArray
不是函数的描述性名称,更合适的名称可能是
partition_zero
或类似名称


添加注释可以提高可读性,但您当前的重点应该是重命名变量,以更好地表达代码的意图。

根据我的经验,除非您有非常复杂的算法,否则速度和清晰性都要结合在一起:

void sortArray(int array[], int size)
{
  int item;
  int dst = 0;
  int src = 0;

  // collect all non-zero elements
  while (src < size) {
    if (item = array[src++]) {
      array[dst++] = item;
    }
  }

  // fill the rest with zeroes
  while (dst < size) { 
    array[dst++] = 0;
  }
}
void sortArray(int数组[],int大小)
{
国际项目;
int-dst=0;
int src=0;
//收集所有非零元素
while(src

速度来自于一个好的算法。清晰来自于格式化、命名变量和注释。

我认为这是最好的——当然你可能希望使用doxygen或其他一些

// Shift the non-zeros to the front and put zero in the rest of the array
void moveNonZerosTofront(int *list, unsigned int length)
{
   unsigned int from = 0, to = 0;

   // This will move the non-zeros
   for (; from < length; ++from) {
      if (list[from] != 0) {
          list[to] = list[from];
          to++;
      }
   }

   // So the rest of the array needs to be assigned zero (as we found those on the way)
   for (; to < length; +=to) {
     list[to] = 0;
   }
}
//将非零移到前面,并将零放在数组的其余部分
void moveNonZerosTofront(整数*列表,无符号整数长度)
{
无符号整数from=0,to=0;
//这将移动非零
for(;from
你的教授是个白痴。你可以编写既清晰又快速的代码。你可以使用注释。你应该一直编写尽可能清晰有效的代码。没有人会编写第二个版本。除非你是那种开发人员,他们编写的代码总是按照客户的要求运行,因此永远不需要做任何修改更改和/或修复(是的,这是一个空集),以牺牲其他任何东西为代价而失去清晰度是一个非常糟糕的计划