C++程序设计趣题:递归

目录

例题一 “The Sierpinski Fractal”
例题二 “文件结构“图””


例题一 “The Sierpinski Fractal”

【描述】
考虑一个规则的三角形区域,将其划分为四个相等的一半高度的三角形,然后将中间的三角形去除。对剩余的三个三角形中的每个递归地应用相同的操作。如果无限次重复此过程,则将获得面积为零的东西。以这种方式演化的分形称为Sierpinski三角形。尽管其拓扑维数为2,但其Hausdorff-Besicovitch维数为log(3)/ log(2)〜1.58,是一个分数值(这就是为什么它称为分形)。顺便说一下,挪威海岸的Hausdorff-Besicovitch维度约为1.52,其拓扑维度为1。

对于此问题,您将仅使用ASCII字符将Sierpinski三角形的轮廓绘制到一定的递归深度。由于绘图分辨率是固定的,因此您需要适当地放大图片。用两个斜杠绘制最小的三角形(不再进一步划分),以反斜杠和两个下划线表示,如下所示:

 /\
/__\

要查看如何绘制更大的三角形,请看一下示例输出。

【输入】
输入包含几个测试用例。每个由整数n指定。输入以n = 0终止。否则,1 <= n <= 10表示递归深度。
【输出】
为每个测试用例绘制一个Sierpinski三角形的轮廓,其侧面的总长度为2 n个字符。将您的输出向左对齐,即,将最左下的斜线打印到第一列中。输出中不得包含任何尾随空白。在每个测试用例之后打印一个空行。
【样例输入】

3 
2 
1 
0

【样例输出】

       /\
      /__\
     /\  /\
    /__\/__\
   /\      /\
  /__\    /__\
 /\  /\  /\  /\
/__\/__\/__\/__\

   /\
  /__\
 /\  /\
/__\/__\

 /\
/__\

【来源】OJ
【解】

#include <iostream>
#include <cstring>
using namespace std;

void drawL1();//画第一层, 不转行
void drawL2();//画第二层, 不转行
void myDraw(int layer,//级数
			int lines_in_layer//第几层,从1开始
);//画出指定级数的图形的指定层,不考虑行前空格和行后换行

void finaldraw(int layer);//包装

int n;
int main() {
	while(cin >> n) {
		finaldraw(n);
		cout << '\n';
	}
	cin >> n;
}

void drawL1()
{
	printf("/\\"); return;
}

void drawL2()
{
	printf("/__\\"); return;
}

void myDraw(int layer, int lines_in_layer)
{
	if(layer == 0)return;
	else if(layer == 1 && lines_in_layer == 1)drawL1();
	else if(layer == 1 && lines_in_layer == 2)drawL2();
	else {
		if(lines_in_layer <= (1 << (layer-1))) {
			myDraw(layer - 1, lines_in_layer);
		}//上半部分
		else {
			myDraw(layer - 1, lines_in_layer - (1 << (layer - 1)));
			for(int BLANK = 0; BLANK < (((1<<layer)-lines_in_layer)<<1);++BLANK)printf(" ");
			myDraw(layer - 1, lines_in_layer - (1 << (layer - 1)));
		}//下半部分 中间空格
		return;
	}
	return;
}

void finaldraw(int layer)
{
	for(int i = 1; i <= (1 << layer); ++i) { 
		//前方空格
		for(int countBlank = 0; countBlank < (1 << layer) - i; ++countBlank)printf(" ");
		myDraw(layer, i); 
		printf("\n");
	}
	return;
}

【说明】应恰当地选取可递归的部分。


例题二 “文件结构“图””

【描述】
在计算机上看到文件系统的结构通常很有用。Microsoft Windows上面的"explorer"程序就是这样的一个例子。但是在有图形界面之前,没有图形化的表示方法的,那时候最好的方式是把目录和文件的结构显示成一个"图"的样子,而且使用缩排的形式来表示目录的结构。比如:

ROOT
|     dir1
|     file1
|     file2
|     file3
|     dir2
|     dir3
|     file1
file1
file2

这个图说明:ROOT目录包括三个子目录和两个文件。第一个子目录包含3个文件,第二个子目录是空的,第三个子目录包含一个文件。

【输入】
你的任务是写一个程序读取一些测试数据。每组测试数据表示一个计算机的文件结构。每组测试数据以’*‘结尾,而所有合理的输入数据以’#‘结尾。一组测试数据包括一些文件和目录的名字(虽然在输入中我们没有给出,但是我们总假设ROOT目录是最外层的目录)。在输入中,以’]‘表示一个目录的内容的结束。目录名字的第一个字母是’d’,文件名字的第一个字母是’f’。文件名可能有扩展名也可能没有(比如fmyfile.datfmyfile)。文件和目录的名字中都不包括空格,长度都不超过30。一个目录下的子目录个数和文件个数之和不超过30。
【输出】
在显示一个目录中内容的时候,先显示其中的子目录(如果有的话),然后再显示文件(如果有的话)。文件要求按照名字的字母表的顺序显示(目录不用按照名字的字母表顺序显示,只需要按照目录出现的先后显示)。对每一组测试数据,我们要先输出"DATA SET x:",这里x是测试数据的编号(从1开始)。在两组测试数据之间要输出一个空行来隔开。

你需要注意的是,我们使用一个’|'和5个空格来表示出缩排的层次。
样例输入

file1
file2
dir3
dir2
file1
file2
]
]
file4
dir1
]
file3
*
file2
file1
*
#

【样例输出】

DATA SET 1:
ROOT
|     dir3
|     |     dir2
|     |     file1
|     |     file2
|     dir1
file1
file2
file3
file4

DATA SET 2:
ROOT
file1
file2

【提示】
一个目录和它的子目录处于不同的层次
一个目录和它的里面的文件处于同一层次
【来源】OJ
【解】

#include<iostream>
#include<string>
#include<vector>
#include<algorithm>
//#include<fstream>
using namespace std;

//ofstream fout("D:\\out.txt", ios::trunc);
int display(int layer, string headname="ROOT");//第0层是ROOT

int main() {
	//if(!fout) { cerr << "Open Failed.\n"; system("pause"); return 0; }

	int count = 1;
	bool is_end = false;
	while(!is_end) {
		cout << "DATA SET " << count << ":\n";
		//fout << "DATA SET " << count << ":\n";//
		int s=display(0);
		if(s == -1) {
			//cout << "END success.\n";
			is_end = true; break; 
		}
		printf("\n"); //fout << endl;
		++count;
	}
	//fout.close();//
	//int n; cin >> n;
}

int display(int layer, string headname)
{
	string temp; vector<string> tempL;
	//先输出子目录
	for(int HEAD = 0; HEAD < layer; ++HEAD) {
		cout << "|     "; //fout << "|     ";
	}
	cout << headname << endl; //fout << headname << endl;

	while(true) {
		cin >> temp;
		if(temp[0] == '*') { break; }
		if(temp[0] == 'd')display(layer + 1, temp);
		else if(temp[0] == 'f')tempL.push_back(temp);
		else if(temp[0] == ']')break;
	}

	sort(tempL.begin(), tempL.end());//正常排序
	
	for(vector<string>::iterator i = tempL.begin(); i != tempL.end(); ++i) {
		for(int HEAD = 0; HEAD < layer; ++HEAD) {
			cout << "|     "; //fout << "|     ";
		}
		cout << *i << endl; //fout << *i << endl;
	}

	if(layer == 0) { //判断是否结束: 看下一个是否为'#'
		char c = 0;
		getchar();//去掉'\n'
		c = cin.peek();
		if(c == '#')return -1;
	}
	return 0;
}

【注】应当恰当选取递归的部分。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值