查看完整版本: 陣列依順時針方向列印的值
頁: [1]

不要唸我的名子 發表於 2016-12-12 06:43 PM

陣列依順時針方向列印的值

輸入: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-13 01:32 AM

本帖最後由 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:20 PM

本帖最後由 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 發表於 2016-12-19 09:22 AM


#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]