排版——螺旋打印
来源:互联网 发布:企业it 运维 知乎 编辑:程序博客网 时间:2024/05/17 22:11
题目描述:
给定一个自然数n,打印1-n之间所有的数,要求:按螺旋形状顺时针打印。
由内而外的打印
分析
最简单且直观的方法就是k * k的二维数组存储数字,先将数字按照要求填入数组,然后输出整个数组即可
分配数组
对于n个数而言,令k = Ceil(sqrt(n)), 则分配k*k的二维数组即可。比如n = 5时,分配3*3的数组即可。
如何填数
起始点
以左上角为起始点方向
用一个整数flag来标识方向
flag = 1 - 向右
flag = 2 - 向下
flag = 3 - 向左
flag = 4 - 向上边界判断
当到达边界的时候应该变换方向,即向右转,如何判断边界?我的方法是,将所有数组元素初始化为-1,则有如下两种情况
1.下标超出二维数组边界,则需转向(注意,转向之前下标需要退回一格)
2.下标未越界,但下一个位置的值不是-1,那么说明它被填充过,也需转向。填充
重复以下过程直到所有数据填充完毕。
- 从左至右填充数组,如遇右边界或者下一位置已经被填充过,则改变方向,转入步骤2
- 从上至下填充数组,如遇下边界或者下一位置已经被填充过,则改变方向,转入步骤3
- 从右至左填充数组,如遇左边界或者下一位置已经被填充过,则改变方向,转入步骤4
- 从下至上填充数组,如遇上边界或者下一位置已经被填充过,则改变方向,转入步骤1
代码实现:
#include <iostream>#include <iomanip>using namespace std;//从外向内螺旋打印numvoid SpiralPrint1(int num){ //计算二维数组的维数k int k = ceil(sqrt(num)); //ceil()向上取整 //动态分配一个二维数组 int **a = new int*[k]; for (int i = 0; i < k; i++) { a[i] = new int[k]; } //初始化动态分配的二维数组 for (int i = 0; i < k; i++) for (int j = 0; j < k; j++) a[i][j] = -1; int i = 0, j = 0; a[i][j] = 1;// 用一个整数flag来标识方向// flag -> 1 向右(j++) | flag -> 2 向下(i++) | flag -> 3 向左(j--) | flag -> 向上(i--) int flag = 1; int m = 1; while (a[i][j] < num) { m++; if (flag == 1) { j++; if (j >= k || a[i][j] != -1) { j--; flag = 2; } } if (flag == 2) { i++; if (i >= k || a[i][j] != -1) { i--; flag = 3; } } if (flag == 3) { j--; if (j <= -1 || a[i][j] != -1) { j++; flag = 4; } } if (flag == 4) { i--; if (a[i][j] != -1 || i <= -1) { i++; flag = 1; j++; if (j >= k || a[i][j] != -1) { j--; } } } a[i][j] = m; } for (int i = 0; i < k; i++) { for (int j = 0; j < k; j++) cout << right << setw(5) << a[i][j] << " "; cout << endl; }}int main(){ SpiralPrint1(25); system("pause"); return 0;}
由内而外的打印
起始位置
由于是从内向外填充,所以起始位置不再是(0, 0),需要重新计算,而且还与二维数组的阶数k的奇偶性相关
1 当k为奇数时,起始位置为(k / 2, k / 2),如下:
2 当k为偶数时,起始位置为(k / 2 - 1, k / 2 - 1),如下:边界判断
与从外向内填充不同的是,边界判断中不会再出现下标越界的情况,只需判断当前位置是否填充过即可
方向转换
从内向外填充时,能转向时优先转向,不能转向时才继续向前填充,而从外向内填充则恰恰相反,无法继续向前填充时才转向
代码实现:
#include <iostream>#include <iomanip>using namespace std;void SpiralPrint2(int num){ //计算二维数组的维数k int k = ceil(sqrt(num)); //动态分配一个二维数组 int **a = new int*[k]; for (int i = 0; i < k; i++) { a[i] = new int[k]; } //初始化动态分配的二维数组 for (int i = 0; i < k; i++) for (int j = 0; j < k; j++) a[i][j] = -1; int i, j; if (k % 2 == 0) i = j = k / 2 - 1; else i = j = k / 2; a[i][j] = 1; int m = 1; int flag = 1; while (m < num) { m++; if (flag == 1) { j++; if (a[i][j] == -1) { a[i][j] = m; flag = 2; } else { j--; i--; if (a[i][j] == -1) { a[i][j] = m; flag = 1; } } } else if (flag == 2) { i++; if (a[i][j] == -1) { a[i][j] = m; flag = 3; } else { i--; j++; if (a[i][j] == -1) { a[i][j] = m; flag = 2; } } } else if (flag == 3) { j--; if (a[i][j] == -1) { a[i][j] = m; flag = 4; } else { j++; i++; if (a[i][j] == -1) { a[i][j] = m; flag = 3; } } } else if (flag == 4) { i--; if (a[i][j] == -1) { a[i][j] = m; flag = 1; } else { i++; j--; if (a[i][j] == -1) { a[i][j] = m; flag = 4; } } } } for (int i = 0; i < k; i++) { for (int j = 0; j < k; j++) { cout << right << setw(5) << a[i][j] << " "; } cout << endl; }}int main(){ SpiralPrint1(25); system("pause"); return 0;}
题目描述:
把一个个大小差一圈的框叠起来,使得从上往下看时,边框花色交错,这个工作现在要让计算机来完成
输入:
输入时一个个的三元组,分别是,外框尺寸n(n为满足0
输出:
输出叠在一起的框案,中心花色和外框花色字符从内层起交错相叠,多狂想叠时,最外框的角总是被打磨掉。叠框和叠框之间一行间隙
样例输入:
5 @ w
样例输出:
@ @ @@ w w w @@ w @ w @@ w w w @ @ @ @
样例输入:
11 B A
样例输出:
A A A A A A A A AA B B B B B B B B B AA B A A A A A A A B AA B A B B B B B A B AA B A B A A A B A B AA B A B A B A B A B AA B A B A A A B A B AA B A B B B B B A B AA B A A A A A A A B AA B B B B B B B B B A A A A A A A A A A
思想关键:按照由最内圈至最外圈的顺序来完成图形的排序。在完成每圈打印时,注意两个要点:首先需要确定最上角的坐标。我们将以这个坐标作为参照点来完成该圈的其他位置上的字符位置的确定
代码实现
#include <iostream>#include <iomanip>using namespace std;int main(){ int n; char a, b; while (cin >> n >> a >> b) { //动态创建一个二维数组用于存储数据 char **output = new char*[n]; for (int i = 0; i < n; i++) { output[i] = new char[n]; } int k = n / 2; output[k][k] = a; for (int i = 1; i <= n / 2; i++) { char c; if (i % 2 == 0) c = a; else c = b; for (int j = 0; j < 2 * i + 1; j++) { output[k - i][k - i + j] = c; //上面一行的字符确定 output[k - i + j][k - i] = c; //左边一列的字符确定 output[k + i - j][k + i] = c; //右边一列的字符确定 output[k + i][k + i - j] = c; //下边一行的字符确定 } } if (n != 1) { output[0][0] = ' '; output[n - 1][0] = ' '; output[0][n - 1] = ' '; output[n - 1][n - 1] = ' '; } for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) cout << setw(3) << output[i][j] << " "; cout << endl; } } system("pause"); return 0;}
本文参考:
http://www.cnblogs.com/graphics/archive/2010/06/05/1739658.html
- 排版——螺旋打印
- 黑马程序员——用二维数组打印螺旋方阵和螺旋矩阵
- 每日一题(3)——打印螺旋矩阵(queue)
- 黑马程序员——螺旋方阵的打印
- 螺旋打印
- 螺旋打印
- 出版物排版软件——对XML数据进行排版、浏览、转换、打印
- 出版物排版软件——对XML数据进行排版、浏览、转换、打印
- 螺旋矩阵2——顺时针打印任意大小的矩阵
- 黑马程序员——今天在黑马论坛看到有人问打印螺旋矩阵的题目
- 打印逆向螺旋数
- 螺旋矩阵的打印
- 打印螺旋矩阵
- 打印一个螺旋图
- 打印螺旋矩阵
- 打印螺旋数列
- 打印螺旋矩阵
- 数组螺旋打印
- Java中List集合的遍历
- Java JDBC 之 Statement
- 总结今天实现Topbar随屏幕滚动逐渐出现和淡出问题
- Html 链接
- ZigZag Conversion
- 排版——螺旋打印
- 一个月实验室网站和PMS系统、邮件系统、FTP服务器搭建
- 初识Java多线程编程
- 线程的生命周期
- Oracle分页以及与MySql的比较
- SQL--JOIN之完全用法
- 线程的优先级
- ListView加载两种Item样式问题总结
- ionic之AngularJS扩展动态组件