【问题标题】:Union of Sets using Dynamic Memory使用动态内存的集合并集
【发布时间】:2015-11-13 15:42:18
【问题描述】:

下面我有一段代码。我正在尝试为集合创建一个联合方法,它应该调用 element(int) 方法来检查我正在创建的新集合中的所有元素,我在这里称之为 C。我们不应该使用标准库中的联合。当我在主函数中调用 A.Union(B) 并显示它时,程序只显示我输入到 Set A 中的任何内容,但它应该返回我在我的联合函数。如何让这个函数返回我创建的新集合的所有内容,同时检查元素以确保没有元素重复?

*旁注:我完全了解我的变量名称,一旦我了解如何更正此方法,我将更改它们。我也是一个初学者,真的很想学习,所以我会很感激建设性的批评,这样我就可以知道如何改进。 //默认构造函数

Set::Set ( int s ){

        if ( s > 0 )
                psize = s;
        else
                psize = DEFAULTSIZE;
        //allocate an array of specified size
        set = new int[ psize ];

        if(!set) {
                //send an error is system cannot allocate memory
                cout << "Cannot Allocate Memory, exiting program... " << endl;
                exit (1);
        }

        for ( int i = 0; i < psize; i++){
                set[i] = 0;
                numOfElements = 0;
        }
}
bool Set::element ( int n ){
                 for ( int i = 0; i < psize; i++){
                            if ( set[i] == n )
                                    return true;
                    }
                    return false;
            }

         Set Set::Union( Set &B ){
                int newsize = B.numOfElements + numOfElements;

                Set C(newsize);

                for (int i = 0; i < numOfElements; i++){
                        C.set[i] = set[i];
                }

                int indx = 0;
                for(int i = 0; i < B.numOfElements; i ++){
                        if(C.element(B.set[i])){
                                newsize--;
                                continue;
                        }
                        else
                        {
                                C.set[indx + numOfElements] = B.set[i];
                                indx++;
                        }
                }

                C.numOfElements = newsize;
                C.display();
                return (C);
        }
        Set Set::Intersection( Set &B ) {

                int newsize = numOfElements;

                Set C(newsize);
                        for ( int i = 0; i < numOfElements; i++ ){
                                if( element(B.set[i]))
                                        C.set[i] = B.set[i];
                                else{
                                        newsize--;
                                        continue;
                                }
                        }
                return (C);
        }
   Set Set::operator-( int n ){
            for ( int i = 0; i < numOfElements; i++){
                    if(element(n)){
                            delete set[i];
                            numOfElements--;
                    }
            }
            psize = numOfElements;

            return (*this);
    }


            main (){

                    Set A, B, C;
                    A.input();
                    A.display();
                    B.input();
                    B.display();
                    C = A.Union(B);
                    C.display();
            }

【问题讨论】:

  • 能否分享您声明数据成员及其功能的structclass

标签: c++ memory dynamic operator-overloading


【解决方案1】:

Set::element 如果n 等于集合的最后一个元素,则返回false。否则返回true。这可能不是你想要的。

另外,newsize 应该是 B.psize + psize,前提是您添加了两个集合中的所有元素。但是如果某些元素同时在AB 中,那么您就不会全部添加。

另外,main 函数缺少返回类型。

当我在主函数中调用 A.Union(B) 并显示它时,程序只显示我输入到 Set A 中的任何内容

但你从不显示A.Union(B)。联合后,您拨打A.display()。它显示您输入到 Set A 中的内容一点也不奇怪。你甚至永远不会将Set::Union 返回的集合存储在变量中。

【讨论】:

  • 我认为联合循环确实是有意义的,尽管它写得很奇怪。该代码只是使用基于数组的代表,对所有内容进行线性搜索,并且两者之间可能存在间隙。该循环的逻辑如下所示,“对于 C 中的每个附加条目:对于 B 中的每个条目:如果在 C 中找不到 B 条目,则将 C 条目设置为 B 条目(基本上添加它)。”当发现某些东西时,多余的 continue 和 element 返回 false 而不是 true 真的很令人困惑。
  • @Ike 很公平,我将删除该评论。
【解决方案2】:

首先,仅此一项就可以解决眼前的问题,您的Union 方法看起来应该提供正确的结果,但它返回一个新的集合。因此,如果您想正确使用它,您需要执行以下操作:

C = A.Union(B);
C.display();

...或更简洁:

A.Union(B).display();

当你写作时:

A.Union(B);

...你正在计算联合,函数返回值,但你没有捕获它,所以它只是被扔掉了,代码基本上什么都不做(就副作用而言)。

也只是另一件小事,不会影响正确性:

bool Set::element ( int n ) {
        bool validate = true;
        for ( int i = 0; i < psize; i++){
                if ( set[i] == n )
                        validate = false;
        }
        return (validate);
}

...这部分可以简单地是:

bool Set::element ( int n ) {
        for ( int i = 0; i < psize; i++){
                if ( set[i] == n )
                        return false;
        }
        return true;
}

它的效率要高得多,因为它会在找到匹配项的那一刻退出函数,并且在找到匹配项时不会继续不必要地搜索集合的其余部分。

更重要的是,处理状态很困难。函数中的变量越多,通常就越容易出错。因此,如果您知道如何避免它,请尽量不要引入比需要更多的变量,这会使您的生活更轻松。

如果 element 函数在找到元素时返回 true 而不是 false,则可能会更容易理解,但这取决于您。

最后但并非最不重要的一点是,我强烈建议为您目前拥有的任何编译器学习调试器。如果你想要一些类似于合法“作弊”的东西,它会让你比其他学生更有优势,让你了解你的代码在每一步都在做什么以及它有什么问题,请学习调试器并学习如何跟踪您的代码并在任何给定时间查看变量的值。随着对调试器的理解,许多这些问题对您来说会立即变得显而易见,并且无需抓挠头并盯着代码直到您变得斗鸡眼(尽管这有时也是一个有用的练习)。

【讨论】:

  • 我希望这听起来不是一个愚蠢的问题,但我在哪里可以找到调试器?此外,我可以去哪里学习如何使用调试器?
  • 你编译你的代码的依据是什么?海合会?微软?铛?还有什么?你使用 IDE 还是像普通的旧文本编辑器一样?
  • 我猜你在这种情况下使用 GCC(很可能)。如果是这样,GDB 就是你的调试器 -- youtube.com/watch?v=xQ0ONbt-qPs
  • 我已经根据你的建议编辑了我的代码,但我仍然不明白,因为它仍在返回 Set A 的内容
  • 嗯——Union 方法中的逻辑似乎是合理的。我已经反复检查和三重检查,找不到任何问题(尽管我确实一直在发现element 在找到元素时返回 false 而不是 true 的部分)。我会检查一些您尚未显示的代码,例如从Union 返回C 时将调用的复制构造函数。
猜你喜欢
  • 2015-12-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-05-02
  • 2014-11-17
  • 2014-09-17
  • 2013-02-24
  • 1970-01-01
相关资源
最近更新 更多