【问题标题】:C++: Should I implement stack / queue / deque by array to improve performance?C++:我应该按数组实现堆栈/队列/双端队列以提高性能吗?
【发布时间】:2015-02-16 19:53:13
【问题描述】:

我刚刚解决了一个关于 SPOJ 的问题,我做 DFS 并使用 STL 堆栈而不是递归,我得到了 TLE。然后我使用数组堆栈而不是 STL 堆栈并被接受。

问题是:给一个n*n的表,每个方格都有一个数字。首先,你可以从任何方格开始,选择一个数字K。然后你可以去与你站立的方格有共同边的方格,abs(那个方格上的数字-你站立的方格上的数字)== K。你可以去的最大区域是什么?

这是我的解决方案:

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <utility>
#include <cmath>
#include <cstring>
#include <stack>
using namespace std;

#define maxn 1010

int n, a[maxn][maxn],visited[maxn][maxn], direction[5][3],cnt,anscnt,dd[1000010],dc[1000010],k[1000010];
bool Free[maxn][maxn][5];

/*void visit(int d,int c,int dif) {
    stack<int> dd,dc,k;
    dd.push(d);
    dc.push(c);
    k.push(1);
    visited[d][c]=dif;
    cnt = 0;
    while (!dd.empty()) {
        int ud = dd.top(), uc = dc.top() , i = k.top();
        k.pop();
        for (;i<=4;i++)
        if (Free[ud][uc][i]) {
            int vd = ud+direction[i][1], vc = uc + direction[i][2];
            if ((vd==0) or (vc==0) or (vd>n) or (vc>n)) continue;
            if ((visited[vd][vc]==dif) or (abs(a[vd][vc]-a[ud][uc])!=dif)) continue;
            if (Free[vd][vc][5-i]==false) continue;
            visited[vd][vc]=dif;
            Free[vd][vc][5-i]=false;
            Free[ud][uc][i]=false;
            k.push(i+1);
            dd.push(vd);
            dc.push(vc);
            k.push(1);
            break;
        }
        if (i==5) {
                cnt++;
                cout << ud << ' ' << uc << ' ' << dd.top() << ' ' << dc.top() <<  ' ' << dd.size() << '\n';
                dd.pop(); dc.pop();
        }
    }
     if (cnt > anscnt) {anscnt = cnt;}
} */

void visit(int d,int c,int dif) {
    int topdd=0, topdc=0, topk=0;
    dd[++topdd]=d;
    dc[++topdc]=c;
    k[++topk]=1;
    visited[d][c]=dif;
    cnt = 0;
    while (topdd>0) {
        int ud = dd[topdd], uc = dc[topdc] , i = k[topk];
        topk--;
        for (;i<=4;i++)
        if (Free[ud][uc][i]) {
            int vd = ud+direction[i][1], vc = uc + direction[i][2];
            if ((vd==0) or (vc==0) or (vd>n) or (vc>n)) continue;
            if ((visited[vd][vc]==dif) or (abs(a[vd][vc]-a[ud][uc])!=dif)) continue;
            if (Free[vd][vc][5-i]==false) continue;
            visited[vd][vc]=dif;
            Free[vd][vc][5-i]=false;
            Free[ud][uc][i]=false;
            k[++topk]=(i+1);
            dd[++topdd]=(vd);
            dc[++topdc]=(vc);
            k[++topk]=(1);
            break;
        }
        if (i==5) {
                cnt++;
                topdd--; topdc--;
        }
    }
     if (cnt > anscnt) {anscnt = cnt;}
}

int main()
{
    std::ios_base::sync_with_stdio(false);
    anscnt = 1;
    direction[1][1] = -1; direction[1][2] = 0;
    direction[2][1] = 0;  direction[2][2] = 1;
    direction[3][1] = 0;  direction[3][2] = -1;
    direction[4][1] = 1;  direction[4][2] = 0;
    cin >> n;
    for (int i=1; i<=n; i++)
      for (int j=1; j<=n; j++) cin >> a[i][j];
    for (int i=1; i<=n; i++)
      for (int j=1; j<=n; j++) visited[i][j]=-1;
    memset(Free,true,sizeof(Free));
    for (int i=1; i<=n; i++)
        for (int j=1; j<=n; j++) {
                    if (i>1) visit(i,j,abs(a[i][j]-a[i-1][j]));
                    if (j<n) visit(i,j,abs(a[i][j]-a[i][j+1]));
                    if (j>1) visit(i,j,abs(a[i][j]-a[i][j-1]));
                    if (i<n) visit(i,j,abs(a[i][j]-a[i+1][j]));
                }
    cout << anscnt;
}

http://ideone.com/Hn6Dl4

当n = 1000,并且table中的所有方格=0时,STL栈大于2s,数组栈小于1s。 所以我认为堆栈的 STL 实现比按数组实现堆栈要慢。队列、双端队列也可以用数组来实现。

为什么 STL 实现速度较慢,我应该通过数组来实现它们以提高性能?

【问题讨论】:

  • 这是无法回答的。您是否应该使用堆栈上的数组来提高性能取决于您更关心性能还是可读性/可维护性/可调试性等。如果性能是您唯一关心的问题,那么自定义数据结构通常会胜过一般数据结构。
  • “为什么 STL 实现速度较慢...” - “预取器”浮现在脑海中。逐节点分配可能是您可以为这样的任务召集的最差内存访问模型。您问题的第二部分完全取决于

标签: c++ stl stack queue deque


【解决方案1】:

像往常一样,您应该始终在简单情况下使用直接内存访问(如数组),或者为复杂情况实施自己的数据结构以获得更好的性能。标准容器具有降低内存访问性能的检查、内切和抛出异常。此外,在“堆栈”版本的算法中,您使用增加/减少堆栈大小的方法,这可能(但不是必须)导致大量内存分配/释放,这也会导致性能问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-08-17
    • 2020-06-12
    • 2013-03-10
    • 2018-05-09
    • 2021-07-08
    • 2016-08-18
    • 2014-10-14
    • 1970-01-01
    相关资源
    最近更新 更多