頁:
[1]
陣列依順時針方向列印的值
輸入:n、n*n陣列的值輸出:以矩陣輸出的原陣列、陣列依順時針方向列印的值
sample input:
2
1 2 3 4
3
1 2 3 4 5 6 7 8 9
sample output:
1 2
3 4
1
2
4
3
1 2 3
4 5 6
7 8 9
1
2
3
6
9
8
7
4
5
要怎麼順時針印出?
<div></div> 本帖最後由 CoNsTaRwU 於 2016-12-14 03:03 PM 編輯
四個函式互相呼叫(或看成是遞迴):
1、向右:列印第一列,呼叫向下列印的函式
2、向下:每列最後一個,呼叫向左列印的函式
3、向左:最後一列反向,呼叫向上列印的函式
4、向上:每列第一個反向,呼叫向右列印的函式
被印過的資料就丟棄,剩餘的資料繼續傳給下一位
在陣列維度等於一的時候結束遞迴
以下虛擬碼:
top : List (List a) → List a
top (x ∷ []) = x ++ []
top (x ∷ xs) = x ++ (right xs)
right : List (List a) → List a
right (x ∷ []) = (fmap head x) ++ []
right xs = (fmap last xs) ++ (button $ fmap init xs)
button : List (List a) → List a
button (x ∷ []) = (reverse x) ++ []
button (xs) = (reverse . last xs) ++ (left . init xs)
left : List (List a) → List a
left (x ∷ []) = (fmap first xs) ++ []
left xs = (reverse (fmap first xs)) ++ (top . tail xs)
printAll : Show a ⇒ List (List a) → IO ()
printAll = print $ show . top
main : IO ()
main = printAll xs
where
xs = ...
補充內容 (2016-12-13 01:43 AM):
還要記得處理 x×2 或是 2×x 大小的陣列,會有函式不需要印東西...<div class='locked'><em>瀏覽完整內容,請先 <a href='member.php?mod=register'>註冊</a> 或 <a href='javascript:;' onclick="lsSubmit()">登入會員</a></em></div> 本帖最後由 kiwis 於 2016-12-15 01:43 PM 編輯
嗯,這個問題分析過後其實沒有想像中困難。
把輸入的資料存成二維陣列後,如何在陣列中移動而已。
圖解也已經貼出來了,就是右>下>左>上>右...直到無法再移動為止。
再來就是如何判定”無法再移動”的條件。
無法再移動也很簡單﹐就是陣列中所有的位置都已經被走過(印過)一次。
那麼就來看code要怎麼寫吧。#include <iostream>
#include <string>
#include <stdio.h>
using namespace std;
int** data=0; //保存資料的二維陣列
char** record=0; //紀錄是否已走過某個陣列位置
int array_length=0; //陣列的長及寬
// 初始化資料,將輸入轉成二維陣列
void CreateDataFromString(int length, string& array_data)
{
array_length = length;
data = new int*;
record = new char*;
char* pData = (char*) array_data.c_str();
for(int i(0); i<length; ++i)
{
data = new int;
for(int j(0); j<length; ++j)
{
char* tail = strstr(pData, " ");
if(tail)
{
tail = 0;
data = atoi(pData);
tail = ' ';
pData = tail+1;
}
else
data = atoi(pData);
}
record = new char;
memset(record, 0, length);
}
}
//釋放資源
void ClearData()
{
for(int i(0); i<array_length; ++i)
{
delete [] data;
delete [] record;
}
delete [] data;
delete [] record;
data = 0;
record = 0;
array_length = 0;
}
//自訂資料格式,座標(x, y),用來表現二維陣列的位置
typedef struct coor
{
coor(int new_x=0, int new_y=0):
x(new_x),
y(new_y)
{};
//自訂 "+" ,用來計算”下一步”的陣列位置
coor operator+(coor& rhs)
{
return coor( this->x+ rhs.x, this->y+rhs.y );
};
int x;
int y;
}_coor;
//(右、下、左、上),用來計算”下一步”
coor FourDirections = { coor(1,0), coor(0,1), coor(-1,0), coor(0,-1) };
//斷定一個座標是否為合法座標
bool IsValidCoor(coor& point)
{
if( point.x < 0 || point.x >= array_length || //x座標超出範圍
point.y < 0 || point.y >= array_length || //y座標超出範圍
record //這個座標已經被走過了
)
{
return 0;
}
return 1;
}
//順時針列印
void PrintClockWise(coor& start_point, int direction_index, int steps)
{
//這個是座標已經走過,陣列中所有資料已經都走過了
if(record)
return;
//總共走了 長度*寬度 次(陣列內的所有資料數),陣列中所有資料已經都走過了
//這兩個選一個當結束點就行了。
if(steps == array_length*array_length)
return;
//在 record 陣列中記錄下目前座標為”已走過”
record = 1;
steps++;
//列印
cout << data << endl;
//計算下一步該往哪裡走(右、下、左、上)
coor next = start_point + FourDirections;
if( IsValidCoor(next) ) //判定計算出的下一步座標位置是否為陣列中尚未走過的點
{
PrintClockWise(next, direction_index, steps); //進入下一步
}
else
{
//計算出的下一步座標為不合法座標,總之先改方向。
//(direction_index+1)%4 會產生出 0, 1, 2, 3, 0... 也就是右>下>左>上>右...
next = start_point + FourDirections[ (direction_index+1)%4 ];
PrintClockWise(next, (direction_index+1)%4, steps); //進入下一步
}
}
int main(int argc, char* argv[])
{
string input;
//讀取長寬
std::getline(std::cin, input);
int length = atoi(input.c_str());
//讀取陣列資料
std::getline(std::cin, input);
CreateDataFromString(length, input);
//列印成二維樣式
for(int i(0); i<length; i++)
{
for(int j(0); j<length; j++)
{
cout << data << " ";
}
cout << endl;
}
//順時針列印
PrintClockWise(coor(0,0), 0, 0);
//清除資源
ClearData();
return 0;
}...<div class='locked'><em>瀏覽完整內容,請先 <a href='member.php?mod=register'>註冊</a> 或 <a href='javascript:;' onclick="lsSubmit()">登入會員</a></em></div>
#include<iostream>
#define N 5
using namespace std;
int main()
{
int map;
int j, k, vx = 0, vy = 1, temp, x = 0, y = -1, flag = 1;
for(j = 0;j < N;j ++) // 給陣列值
for(k = 0;k < N;k ++)
map = j * N + k + 1;
j = N;
while(j >= 0)
{
for(k = j - 1;k >= 0;k --)
{
x += vx; //移動
y += vy;
cout<<map<<endl;
}
vx *= -1; //處理移動的向量
temp = vx;
vx = vy;
vy = temp;
if(flag == 1) //計算下一次印出的個數
j--;
flag = 1 - flag;
}
}
...<div class='locked'><em>瀏覽完整內容,請先 <a href='member.php?mod=register'>註冊</a> 或 <a href='javascript:;' onclick="lsSubmit()">登入會員</a></em></div>
頁:
[1]