程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> c++實現螺旋矩陣分析總結,螺旋矩陣

c++實現螺旋矩陣分析總結,螺旋矩陣

編輯:C++入門知識

c++實現螺旋矩陣分析總結,螺旋矩陣


螺旋矩陣,是這麼一個東西:

1   2   3

8   9   4

7   6   5

這是一個,n*n的矩陣,由外向裡一次遞增,一環一環,就好像一個螺旋一樣。不難想象,如果n=5,那麼應該是這樣的:

當然,這是的一道筆試程序題,實話說,第一眼看到,還真不會做,因為,c++的數組下標無法從控制台讀入。反正就是基礎不行,看上去也很難。但是,第二天仔細一想,其實是有規律可循的,於是,就開始做了。因為比較時間有限,而且能力有限,所以有什麼更好的方法,歡迎補充。一開始的想法是比較麻煩的,就是每一條螺旋的邊,做一個循環,想法是這樣的:

1   2   3

8   9   4

7   6   5

先一最上面開始,但是仔細想這樣的想法會使得程序比較復雜,因為很明顯規律是不太完美的,代碼比較多,所以優化了一下,並且還有更多的規律。

1   2   3   4

12 13 14  5

11 16 15  6

10  9   8  7

第一個規律

如果我們把整個矩陣看成是一層一層最外環構成,那麼上面的矩陣就是這樣的:

1   2   3   4

12           5

11           6                   13  14

10  9   8  7         +        16  15

你可以畫更多的矩陣參考,這將作為最外層循環,並且,每次長度減二,這算上不錯的發現。

第二個規律

最外層循環這麼實現的話,那麼問題是我們每一個外殼,可以這麼實現,一次性從1到12,但是你很快會發現,這樣的下標將是混亂的,所以有必要在循環裡面在分循環,而我的思路是這樣的:

1   2   3                   4

                +            5          +                    +       12

                              6                                          11

                                                 9   8   7             10

這樣四步是很有規律的,我們雖然可以用四個循環實現,但是因為這四個不同區域的矩陣是同時遞增,那麼我可以讓四個矩陣同時在一個循環裡面同時賦值,很明顯,上面的這個循環是3。寫到這裡,你應該是發現了第一個規律的意義,這樣子,整個矩陣分成了完全相同的步驟,一層一層向裡面變小,每一層的賦值也得到了保證,但是問題是終結點在哪裡呢,算法的有限性。

第三個規律:

考慮到最後的終結點,你可以這麼理解,在第一個規律的基礎上,我們每一層可能依次減二,那麼就有這樣的規律,對於任意正整數n,依次減二,最後只有兩種結果,一種是完全為零,一種是為一,說白了就是偶數和奇數的兩種可能,而這兩種可能最後有什麼規律呢?我們看兩種矩陣:

 

1   2   3

 

8   9   4

 

7   6   5    

 

 和     

 

1   2   3   4

12 13 14  5

11 16 15  6

10  9   8   7

很明顯,如果是1,那麼就是2*2的小矩陣,你可以發現在這個點上,也就是第二個規律中每一條邊為1的情況,但是如果是零,那麼他是一個數,只有一個,這種情況我們有必要拿出來,因為在上面兩種情況,最後是不會出現這種可能性。還是只看我實現的代碼吧:

#include <iostream>
using namespace std;

void sparalMat(int *array[],int n)
{    
    int time = 0;
    int start = 1; //左上角起始點,做個補充,這個是每一個外殼,第一個起始點。
    while (time < n)
    {
        if (n-1-time==0)
        {
            array[time / 2][time / 2] = start;
        }
        for (int i = 0; i < n-1-time; ++i)
        {
            array[(time / 2)][time/2+i] = start + i;
            array[time / 2 + i][n - 1 - time / 2] = start + (n - time - 1) + i;
            array[n-1 - time / 2][n-1 - time / 2 - i] = start + 2 * (n - 1 - time) + i;
            array[n - 1 - time / 2 - i][time / 2] = start + 3 * (n - 1 - time) + i;
        }
        
        start += 4 * (n - 1 - time);
        time += 2;
    }
}

//主函數入口
int _tmain(int argc, _TCHAR* argv[])
{
    int ha = 0;
    cin >> ha;
    int **a = new int*[ha];
    for (int i = 0; i < ha; i++)   //這一塊僅僅是動態內存分配,與算法無關
    {
        a[i] = new int[ha];
    }
sparalMat(a, ha);
for (int i = 0; i < ha; i++) { for (int j = 0; j < ha; j++) { cout << a[i][j] << "\t"; } cout << endl; } for (int i = 0; i < ha; i++) //內存釋放,我覺得有必要釋放,即使是在程序結束時。 { delete [] a[i]; } delete[] a; return 0; }

沒錯,我決定還是相當簡潔的,我用了動態內存釋放,之前不知道,但是數組下標無法從控制台讀入,所以很麻煩,只能這麼玩。思路就是這樣。現在看看它的運行結果吧,我取

1,3,6,7,10。這五種情況:

1:

3:

6:

 

 7:

10:

 

 

最後,就是這樣,見笑了。

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved