Z字型编排问题(C++)

问题:

给定一个二维原数组,输出该数组矩阵进行Z字形编排后的内容。

原二维数组示例:

《Z字型编排问题(C++)》

输出示例:

《Z字型编排问题(C++)》

算法描述:

《Z字型编排问题(C++)》

个人思路:

    可以利用“走迷宫”算法的思路,先把所有可以移动的方向枚举出来,如下:

enum WAY{
	RIGHT,
	BOTTOM,
	LEFTBOTTOM,
	RIGHTTOP,
	NONE
} nextWay;

  然后利用状态机思想,在循环遍历原数组的内循环中,switch case一下当前应该走的方向,然后在走完之后确定一下下一步应该走哪个方向(注意一定要在确定下一步之前加判断防止越界)。仔细观察该问题可以发现该走法有以下几个特征:

1.第一步在左上角开始走。

2.导致下一步往右走的情况只可能是:

  1.     走了第一步。
  2.     从左下到右上移动了之后移动到了首行,并且非右上角(RIGHTTOP方向移动到了右上角便没办法再右移了),那么接下来应该往右。
  3.     从右上到左下方向移动之后到了左下角或者底边,接下来没办法继续左下移动了,所以只能朝RIGHT方向移动。

3.导致下一步往下走的情况只可能是:

  1.     当前进行了左下方向的移动,并且移动到了首列,这时候如果当前point非左下角的话,就应该往下移动。
  2.     当前进行了右上方向的移动,并且移动到了尾列,那么这时候便无法继续右上了,所以下一步只能往下方移动。

4.导致往左下方向移动的可能性只能是:

  1.     在首行向右移动了之后,下一步应该往坐下移动。
  2.     如果上一步就是往坐下移动的,且没有触碰到坐下边界,则下一步应该继续往左下移动。
  3.     当尾列往下方移动一步之后,下一步应该往左下移动。

5.导致往右上方向移动的可能性只能是:

  1.     在首列往下移动一步之后,应该往右上移动。
  2.     如果上一步就是右上移动,且下一步并不会达到右上角或者右边及顶边边界,那么还应该继续往右上移动。
  3.     上一步如果是在底边横向往右移动了一步,那么下一步应该往右上。

个人思路实现的完整代码如下:

#include <iostream>
#include <stdlib.h>
#include <typeinfo>
#include <memory>
#define SIZE 8
using namespace std;
void print (int** p){
	//输出
	for (int i = 0; i < SIZE; ++i){
		for (int j = 0; j < SIZE; ++j){
			cout << p[i][j] << '\t';
		}
		cout << endl;
	}
}
void init(int** p){
	for (int i = 0; i < SIZE; ++i){
		for (int j = 0; j < SIZE; ++j){
			p[i][j] = i*SIZE + j;
		}
	}
}
enum WAY{
	RIGHT,
	BOTTOM,
	LEFTBOTTOM,
	RIGHTTOP,
	NONE
} nextWay;
struct Point{
	int row;
	int clum;
};
int main(){
	int** p = new int*[8] ;
	int** nP = new int*[8];
	for (int i = 0; i < SIZE; ++i){
		p[i] = new int[8];
		memset(p[i], 0, sizeof(int)* 8);
		nP[i] = new int[8];
		memset(nP[i], 0, sizeof(int)* 8);
	}
	init(p);
	nextWay = NONE;
	Point curPos;
	cout << "原数组:" << endl;
	print(p);

	for (int i = 0; i < SIZE; ++i){
		for (int j = 0; j < SIZE; ++j){
			switch (nextWay){
			case RIGHT:
					curPos.clum += 1;
					if (curPos.row == 0){
						//首行右移
						nextWay = LEFTBOTTOM;
					}
					else{
						//底行右移
						nextWay = RIGHTTOP;
					}
				break;
			case BOTTOM:
				curPos.row += 1;
				if (curPos.clum == 0){
					//首列下移
					nextWay = RIGHTTOP;
				}
				else{
					//尾列下移
					nextWay = LEFTBOTTOM;
				}
				break;
			case LEFTBOTTOM:
				curPos.row += 1;
				curPos.clum -= 1;
				if (curPos.clum == 0){
					//如果已经左下移动到首列
					if (curPos.row == SIZE - 1){
						//如果移动到左下角
						nextWay = RIGHT;
					}
					else{
						//如果移动到左边首列但非左下角
						nextWay = BOTTOM;
					}
				}
				else{
					if (curPos.row == SIZE - 1){
						//如果移动底列
						nextWay = RIGHT;
					}
					else{
						//如果移动到非左边首列且非底列
						nextWay = LEFTBOTTOM;
					}
				}
				break;
			case RIGHTTOP:
				curPos.clum += 1;
				curPos.row -= 1;
				if (curPos.row == 0){
					//如果右上角移动已经移到了首行
					if (curPos.clum == SIZE - 1){
						//如果移动到了右上角
						nextWay = BOTTOM;
					}
					else{
						nextWay = RIGHT;
					}
				}
				else{
					if (curPos.clum == SIZE - 1){
						//如果移动到了最右列
						nextWay = BOTTOM;
					}
					else{
						nextWay = RIGHTTOP;
					}
				}
				break;
			case NONE:
				curPos.clum = 0;
				curPos.row = 0;
				if (curPos.clum + 1 < SIZE)
					nextWay = RIGHT;
				break;
			}
			nP[curPos.row][curPos.clum] = p[i][j];
		}
	}
	cout << endl << endl;
	cout << "输出该数组进行Z字形编排后的内容:" << endl;
	print(nP);
	delete[] p;
	delete[] nP;
	system("pause");
	return 0;
} 

注意事项:  主要是在进行下一步走法的确定时,一定要严格检查是否已经达到边界,因为如果达到了边界,则下一步的方向可能发生改变。

    原文作者:Z字形编排问题
    原文地址: https://blog.csdn.net/csjapan/article/details/79359942
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞