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