【问题标题】:Recursive functions for partitions, stirling numbers, and chebyshev polynomials of the first第一个的分区、斯特林数和切比雪夫多项式的递归函数
【发布时间】:2014-09-22 20:18:43
【问题描述】:

所以我正在做一个家庭作业,我需要为分区、斯特林数(第一类和第二类)和第一类切比雪夫多项式创建递归函数。我的程序应该能够让用户输入一个正整数 n,然后创建名为 Partitions.txt、Stirling1.txt、Stirling2.txt 和 Chebyshev.txt 的文件,从而创建一个包含所有值 f(k,m) 的表对于 1

    #include <iostream>
    #include <vector>
    #include "OutputFile.h"

    using namespace std;
    using namespace OutputStream;


    int firstKindStirling();
    vector<vector<int> > getPartitions(int number, int maxElement);

    int main() {

        cout << "Welcome! Please input a number m:";
        int m;
        cin>>m;


        OFile fout("Partitions.txt");

        return 0;
    }

    vector<vector<int> > getPartitions(int number, int maxElement)
    {
        if (number < 1) 
            return vector<vector<int>>();

       vector<vector<int>> partitions;

        if (number <= maxElement) 
            partitions.push_back(number); //for some reason this doesn't want to work. Not sure what I'm missing here. 

        for (int i = number - maxElement; i < number; ++i)
        {
            // (recursively) get the partitions of `i`, with elements no larger than `n - i`
            auto partitionsForI = getPartitions(i, number - i);

            // add `n - i` to the front of all of those partitions
            for(vector<int>& partition : partitionsForI)
            {
                partition.insert(partition.begin(), number - i);
            }

            // add these new partitions to our list.
            partitions.insert(partitions.end(), partitionsForI.begin(), partitionsForI.end());
        }
        return partitions;
    }

    int firstKindStirling(int n, int k) 
    {
        if (n == 0 && k == 0) return 1;
        else if (n == 0 || k == 0) return 0;
        else return -(n-1) * firstKindStirling(n-1, k) + firstKindStirling(n-1, k-1);
    }

这是我的输出 .h 文件

    #ifndef OUTPUT_H
    #define OUTPUT_H

    #include <fstream>
    #include <string>
    #include <vector>
    #include <iostream>
    #include <sys/stat.h>
    #include <sstream>
    #include <memory>

    namespace OutputStream {

        class OFile {
            std::ofstream file;
        public:

            OFile(std::string filename, size_t output_precision = 10) {

                file.open(filename);
                if(file.fail()) throw std::runtime_error("Error: cannot open file");

                file.precision(output_precision);

            };

            /*
            OFile& operator<<(int x) {
                file<<x;
                return *this;
            }
            */

            /*
            OFile& operator<<(const Point2D& p) {
                file<<p;
                return *this;
            }
            */

            OFile& operator<<(const std::vector<int>& v) {

                for(auto x : v) file<<x<<std::endl;
                return *this;
            }


            template<typename T>
            OFile& operator<<(const T& p) {
                file << p;
                return *this;
            }


            ~OFile() { file.close(); };

        };


        // Strongly enumerate type
        enum class FileType { Input, Output, SafeOutput };

        // Partial Template Specialization
        template<FileType> class File;

        template<>
        class File < FileType::Input > {
        public:
            File( const std::string& filename ) : fin(filename) {

                if(fin.fail()) throw std::runtime_error("Error opening file: "+filename);
            };

            /** ...

            IFile& allows for syntax like
            fin>>a>>b>>c;
            */
            File& operator>>(int& a) {
                fin>>a;
                return *this;
            }

            /**...*/
            operator bool() {
                return !(fin.fail());
            }

            operator std::string() {
                return "Active";
            }

            // operator [data type]() {
                // code here
            //  return [object of type data type];
            // }

            friend File& getline( File& fin, std::string& line) {
                getline( fin.fin, line);
                return fin;
            }

            friend File& getrow( File& fin, std::vector<int>& rows);
            friend File& getmatrix( File& fin, std::vector< std::vector<int> >& table);

            ~File() { fin.close(); };
        private:
            std::ifstream fin;
        };  

        template<>
        class File < FileType::Output > {
            std::ofstream file;        
        public:

            File(std::string filename, size_t output_precision = 10) {

                file.open(filename);
                if(file.fail()) throw std::runtime_error("Error: cannot open file");

                file.precision(output_precision);

            };

            /*
            OFile& operator<<(int x) {
                file<<x;
                return *this;
            }
            */

            /*
            OFile& operator<<(const Point2D& p) {
                file<<p;
                return *this;
            }
            */

            File& operator<<(const std::vector<int>& v) {

                for(auto x : v) file<<x<<std::endl;
                return *this;
            }


            template<typename T>
            File& operator<<(const T& p) {
                file << p;
                return *this;
            }


            ~File() { file.close(); };

        };

    }

    #endif

【问题讨论】:

  • 您遇到了哪些问题?你了解Stirling numbersChebyshev polynomials的概念吗?您使用什么语言? “分区的递归函数”是什么意思?
  • 所以分区是指整数分区。因此,例如,如果我有一个整数 n,比如说 5。分区是总和为 5 的正整数的集合。{5}、{4,1}、{3,2}、{3,1、 1}、{2,2,1}、{2,1,1,1} 和 {1,1,1,1,1}。而且我不理解斯特林数或切比雪夫多项式的概念,但我的教授说我们不应该为了完成作业而需要。
  • 他有没有给你关于如何生成它们的说明,然后,因为如果没有,你将必须至少有一些了解......

标签: c++ recursion partitioning partition


【解决方案1】:

这真的是几个问题合而为一的,所以我会分部分回答。

分区

这可能是这些任务中最难的,但如果你分解它,它是相当可行的。

数字n的所有分区是什么?每个分区中的第一个数字必须介于 1 和 n 之间。由于我们不关心顺序,所以让我们始终保持数字降序。所以第一个分区列表看起来像这样:

  • {n}
  • {n-1, 1}
  • {n-2, 2}, {n - 2, 1, 1}
  • {n-3, 3}, {n - 3, 2, 1}, {n - 3, 1, 1, 1}
  • ...
  • {1, 1, ..., 1}

但是等等!我们可以更简单地说。这只是

  • [the set of partitions starting with n]
  • [the set of partitions starting with n - 1]
  • [the set of partitions starting with n - 2]
  • ...
  • [the set of partitions starting with 1]

对于介于 1 和 n 之间的所有 i,实际上只是所有以 n - i 开头的分区。因此,如果我们能找到一种方法来获取每个i 的每组分区,我们就可以简化事情。

我们该怎么做呢?好吧,如果我们仔细想想,我们可以很容易地得到每个以n - i 开头的分区。每个分区只是n - i,然后是一种获取数字的方法,这些数字加起来为i...这正是分区的含义,所以我们找到了递归案例!我们通过获取n - i 后跟i 的每个分区来获取所有分区。

现在我们只需要一个基本案例。这很简单:我们可以将零的分区定义为空集。

把它们放在一起

那么这是什么样的呢?

vector<vector<int>> getPartitions(int number, int maxElement)
{
    if (number < 1) return vector<vector<int>>();
    vector<vector<int>> partitions;

    if (number <= maxElement) partitions.push_back({number});

    for (int i = number - maxElement; i < number; ++i)
    {
        // (recursively) get the partitions of `i`, with elements no larger than `n - i`
        auto partitionsForI = getPartitions(i, number - i);

        // add `n - i` to the front of all of those partitions
        for(vector<int>& partition : partitionsForI)
        {
            partition.insert(partition.begin(), number - i);
        }

        // add these new partitions to our list.
        partitions.insert(partitions.end(), partitionsForI.begin(), partitionsForI.end());
    }
    return partitions;
}

斯特林数

这些非常相似。如果您查看它们各自的维基百科页面,您可以找到每种类型的重复关系:

First Kind

s1(n, k) = -(n - 1) * s1(n - 1, k) + s1(n - 1, k - 1)

Second Kind

S2(n, k) = k * S2(n - 1, k) + S2(n - 1, k - 1)

它们的基本情况相同:S(0, 0) = 1S(n, 0) = 0S(0, n) = 0

所以你可以定义一个函数来计算它们,如下所示:

int firstKindStirling(int n, int k) 
{
    if (n == 0 && k == 0) return 1;
    else if (n == 0 || k == 0) return 0;
    else return -(n-1) * firstKindStirling(n-1, k) + firstKindStirling(n-1, k-1);
}

第二类的看起来与那个非常相似。

切比雪夫多项式

这里的要求并不完全清楚。我将假设它是一次评估一个,而不是提出一些扩展的表示。它与斯特林数字几乎相同。

同样,the wikipedia page 具有递归关系:

chebyshev(0, x) = 1
chebyshev(1, x) = x
chebyshev(n, x) = 2 * x * chebyshev(n-1, x)  -  chebyshev(n-2, x)

我假设你可以弄清楚如何将它变成一个函数。 (提示:基本上只需要将这些左侧变成 if 语句,类似于上面的示例。)

【讨论】:

  • 非常感谢,这真的很有帮助。不过,Visual Studio 给我这行的错误: if (number
  • 您的编译器可能不支持初始化语法。如果是这种情况,您将需要手动构建向量。
  • 从我在书中阅读的内容来看,它应该与 push_back(number) 一起使用,因为这是我试图添加到向量末尾的值,并且 number 已经被声明。我不太明白它有什么问题......
  • 它是一个向量>。您不能直接将 int 添加到 vector> 。它周围的大括号是包含这些大括号内元素的向量的快捷方式。
  • 我觉得我的电脑讨厌我。我添加了代码,由于某种原因我无法弄清楚。
猜你喜欢
  • 1970-01-01
  • 2020-07-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-06-05
  • 1970-01-01
  • 2012-08-13
相关资源
最近更新 更多