【问题标题】:Flexible Safe Array C++灵活的安全数组 C++
【发布时间】:2015-02-07 19:11:13
【问题描述】:

我的安全数组可以保存任何类型的数据,并且可以根据需要调整大小。我要做的是,如果用户输入的数组大小小于 for 循环中的索引(在本例中为 30),它将自行调整大小。但是它太大了,所以我只有很多零。例如,如果我输入大小 15,它将使其大小为 45,这允许我存储所有数据,但我有多余的空间我不需要。我的 TA 说这对于一个好成绩来说很好,但是因为它还没有到期,所以我想要一个 resize 函数,它可以将数组的大小调整为与索引完全相同的大小,而不管用户输入的大小是多少.我不确定如何最好地做到这一点。有什么帮助吗?谢谢。

#include <iostream>
using namespace std;


template<typename Element>
class SafeArray
{
   int size;
    Element*Array;
    Element def;

public:
    SafeArray()                         //default constructor(with no parameter)
    {
        Array = new Element[size];
    size = 10;
    }
    SafeArray(int value = NULL)         //constructor with one int
    {
        Array = new Element[value];
        size = value;
    }
    ~SafeArray() { delete [] Array;};                     //destructor

      Element get(int pos)                    //get method
    { if (pos<0)
    {cout<<"error";}

        if(pos>=size)
        { set_default(def);}
        return Array[pos]; }

    void set(int pos, Element val)      //set method
    { if (pos<0)
    {
        cout<<"error";
    }
        if(pos>=size)
    { resize(3); }
        Array[pos] = val; }

    void resize(int size_mult)           //resize function
    {
            Element*temp=new Element[size*size_mult];
            for(int i = 0; i<size;i++)
            {temp[i]=Array[i];}
            delete[]Array;
            Array = temp;
            size=size*size_mult;
        }
    void set_default(Element d)        //set_default(just a safety precaution, doesn't really effect the outcome)
    {
         def=d;
    }
    //Element get_default()
   // {
   //     return def;
   // }
    int get_size()                       //get size
    {
        return size;
    }
};


int main()
{

    int N;
    cout<<"How big should the Array be?"<<endl;
    cin>>N;
    SafeArray<int> X(N);
    SafeArray<double>Y(N);
    X.set_default(-1);
    cout<<"Array is size "<<X.get_size()<<endl;

    for(int i=0; i<30;i++)

    {
        int x=i*3+1;
        double y =1000.0/x;
        X.set(i,x);
        Y.set(i,y);
    }

    for (int i = 0; i <= X.get_size(); i += 1)
        {if(i<10)
            cout <<"0"<< i << ": x = " << X.get(i) << ", 1000/x = " << Y.get(i) << "\n";
        else
        cout << i << ": x = " << X.get(i) << ", 1000/x = " << Y.get(i) << "\n";}
            cout<<"Array is size "<<X.get_size()<<endl;

    return 0;

}

【问题讨论】:

  • 我猜只是交出std::vector 的包装是作弊?肯定是技术上最好的解决方案。 :)
  • if(pos&gt;=size) { resize(3); } 不安全:如果我创建SafeArray&lt;int&gt; X(10) 然后写X.set(100, 1) 怎么办?
  • 是的,我们不允许在此类中使用 std::vector。会很好。
  • @Inspired 是的,这似乎可行,但作为分配标准的一部分,我必须在我的 SafeArray 类中有一个 resize 方法来做到这一点。另外,它仅在索引为 30 时才有效。如果我将其更改为 40,那么它只会将数组大小设置为 90
  • 通过type name(value); 创建变量不是一个好主意,因为您实际上并没有创建变量,甚至可能编译器不允许您这样做(或在您这样做时警告您)。这被称为“最令人烦恼的解析”。 C++11 引入了使用 {} 而不是 () 来初始化变量、执行此操作或查找有关如何解决该问题的信息的可能性。

标签: c++ arrays class


【解决方案1】:

有一些事情需要考虑。

  1. 您是否希望节省空间或时间复杂度?您现在设置它的方式(将当前长度乘以某个倍数)大大节省了您的时间复杂度,但正如您所指出的那样使用了一些额外的空间。通常,程序员希望尽量减少时间复杂度,但这完全取决于您的目标。

注意:我最好只乘以 2 而不是传递的倍数,因为您将获得相同的时间收益,但不会在较大的调整大小时产生这么多的空间。 (即 10,000 * 2 = 20,000 与 10,000 * 3 = 30,000 可节省 10,000 个您可能最终不需要的空间)

  1. 虽然与您的问题没有直接关系,并且可能超出了您的实验室问题的范围,但您构建它的方式类似于地图/哈希表,因为您选择的任何索引都会存储一些值,但假设您有这种情况。 SafeArray.length 为 10,并且您将一个项目放置在索引 1000 处。您将最终无法调整您当前实现的 SafeArray 的数组大小并得到一个超出范围的错误。即使您确实调整了它的大小,也会有 10 到 999 的职位全部为空,这是一种巨大的浪费,您必须记住,您在 1000 时有一些价值,中间没有任何东西。如果您打算将 SafeArray 用作真正的数据结构,那么一些关于 SafeArray 应该如何工作的额外规则/限制可能是明智的。

现在要真正回答您的问题,最好的方法是创建一个从 0 到索引的 for 循环,然后将值复制到新数组中,并使最后一条语句成为新的赋值。见下文

设置会变成:

void set(int pos, Element val)      //set method
{ if (pos<0)
{
    cout<<"error";
}
    if(pos>=size)
{ resize(pos+1); }
    Array[pos] = val; }

调整大小如下所示:

void resize(int new_size)           //resize function
{
        Element*temp=new Element[new_size];
        for(int i = 0; i<new_size;i++)
        {temp[i]=Array[i];}
        delete[]Array;
        Array = temp;
        size=new_size;
    }

编辑: 如果您不太关心空间,想要节省一些时间,并且仍然有一个安全的边界分配(有人在您的问题的 cmets 中指出),您可以将以下内容用于 Set 方法:

设置:

void set(int pos, Element val)      //set method
{ if (pos<0)
{
    cout<<"error";
}
    if(pos>=size)
{ resize((pos - size) * 2); }
    Array[pos] = val; }

这将为您提供一些额外的空间,您可以使用大于 2 的倍数在顺序情况下节省更多时间(即通过 for 循环添加)。

【讨论】:

  • 请注意,当您按顺序进入 for 循环并在每个下一步强制您执行时添加值时,我给出的答案是最小化使 SafeArray 正常工作所需的空间,但时间复杂度确实很差O(n) 调整大小。
  • 这很好用,但是如果用户输入的数字大于索引,那么它将打印大于索引的数组。即 20 将更改为 30,这很好。但是 40 将保持在 40,如果输入对于索引来说太大,我还需要它来调整大小
  • 为了回答您的问题,我希望节省空间。我只需要一个调整大小,无论输入太高或太低,它都会调整到索引大小。也感谢其他提示。我会记住他们的
  • 实际上它会按照我的想法工作。假设大小为 40,我在索引 40 处输入一个值,Set 方法将调整大小(即 if(pos>=size) { resize(pos+1); }) pos+1 = 41 使其工作并且 40 >= 40.
  • 如果您缩小尺寸,您可能会丢失以较大值存储的项目,对吗?我认为你所拥有的对于你的家庭作业来说是很好的,但是对于一个真正的数据结构,这真的需要稍微不同的定义。不过祝你在课堂上好运!这些类真的让你思考编程中的重要内容:)
猜你喜欢
  • 1970-01-01
  • 2010-10-25
  • 1970-01-01
  • 1970-01-01
  • 2020-10-12
  • 2011-03-04
  • 2022-11-04
  • 2011-06-17
  • 2014-04-27
相关资源
最近更新 更多