【问题标题】:How can I optimize this code to print in this format?如何优化此代码以这种格式打印?
【发布时间】:2016-03-01 04:34:58
【问题描述】:

我想打印一个这样的链表:

0       1       2       3       4
12      24      36      85      48

我当前的代码是

void LinkedList::printList()
{
    curr = head; //store head in curr to irerate
    int count = 0; //counter to help uer manipulate list
    while (curr != NULL) //traverse whole list
    {
        cout << count++ <<"\t"; //print index
        curr = curr->next; //move to next 
    }
    curr = head; //make current head again
    cout << endl;//go to next line
    while (curr != NULL) //traverse whole list
    {
        cout << curr->data << "\t"; //print data
        curr = curr->next; //move to next 
    }
    cout << endl;
}

我很确定还有另一种方法可以做到这一点,这是一种更简单、更快捷的方法。我想减少这段代码的冗余。

我正在显示计数器以帮助用户添加或删除数字。

【问题讨论】:

  • 数据中的数字有多大,您是否每 5 个数字打印一次?
  • 更新代码是固定大小的链表?我在提出解决方案时假设了这一点
  • 鉴于您的列表很小(如果它很大,显示输出的屏幕也必须很大;)),您可以使用 1 次遍历而不是 2 次遍历并使用 2 个实例std::ostringstream,可以同时创建计数和元素值字符串,然后在循环结束后输出。
  • 如果你想打印换行输出,你会在小块中工作。在将列表移至max_per_line 并打印索引(检查NULL)时保存指向当前位置的指针。然后打印一个换行符并再次遍历列表。或者,不要重新遍历列表,而是将要打印的列表数据复制到一个小数组中。或者像 BitTickler 建议的那样即时格式化。这确保即使是长列表也不会导致问题,因为您只会对它们进行小块操作。
  • @TahTatsumoto 它只是用于练习的东西,所以不是很大。

标签: c++ performance c++11 optimization time-complexity


【解决方案1】:
#include <sstream>
void LinkedList::printList(std::ostream& os = std::cout) {
    size_t counter = 0;
    std::ostringstream indx;
    std::ostringstream value;
    for( ListNode *current = head; current != NULL; current = current->next ) {
        indx << counter++ << "\t";
        value << current->data << "\t";
    }
    os << indx.str().c_str() << std::endl << value.str().c_str() << std::endl;
}
  • 只有一个 List 遍历
  • for 循环而不是 while。
  • 速度并不重要,因为您的列表应该很小(除非您的屏幕非常宽或字体很小),因为您希望列表的内容整齐地放入输出窗口的 1 行中。李>

【讨论】:

    【解决方案2】:

    这真的取决于你所说的“优化”是什么意思。由于缓存局部性差,链表本质上不是遍历的最佳选择。更不理想的是将整数数据转换为文本并写入流。

    所以我只能得出结论,您希望减少代码冗余并将其视为一种优化,即使它以牺牲执行时间为代价。一种可能的解决方案是接受一个应用于每个元素的函数:

    void LinkedList::forEach( std::function<void (node*)> fn )
    {
        for( node *curr = head; curr != NULL; curr = curr->next )
        {
            fn( curr );
        }
    }
    

    现在您可以使用它来打印节点数据或其他内容:

    void LinkedList::printList()
    {
        int count = 0;
        forEach( [&count]( node * ) { cout << count++ << "\t"; } );
        cout << endl;
        forEach( []( node *n ) { cout << n->data << "\t"; } );
        cout << endl;
    }
    

    【讨论】:

    • 请注意,可以通过为您的类定义自定义 前向迭代器,然后使用标准语言特性(如 foreach)或来自 @987654324 的函数来使用类似的方法@对你的列表进行操作。但是,制作自定义迭代器比建议的解决方案要复杂一些。所以我把它排除在外了。
    【解决方案3】:

    您可以尝试使用 ANSI 转义码来移动打印输出位置,并在一个循环中完成所有操作。 http://www.tldp.org/HOWTO/Bash-Prompt-HOWTO/x361.html

    【讨论】:

    • 这仅对支持 ANSI 的终端有用,不适用于长列表。写入流将是一团糟。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-07-11
    • 2011-04-09
    • 2015-06-09
    • 2013-03-09
    • 1970-01-01
    • 2015-08-17
    • 1970-01-01
    相关资源
    最近更新 更多