C++ 如何显示collatz猜想的二叉树?

C++ 如何显示collatz猜想的二叉树?,c++,math,console,C++,Math,Console,我创建了一个程序,生成collatz猜想“树”元素的链接列表,如下所示: 我希望我的链接列表显示在终端中,如下所示: 1 | 2 | 4 | 8 | 16 | \ 32 5 | | 64 10 但我不知道如何继续 是我为生成系列而创建的代码 注: splitter是生成指向它的两个数字的数字 如果一个数字不是拆分器,它的奇数指针将为NULL 在等待@ RoryDaulton的P

我创建了一个程序,生成collatz猜想“树”元素的链接列表,如下所示:

我希望我的链接列表显示在终端中,如下所示:

  1  
  |  
  2  
  |  
  4  
  |  
  8  
  |  
 16  
  |   \  
 32    5  
  |    |  
 64   10
但我不知道如何继续

是我为生成系列而创建的代码

注:

  • splitter是生成指向它的两个数字的数字
  • 如果一个数字不是拆分器,它的奇数指针将为NULL

  • 在等待@ RoryDaulton的Python解决方案的同时,这里给出了一个基于二叉树算法创建控制台树的100%个STD C++解决方案。 步骤1-在添加
    ConsoleTree类之前,需要在现有算法中添加一些元素

    添加全局
    ndigit
    整数以自动调整 树枝

    添加一个字段
    整数以存储分支位置

    提取要显示的较大值以计算 数字

    generator()
    函数中添加图层值

    步骤2-用于管理树的编号和分支的
    ConsoleTree类

    class ConsoleTree {
    private:
        int iSize;
        string *sDigitLines;
        string *sTreeLines;
    protected:
        string FmtInt(int ival,int idigit,char cFill);
        string FmtTree(int idigit, bool bBranch);
        string ShiftRight(string& sLine, int ipos, int idigit);
    public:
        ConsoleTree(int iLimit);
        ~ConsoleTree();
        int NbDigit(int x);
        void Make(num *pTree);
        void Print();
    };
    
    // Constructor to allocate the number of lines to be displayed
    // sDigitLines array is dedicated to numbers
    // sTreeLines array is dedicated to branches
    ConsoleTree::ConsoleTree(int iLimit)
    {
        iSize = iLimit+1;
        sDigitLines = new string[iSize];
        sTreeLines = new string[iSize];
    }
    
    // delete arrays
    ConsoleTree::~ConsoleTree()
    {
        delete[] sDigitLines;
        delete[] sTreeLines;
    }
    
    // format the numbers for sDigitLines
    string ConsoleTree::FmtInt(int ival,int idigit,char cFill)
    {
        ostringstream strStream;
    
        strStream << std::setfill(cFill) << std::setw(idigit) << (ival);
        return (strStream.str());
    }
    
    // format the tree & branches for sTreeLines
    string ConsoleTree::FmtTree(int idigit, bool bBranch)
    {
        ostringstream strStream;
    
        strStream << std::string(idigit-1, ' ') << "|";
        if (bBranch) strStream << std::string(idigit-2, '-') << "\\ ";
        return (strStream.str());
    }
    
    // Shift numbers & branches when adding new branches
    string ConsoleTree::ShiftRight(string& sLine, int ipos, int idigit)
    {
        int ilen = sLine.length();
        string sTemp;
    
        sTemp = sLine.substr(0,ipos);
        if ((ilen>ipos) && (sLine[ipos]=='-')) {
            sTemp += string(idigit, '-');
        }
        else {
            sTemp += string(idigit, ' ');
        }
        if (ilen>ipos) {
            sTemp += sLine.substr(ipos,ilen);
        }
        sLine = sTemp;
        return (sLine);
    }
    
    // compute the number of digit
    int ConsoleTree::NbDigit(int x)
    {
        ostringstream stmp;
    
        stmp << x;
        return (stmp.str().length()+1);
    }
    
    // recurrent function to create tree with numbers and branches
    void ConsoleTree::Make(num *pn)
    {
        int iLevel,iLen,iCut;
        string sTemp;
    
        while (pn!=NULL) {
            iLevel = pn->layer;
            sDigitLines[iLevel] += FmtInt(pn->n,ndigit,' ');
            if (pn->odd!=NULL) {
                iCut = sTreeLines[iLevel].length()+ndigit;
                sTreeLines[iLevel] += FmtTree(ndigit,true);
                for(int i=0;i<iLevel;i++) {
                    sDigitLines[i] = ShiftRight(sDigitLines[i],iCut,ndigit);
                    sTreeLines[i] = ShiftRight(sTreeLines[i],iCut,ndigit);
                }
                sDigitLines[iLevel] = ShiftRight(sDigitLines[iLevel],iCut,ndigit);
                Make(pn->odd);
            }
            else {
                sTreeLines[iLevel] += FmtTree(ndigit,false);
            }
            pn = pn->even;
        }
    }
    
    void ConsoleTree::Print()
    {
        int iLimit = iSize -1;
    
        cout << "treeview" << endl;
        for(int i=0;i<iLimit;i++) {
            cout << sDigitLines[i] << endl;
            cout << sTreeLines[i] << endl;
        }
        cout << sDigitLines[iLimit] << endl;
    }
    
    步骤4输出样本(限值=12)

    增强功能-使用半图形扩展ASCII字符更改控制台树的外观

    ConsoleTree::FmtTree()函数中,使用一组4个扩展
    ASCII{195179&196191}

    和一个输出样本(限值=7)


    等待RoryDaulton @ Python解决方案时,这里是一个100% STD C++解决方案,基于二进制树算法创建控制台树。 步骤1-在添加

    ConsoleTree类之前,需要在现有算法中添加一些元素

    添加全局
    ndigit
    整数以自动调整 树枝

    添加一个字段
    整数以存储分支位置

    提取要显示的较大值以计算 数字

    generator()
    函数中添加图层值

    步骤2-用于管理树的编号和分支的
    ConsoleTree类

    class ConsoleTree {
    private:
        int iSize;
        string *sDigitLines;
        string *sTreeLines;
    protected:
        string FmtInt(int ival,int idigit,char cFill);
        string FmtTree(int idigit, bool bBranch);
        string ShiftRight(string& sLine, int ipos, int idigit);
    public:
        ConsoleTree(int iLimit);
        ~ConsoleTree();
        int NbDigit(int x);
        void Make(num *pTree);
        void Print();
    };
    
    // Constructor to allocate the number of lines to be displayed
    // sDigitLines array is dedicated to numbers
    // sTreeLines array is dedicated to branches
    ConsoleTree::ConsoleTree(int iLimit)
    {
        iSize = iLimit+1;
        sDigitLines = new string[iSize];
        sTreeLines = new string[iSize];
    }
    
    // delete arrays
    ConsoleTree::~ConsoleTree()
    {
        delete[] sDigitLines;
        delete[] sTreeLines;
    }
    
    // format the numbers for sDigitLines
    string ConsoleTree::FmtInt(int ival,int idigit,char cFill)
    {
        ostringstream strStream;
    
        strStream << std::setfill(cFill) << std::setw(idigit) << (ival);
        return (strStream.str());
    }
    
    // format the tree & branches for sTreeLines
    string ConsoleTree::FmtTree(int idigit, bool bBranch)
    {
        ostringstream strStream;
    
        strStream << std::string(idigit-1, ' ') << "|";
        if (bBranch) strStream << std::string(idigit-2, '-') << "\\ ";
        return (strStream.str());
    }
    
    // Shift numbers & branches when adding new branches
    string ConsoleTree::ShiftRight(string& sLine, int ipos, int idigit)
    {
        int ilen = sLine.length();
        string sTemp;
    
        sTemp = sLine.substr(0,ipos);
        if ((ilen>ipos) && (sLine[ipos]=='-')) {
            sTemp += string(idigit, '-');
        }
        else {
            sTemp += string(idigit, ' ');
        }
        if (ilen>ipos) {
            sTemp += sLine.substr(ipos,ilen);
        }
        sLine = sTemp;
        return (sLine);
    }
    
    // compute the number of digit
    int ConsoleTree::NbDigit(int x)
    {
        ostringstream stmp;
    
        stmp << x;
        return (stmp.str().length()+1);
    }
    
    // recurrent function to create tree with numbers and branches
    void ConsoleTree::Make(num *pn)
    {
        int iLevel,iLen,iCut;
        string sTemp;
    
        while (pn!=NULL) {
            iLevel = pn->layer;
            sDigitLines[iLevel] += FmtInt(pn->n,ndigit,' ');
            if (pn->odd!=NULL) {
                iCut = sTreeLines[iLevel].length()+ndigit;
                sTreeLines[iLevel] += FmtTree(ndigit,true);
                for(int i=0;i<iLevel;i++) {
                    sDigitLines[i] = ShiftRight(sDigitLines[i],iCut,ndigit);
                    sTreeLines[i] = ShiftRight(sTreeLines[i],iCut,ndigit);
                }
                sDigitLines[iLevel] = ShiftRight(sDigitLines[iLevel],iCut,ndigit);
                Make(pn->odd);
            }
            else {
                sTreeLines[iLevel] += FmtTree(ndigit,false);
            }
            pn = pn->even;
        }
    }
    
    void ConsoleTree::Print()
    {
        int iLimit = iSize -1;
    
        cout << "treeview" << endl;
        for(int i=0;i<iLimit;i++) {
            cout << sDigitLines[i] << endl;
            cout << sTreeLines[i] << endl;
        }
        cout << sDigitLines[iLimit] << endl;
    }
    
    步骤4输出样本(限值=12)

    增强功能-使用半图形扩展ASCII字符更改控制台树的外观

    ConsoleTree::FmtTree()函数中,使用一组4个扩展
    ASCII{195179&196191}

    和一个输出样本(限值=7)


    下面是将Collatz二叉树打印到控制台的Python代码。填写Collatz树的第一部分是递归的。第二次打印结构不是递归的,我对代码不满意——但它实现了我想要的。打印可以“紧排”,使一些列靠得更近,并使水平空间相同。如果希望列按示例输出中的顺序排列,请交换例程
    的大
    If
    部分中的
    ndiv3
    2*n
    参数

    这里是15行的输出,如果你切换列的顺序。模式更规则,最终占用的水平空间更少

         1
         |
         2
         |
         4
         |
         8
         |
        16
         |\___________________________________________
        32                                            5
         |                                            |
        64                                           10
         |\____________________________________       |\__________________________
       128                                     21    20                           3
         |                                      |     |                           |
       256                                     42    40                           6
         |\___________________                  |     |\____________              |
       512                    85               84    80             13           12
         |                     |                |     |              |            |
     1,024                   170              168   160             26           24
         |\________            |                |     |\_____        |            |
     2,048         341       340              336   320      53     52           48
         |           |         |\____           |     |       |      |\___        |
     4,096         682       680     113      672   640     106    104    17     96
         |\          |\        |       |        |     |\      |\     |     |      |
     8,192 1,365 1,364 227 1,360     226    1,344 1,280 213 212 35 208    34    192
         |     |     |   |     |\      |\       |     |   |   |  |   |\    |\     |
    16,384 2,730 2,728 454 2,720 453 452 75 2,688 2,560 426 424 70 416 69 68 11 384
    

    下面是将Collatz二叉树打印到控制台的Python代码。填写Collatz树的第一部分是递归的。第二次打印结构不是递归的,我对代码不满意——但它实现了我想要的。打印可以“紧排”,使一些列靠得更近,并使水平空间相同。如果希望列按示例输出中的顺序排列,请交换例程
    的大
    If
    部分中的
    ndiv3
    2*n
    参数

    这里是15行的输出,如果你切换列的顺序。模式更规则,最终占用的水平空间更少

         1
         |
         2
         |
         4
         |
         8
         |
        16
         |\___________________________________________
        32                                            5
         |                                            |
        64                                           10
         |\____________________________________       |\__________________________
       128                                     21    20                           3
         |                                      |     |                           |
       256                                     42    40                           6
         |\___________________                  |     |\____________              |
       512                    85               84    80             13           12
         |                     |                |     |              |            |
     1,024                   170              168   160             26           24
         |\________            |                |     |\_____        |            |
     2,048         341       340              336   320      53     52           48
         |           |         |\____           |     |       |      |\___        |
     4,096         682       680     113      672   640     106    104    17     96
         |\          |\        |       |        |     |\      |\     |     |      |
     8,192 1,365 1,364 227 1,360     226    1,344 1,280 213 212 35 208    34    192
         |     |     |   |     |\      |\       |     |   |   |  |   |\    |\     |
    16,384 2,730 2,728 454 2,720 453 452 75 2,688 2,560 426 424 70 416 69 68 11 384
    

    能否将提供的“树”的一部分显示为终端格式?显示的文本(如“
    Merge pull request…
    ”)与您的软件生成的数据之间的链接是什么?也就是说,我需要通过线条连接数字,这样它就可以直观地看到连接。代码可以是另一种语言,例如Python?是的,我只需要逻辑,如果可能的话,请尝试解释该代码在值
    16
    下是如何工作的,初始图形在
    32
    的左侧有分支
    5
    ,但在您的示例控制台输出中,在
    32
    的右侧有分支
    5
    。你想要哪个?这对我的代码(部分完成)有很大的影响。你能将提供的“树”的一部分显示为终端格式吗?显示的文本(如“
    Merge pull request…
    ”)与您的软件生成的数据之间的链接是什么?也就是说,我需要通过线条连接数字,这样它就可以直观地看到连接。代码可以是另一种语言,例如Python?是的,我只需要逻辑,如果可能的话,请尝试解释该代码在值
    16
    下是如何工作的,初始图形在
    32
    的左侧有分支
    5
    ,但在您的示例控制台输出中,在
    32
    的右侧有分支
    5
    。你想要哪个?这对我的代码(部分完成)有很大的影响。这对我来说是很多东西,但我会努力去理解它。。。谢谢lot@Adityaultra为了增强显示效果,我添加了一个使用半图形ASCII字符(从128到255的“English Set”)的替代解决方案。这对我来说是很多东西,但我会努力理解它。。。谢谢lot@Adityaultra为了增强显示效果,我添加了一个
    class ConsoleTree {
    private:
        int iSize;
        string *sDigitLines;
        string *sTreeLines;
    protected:
        string FmtInt(int ival,int idigit,char cFill);
        string FmtTree(int idigit, bool bBranch);
        string ShiftRight(string& sLine, int ipos, int idigit);
    public:
        ConsoleTree(int iLimit);
        ~ConsoleTree();
        int NbDigit(int x);
        void Make(num *pTree);
        void Print();
    };
    
    // Constructor to allocate the number of lines to be displayed
    // sDigitLines array is dedicated to numbers
    // sTreeLines array is dedicated to branches
    ConsoleTree::ConsoleTree(int iLimit)
    {
        iSize = iLimit+1;
        sDigitLines = new string[iSize];
        sTreeLines = new string[iSize];
    }
    
    // delete arrays
    ConsoleTree::~ConsoleTree()
    {
        delete[] sDigitLines;
        delete[] sTreeLines;
    }
    
    // format the numbers for sDigitLines
    string ConsoleTree::FmtInt(int ival,int idigit,char cFill)
    {
        ostringstream strStream;
    
        strStream << std::setfill(cFill) << std::setw(idigit) << (ival);
        return (strStream.str());
    }
    
    // format the tree & branches for sTreeLines
    string ConsoleTree::FmtTree(int idigit, bool bBranch)
    {
        ostringstream strStream;
    
        strStream << std::string(idigit-1, ' ') << "|";
        if (bBranch) strStream << std::string(idigit-2, '-') << "\\ ";
        return (strStream.str());
    }
    
    // Shift numbers & branches when adding new branches
    string ConsoleTree::ShiftRight(string& sLine, int ipos, int idigit)
    {
        int ilen = sLine.length();
        string sTemp;
    
        sTemp = sLine.substr(0,ipos);
        if ((ilen>ipos) && (sLine[ipos]=='-')) {
            sTemp += string(idigit, '-');
        }
        else {
            sTemp += string(idigit, ' ');
        }
        if (ilen>ipos) {
            sTemp += sLine.substr(ipos,ilen);
        }
        sLine = sTemp;
        return (sLine);
    }
    
    // compute the number of digit
    int ConsoleTree::NbDigit(int x)
    {
        ostringstream stmp;
    
        stmp << x;
        return (stmp.str().length()+1);
    }
    
    // recurrent function to create tree with numbers and branches
    void ConsoleTree::Make(num *pn)
    {
        int iLevel,iLen,iCut;
        string sTemp;
    
        while (pn!=NULL) {
            iLevel = pn->layer;
            sDigitLines[iLevel] += FmtInt(pn->n,ndigit,' ');
            if (pn->odd!=NULL) {
                iCut = sTreeLines[iLevel].length()+ndigit;
                sTreeLines[iLevel] += FmtTree(ndigit,true);
                for(int i=0;i<iLevel;i++) {
                    sDigitLines[i] = ShiftRight(sDigitLines[i],iCut,ndigit);
                    sTreeLines[i] = ShiftRight(sTreeLines[i],iCut,ndigit);
                }
                sDigitLines[iLevel] = ShiftRight(sDigitLines[iLevel],iCut,ndigit);
                Make(pn->odd);
            }
            else {
                sTreeLines[iLevel] += FmtTree(ndigit,false);
            }
            pn = pn->even;
        }
    }
    
    void ConsoleTree::Print()
    {
        int iLimit = iSize -1;
    
        cout << "treeview" << endl;
        for(int i=0;i<iLimit;i++) {
            cout << sDigitLines[i] << endl;
            cout << sTreeLines[i] << endl;
        }
        cout << sDigitLines[iLimit] << endl;
    }
    
    int main() {
        limit = 12; // define the height of the tree
        ndigit = 0;
    
        generator();
    
        num *pn = start; // first node of the binary-tree
    
        ConsoleTree myTree(limit);
    
        ndigit = myTree.NbDigit(ndigit);
        myTree.Make(pn);
        myTree.Print();
    
        cout << total << endl;
    
        return 0;
    }
    
        1
        |
        2
        |
        4
        |
        8
        |
       16
        |-----------------------\
        5                       32
        |                        |
       10                       64
        |---\                    |---\
        3   20                  21  128
        |    |                   |    |
        6   40                  42  256
        |    |--------\          |    |--------\
       12   13        80        84   85       512
        |    |         |         |    |         |
       24   26       160       168  170      1024
        |    |         |---\     |    |         |---\
       48   52        53  320  336  340       341 2048
        |    |---\     |    |    |    |---\     |    |
       96   17  104  106  640  672  113  680  682 4096
    
    #ifdef EXTEND_ASCII
        strStream << string(idigit-1, ' ') << string(1,((bBranch)?(195):(179)));
        if (bBranch) strStream << string(idigit-1, 196) << string(1, 191);
    #else
        strStream << std::string(idigit-1, ' ') << "|";
        if (bBranch) strStream << std::string(idigit-2, '-') << "\\ ";
    #endif
    
    #ifdef EXTEND_ASCII
        // Warning: 196 is used as unsigned char ==> cast
        if ((ilen>ipos) && ((unsigned char)sLine[ipos]==196)) {
            sTemp += string(idigit, 196);
        }
    #else
        if ((ilen>ipos) && (sLine[ipos]=='-')) {
            sTemp += string(idigit, '-');
        }
    #endif
    
       1
       │
       2
       │
       4
       │
       8
       │
      16
       ├───────┐
       5      32
       │       │
      10      64
       ├───┐   ├───┐
       3  20  21 128
    
    """Print a representation of a Collatz binary tree to the console."""
    
    # Define each column (a list) in `columns`.
    STARTROW = 0    # index of zero-based row where a column starts (int)
    WIDTH = 1       # index of char width of max number in the column so far (int)
    NUMBERS = 2     # index of the numbers in the column (list of ints)
    
    def numstr(num):
        """Return a number string, properly formatted with commas"""
        return '{:,}'.format(num)
    
    def fillnewcolumn(num, row, columns, dontuse, limit):
        """Fill a new column, starting with number `num` in row `row` of
        the partially-filled structure 'columns', not using the numbers in
        `dontuse`, up to row 'limit'."""
        dontuse.add(num)  # mark num as used
        columns.append([row, len(numstr(num)), [num]])  # top non-blank row of col
        filltherest(row, columns, dontuse, limit)  # keep going
    
    def filloldcolumn(num, row, columns, dontuse, limit):
        """Fill the old column, starting with number `num` in row `row` of
        the partially-filled structure 'columns', not using the numbers in
        `dontuse`, up to row 'limit'."""
        dontuse.add(num)  # mark num as used
        thiscolumn = columns[-1]  # last column so far
        thiscolumn[WIDTH] = max(thiscolumn[WIDTH], len(numstr(num)))
        thiscolumn[NUMBERS].append(num)  # add num to column
        filltherest(row, columns, dontuse, limit)  # keep going
    
    def filltherest(row, columns, dontuse, limit):
        """Fill the rest of the partially-filled structure 'columns' which
        already has used the numbers in `used`, from row 'row' in column
        `col`."""
        if limit <= 1:
            return
        thiscolumn = columns[-1]  # last column so far
        n = thiscolumn[NUMBERS][-1]  # last number in this column
        ndiv3, nmod3 = divmod(n, 3)
        if nmod3 == 1 and ndiv3 % 2 != 0 and ndiv3 not in dontuse:  # two branches
            filloldcolumn(ndiv3, row+1, columns, dontuse, limit-1)
            fillnewcolumn(2*n, row+1, columns, dontuse, limit-1)
        else:  # one branch from here
            filloldcolumn(2*n, row+1, columns, dontuse, limit-1)
    
    limit = int(input('How many levels of Collatz to print? '))
    
    # Fill the structure.
    columns = []            # information for the overall structure to print
    dontuse = {0}           # numbers to not add to the structure
    fillnewcolumn(1, 0, columns, dontuse, limit)
    
    # Print the structure to the console.
    for row in range(limit):
        numline = ''
        diagline = ''
        for column in columns:
            startingrow = column[STARTROW]
            numwidth = column[WIDTH]
            if startingrow <= row:
                nstr = numstr(column[NUMBERS][row-startingrow])
                numline += nstr.rjust(numwidth) + ' '
                if startingrow == row:
                    blanks = ' ' * (len(nstr) + 1)
                    oldlinesize = len(numline)
                    diagline = diagline.rstrip() + '\\'
                    dellinesize = oldlinesize - len(diagline)
                    diagline += blanks.rjust(dellinesize, '_')
                else:
                    diagline += '|'.rjust(numwidth) + ' '
            else:
                numline += ''.rjust(numwidth) + ' '
                diagline += ''.rjust(numwidth) + ' '
        if row > 0:
            print(diagline.rstrip())
        print(numline.rstrip())
    
      1
      |
      2
      |
      4
      |
      8
      |
     16
      |\___________________________________
      5                                    32
      |                                     |
     10                                    64
      |\                                    |\
      3 20                                 21 128
      |  |                                  |   |
      6 40                                 42 256
      |  |\____________                     |   |\__________________
     12 13             80                  84  85                   512
      |  |              |                   |   |                     |
     24 26            160                 168 170                 1,024
      |  |              |\____              |   |                     |\______
     48 52             53     320         336 340                   341       2,048
      |  |\___          |       |           |   |\______              |           |
     96 17    104     106     640         672 113       680         682       4,096
      |  |      |       |\      |\          |   |         |           |\          |\_
    192 34    208      35 212 213 1,280 1,344 226     1,360         227 1,364 1,365  8,192
      |  |\     |\      |   |   |     |     |   |\        |\          |     |     |      |
    384 11 68  69 416  70 424 426 2,560 2,688  75 452   453 2,720   454 2,728 2,730 16,384
    
         1
         |
         2
         |
         4
         |
         8
         |
        16
         |\___________________________________________
        32                                            5
         |                                            |
        64                                           10
         |\____________________________________       |\__________________________
       128                                     21    20                           3
         |                                      |     |                           |
       256                                     42    40                           6
         |\___________________                  |     |\____________              |
       512                    85               84    80             13           12
         |                     |                |     |              |            |
     1,024                   170              168   160             26           24
         |\________            |                |     |\_____        |            |
     2,048         341       340              336   320      53     52           48
         |           |         |\____           |     |       |      |\___        |
     4,096         682       680     113      672   640     106    104    17     96
         |\          |\        |       |        |     |\      |\     |     |      |
     8,192 1,365 1,364 227 1,360     226    1,344 1,280 213 212 35 208    34    192
         |     |     |   |     |\      |\       |     |   |   |  |   |\    |\     |
    16,384 2,730 2,728 454 2,720 453 452 75 2,688 2,560 426 424 70 416 69 68 11 384