JavaRush /בלוג Java /Random-HE /מערכים רב מימדיים

מערכים רב מימדיים

פורסם בקבוצה
מערכים רב מימדיים - 1

מהו מערך ג'אווה חד מימדי?

מערך הוא קבוצה מסודרת של אלמנטים מאותו סוג, פרימיטיבי או הפניה. מידע כללי על מערכים (בעיקר חד מימדיים) ניתן למצוא במאמר " מערכים ב-Java " ובקורס JavaRush . במאמר זה נדבר על מערכים שהאלמנטים שלהם הם מערכים אחרים. מערכים כאלה נקראים רב מימדיים. מערך שהאלמנטים שלו הם מערכים אחרים, כלומר מערך של מערכים, נקרא דו מימדי. לא לכל השפות יש מערכים רב מימדיים המובנים כך, אבל ב-Java זה המצב.

מערכים רב מימדיים של Java, תחביר כללי

באופן כללי, מערכים רב-ממדיים ב-Java נראים כך:
Data_type[dimension1][dimension2][]..[dimensionN] array_name = new data_type[size1][size2].[sizeN];
איפה Data_typeסוג האלמנטים במערך. יכול להיות פרימיטיבי או התייחסות (מחלקה). מספר זוגות הסוגריים dimensionבפנים הוא הממד של המערך (במקרה שלנו - N). array_name— שם מערך size1...sizN— מספר האלמנטים בכל מימד של המערך. הכרזה על מערכים רב מימדיים:
int[][] twoDimArray; //two-dimensional array
String[][][] threeDimArray; //three-dimensional array
double[][][][][] fiveDimArray; // five-dimensional array
אולי כל זה נראה מאוד מופשט, אז עכשיו בואו נעבור לביטויים הקונקרטיים של מערכים רב מימדיים - דו מימדיים ותלת מימדיים. העובדה היא שמפתחי ג'אווה משתמשים לפעמים במערכים דו מימדיים, הרבה פחות - תלת מימדיים, ואפילו מערכים גדולים יותר הם נדירים ביותר. יש סבירות גבוהה שלא תתקלו בהם.

מערכים רב מימדיים בקורס JavaRush

ב-JavaRush, מערכים "רגילים" מתחילים ברמה 7 של קווסט Java Syntax , ובהמשך הקורס נתקלים בהם יותר מפעם אחת. לפעמים במהלך הקורס נתקלים בבעיות המערבות מערכים דו מימדיים (או כאלה שניתן לפתור בעזרתם). מערכים דו מימדיים משמשים גם במנוע המשחק של החלק המיוחד " משחקים ב-JavaRush ". אם עדיין לא הייתם שם, תסתכלו וצרו משחק או שניים. התנאים וההגבלות מגיעים עם הוראות מפורטות ויספקו הכשרה מצוינת במיומנויות תכנות. את המערך התלת מימדי ניתן למצוא במשחק Space Invaders . באמצעותו מצוין סט פריימים לאנימציה (וכל אחת מהפריימים הללו הוא מערך דו מימדי). אם כבר השלמת את קווסט JavaSyntax או סתם מרגיש בטוח בתכנות Java, נסה לכתוב גרסה משלך למשחק הקלאסי הזה.

מהו מערך ג'אווה דו מימדי?

מערך דו מימדי ב-Java הוא מערך של מערכים, כלומר כל תא מכיל הפניה למערך. אבל הרבה יותר קל להציג את זה בצורה של טבלה שיש בה מספר נתון של שורות (מימד ראשון) ומספר עמודות (מימד שני). מערך דו מימדי שבו לכל השורות יש מספר שווה של אלמנטים נקרא מלבני.

הכרזה, יצירה ואתחול של מערכים דו מימדיים

ההליך להכרזה ויצירת מערך דו מימדי כמעט זהה למקרה של מערך חד מימדי:
int[][] twoDimArray = new int[3][4];
למערך זה 3 שורות ו-4 עמודות. גודלו של מערך דו-ממדי מלבני (ייתכן שהם אינם מלבניים, עוד על כך בהמשך), כלומר, ניתן לקבוע את המספר הכולל של האלמנטים על ידי הכפלת מספר השורות במספר העמודות. כעת הוא מאותחל (מולא) בערכי ברירת מחדל. כלומר אפסים. בואו נמלא אותו בערכים שאנחנו צריכים.
twoDimArray[0][0] = 5;//write the value 5 into the cell at the intersection of the zero row and zero column
twoDimArray[0][1] = 7; //write the value 7 into the cell at the intersection of the zero row and the first column
twoDimArray[0][2]  = 3;
twoDimArray[0][3] = 17;
twoDimArray[1][0] = 7;
twoDimArray[1][1] = 0;
twoDimArray[1][2] = 1;
twoDimArray[1][3] = 12;
twoDimArray[2][0] = 8;
twoDimArray[2][1] = 1;
twoDimArray[2][2] = 2;
twoDimArray[2][3] = 3;
כמו עם מערכים חד מימדיים, אתה יכול לבצע את הליך האתחול מהר יותר:
int [][] twoDimArray = {{5,7,3,17}, {7,0,1,12}, {8,1,2,3}};
בשני המקרים, נקבל מערך דו מימדי עם שלוש שורות וארבע עמודות, מלא במספרים שלמים. מערכים רב מימדיים - 2

הצגת מערך דו מימדי על המסך

הדרך ההגיונית ביותר לבצע פעולה זו היא תחילה פלט את אלמנט קו האפס אחר אלמנט, לאחר מכן את השני וכן הלאה. הדרך הנפוצה ביותר לפלט מערך דו מימדי ב-Java היא להשתמש בשתי לולאות מקוננות.
int [][] twoDimArray = {{5,7,3,17}, {7,0,1,12}, {8,1,2,3}};//declared an array and filled it with elements
for (int i = 0; i < 3; i++) {  //go through the lines
            for (int j = 0; j < 4; j++) {//go through the columns
                System.out.print(" " + twoDimArray[i][j] + " "); //output element
            }
            System.out.println();// line wrap for the visual preservation of the tabular form
        }

פלט מהיר של מערך דו מימדי

הדרך הקצרה ביותר להציג רשימה של אלמנטים של מערך דו מימדי על המסך היא להשתמש בשיטת deepToStringהמחלקה Arrays. דוגמא:
int[][] myArray = {{18,28,18},{28,45,90},{45,3,14}};
System.out.printLn(Arrays.deepToString(myArray));
התוצאה של התוכנית היא הפלט הבא: [[18, 28, 18], [28, 45, 90], [45, 3, 14]]

"אורכים" של מערך דו מימדי

כדי לקבל את האורך של מערך חד-ממדי (כלומר, מספר האלמנטים בו), ניתן להשתמש במשתנה length. כלומר, אם נגדיר מערך int a[] = {1,2,3}, אז הפעולה a.lengthמחזירה 3. אבל מה אם נחיל את אותו הליך על המערך הדו-ממדי שלנו?
int [][] twoDimArray = {{5,7,3,17}, {7,0,1,12}, {8,1,2,3}};
System.out.println(twoDimArray.length);
פלט: 3 אז פעולה זו מוציאה את מספר השורות במערך. איך מקבלים את מספר העמודות? אם עסקינן במערכים דו-ממדיים מלבניים (כלומר כאלו שכל הקווים באורך זהה), אז נוכל ליישם את הפעולה twoDimArray[0].lengthאו במקום אלמנט האפס (בעצם קו האפס) - כל אחד אחר קיים. אנחנו יכולים לעשות זאת מכיוון שב-Java, מערך דו מימדי הוא מערך של מערכים, ואלמנט אפס twoDimArray[0]הוא מערך באורך 4. אתה יכול לבדוק זאת בעצמך.

דוגמה לשימוש במערך דו מימדי: לוח דמקה

ניתן להשתמש במערכים דו-ממדיים ליצירת כל שדה דו-ממדי סופי, למשל במשחקים, ובפרט בשחמט. קל לחשוב על לוח שחמט כמערך דו מימדי. אתה יכול "לצרף" גרפיקה לזה, אבל לעת עתה, בואו נגדיר לוח שחמט באמצעות סמלים ונוציא אותו לקונסולה. מערכים רב מימדיים - 3הריבוע השמאלי התחתון של לוח השחמט צבוע בשחור, השני לבן, וכך גם זה שמעליו. אז הצבע משתנה בכל פעם שאתה עובר לתא הסמוך לצד. כדי להגדיר את צביעת השחמט לא ידנית, אלא באמצעות אלגוריתם, אתה יכול להשתמש בבדיקת זוגיות: אם הסכום של אינדקס השורה והעמודה הוא זוגי או אפס, התא יהיה לבן, אחרת הוא יהיה שחור. לבדיקה זו, אנו משתמשים באופרטור השאר % באלגוריתם. מכיוון שאנו עובדים לא עם גרפיקה, אלא עם סמלים, נסמן את התא הלבן באות W(לבן), ואת התא השחור באות B(שחור).
//set the chessboard as a two-dimensional array
String [][] chessBoard = new String[8][8];
        for (int i = 0; i< chessBoard.length; i++) {
            for (int j = 0; j < chessBoard[0].length; j++) {
                if ((i + j) % 2 == 0) chessBoard[i][j] = "W";
                else chessBoard[i][j] = "B";
            }
        }
הפלט של התוכנית הוא כדלקמן: WBWBWBWBBWBWBWBWWBWBW BWBBWBWBWBWWBWBWBWBBW BWBWBWWBWBWBWBBWBWBWB W הכל כמו על לוח שחמט אמיתי, אתה יכול לבדוק את זה. מערכים רב מימדיים - 4כעת נכתוב שיטה למספור נכון של תאים לא בשפת מערך, אלא בשפת "שחמט". התא השמאלי התחתון בלוח נקרא A1, ואילו במערך שלנו הוא chessBoard[7][0]. הבה נקשר כל זוג מדדים של מערך דו מימדי עם המקבילה "שחמט" שלהם. לשם כך, אנו משתמשים בשתי שורות - " abcdefgh" ו" 87654321" (בסדר הפוך - לשם הפשטות, כך שלוח השחמט 8 מתאים לעמודת האפס).
public static String chessBoardCoord(int a, int b) {
            String letters = "abcdefgh";
            String numbers = "87654321";
            if ((a > 7)|| (b>7)) return null; //if the number is outside the board, return the default value - null
            else return (Character.toString(letters.charAt(a)) + numbers.charAt(b)); /*charAt - a method with which we extract from the string the element under the passed number, here - under the numbers a and b. Character.toString - a method that converts the received character into a string */
        }
כעת נציג בכל תא לא רק את הצבע שלו, אלא גם את מספרו, באמצעות השיטהchessBoardCoord
String [][] chessBoard = new String[8][8];
        for (int i = 0; i < chessBoard.length; i++) {
            for (int j = 0; j < chessBoard[0].length; j++) {
                if ((i + j) % 2 == 0) chessBoard[i][j] = "W" + chessBoardCoord(j,i);
                else chessBoard[i][j] = "B"+ chessBoardCoord(j,i);
            }
        }

            for (int i = 0; i < chessBoard.length; i++) {
                for (int j = 0; j < chessBoard[0].length; j++) {
                    System.out.print(" " + chessBoard[i][j] + " ");
                }
                System.out.println();
            }
פלט תוכנית: Wa8 Bb8 Wc8 Bd8 We8 Bf8 Wg8 Bh8 Ba7 Wb7 Bc7 Wd7 Be7 Wf7 Bg7 Wh7 Wa6 Bb6 Wc6 Bd6 We6 Bf6 Wg6 Bh6 Ba5 Wb5 Bc5 Wd5 Be5 Wf5 Bg5 Wh5 Wa4 Bb4 Wf Bc4 Wf 3 Be3 Wf3 Bg3 Wh3 Wa2 Bb2 Wc2 Bd2 We2 Bf2 Wg2 Bh2 Ba1 Wb1 Bc1 Wd1 Be1 Wf1 Bg1 Wh1 איפה We2פירושו הריבוע הלבן שמספרו e2.

דוגמה לשימוש במערך דו מימדי: כפל מטריצה

תשומת הלב!דוגמה זו דורשת ידע בסיסי במטריצות. כאן ייאמר עליהם מעט מאוד, והמידע הזה מיועד למי שלמד, אבל קצת שכח, חשבון מטריצת. עם זאת, ניתן ללקט את הידע הזה ממקורות פתוחים, במיוחד ממאמר בוויקיפדיה . זו דוגמה טובה לשימוש במערכים דו מימדיים, אבל אנחנו יכולים להמשיך הלאה בלעדיה. אז אם זה נראה לכם לא מובן עכשיו מנקודת מבט מתמטית, ואתם לא ממש רוצים להתעמק בזה, אתם מוזמנים לדלג על הדוגמה. אם למדת אלגברה לינארית בסיסית, ייתכן שלמדת על מערכים מלבניים כמטריצות מלבניות. מערכים רב מימדיים - 5כאשר a11, a12... aNN הם כמה מספרים. באיור, המטריצה ​​היא אפילו לא מלבנית, אלא ריבועית (מספר השורות שווה למספר העמודות, אבל זה לא תמיד המקרה). בחיים האמיתיים, לעתים רחוקות נתקלים במטריצות כאלה, אבל בתכנות ובמדעי המחשב הן נפוצות מאוד. בפרט, הם משמשים בגרפיקה ממוחשבת ובמנועי משחק. לדוגמה, ניתן לתכנת סיבוב של אובייקט על המסך לכל זווית באמצעות מטריצת סיבוב. במרחב דו מימדי, מטריצת הסיבוב נראית כך: מערכים רב מימדיים - 6כאשר תטא היא הזווית שדרכה צריך לסובב את האובייקט. ניתן להוסיף מטריצות בעלות מידות שוות אחת לשנייה, והחיבור מתרחש אלמנט אחר אלמנט (אנו מוסיפים אלמנטים עם אותם מדדים). אבל פעולת הכפל המטריצה ​​פחות מוכרת. לפיכך, ניתן להכפיל מטריצות ולקבל מטריצה ​​המתקבלת רק אם מספר העמודות של המטריצה ​​הראשונה עולה בקנה אחד עם מספר השורות של השנייה. למטריצת התוצאה תהיה אותו מספר שורות כמו הראשונה ואותו מספר עמודות כמו השנייה. הכפל מתבצע באופן הבא. תן לנו מטריצה a[l][m]​​ו b[m][n]. כתוצאה מהכפל שלהם, עלינו לקבל מטריצה c[l][n]​​. כדי לקבל אלמנט של c[0][0]מטריצת מוצר, עליך a[0][0]להכפיל את אלמנט האפס של שורת האפס של המטריצה ​​הראשונה באלמנט האפס של המטריצה ​​השנייה, ולאחר מכן להכפיל את האלמנט הראשון של השורה הראשונה של המטריצה ​​הראשונה באלמנט הראשון של העמודה הראשונה של המטריצה ​​השנייה, וכן הלאה, ולאחר מכן מוסיפים את כל המוצרים המתקבלים.

a[0][0]*b[0][0] + a[0][1]*b[1][0] + … + a[0][m-1]*b[m-1][0]
כדי להשיג את האלמנט השני בשורה הראשונה של מטריצת התוצאה, אנו מבצעים את אותו הליך עם השורה השנייה

a[1][0]*b[0][0] + a[1][1]*b[0][1] + … + a[0][m-1]*b[m-1][0]
וכך הלאה עד סוף השורה. לאחר מכן אנו עוברים לשורה הבאה וחוזרים על ההליך עד שנגמרים לנו השורות. כלומר, נכפיל את השורות של המטריצה ​​הראשונה עם העמודות של המטריצה ​​השנייה. להלן הקוד לכפל מטריצה. ניתן להשלים אותו בבדיקת עמידה בתנאי הנ"ל במספר השורות והעמודות.
//declaring two matrices
int [][] twoDimArray1 = {{1,0,0,0},{0,1,0,0},{0,0,0,0}};
int[][] twoDimArray2 = {{1,2,3},{1,1,1},{0,0,0},{2,1,0}};

//matrix multiplication process
int[][]twoDimArray3 = new int [twoDimArray1.length][twoDimArray2[0].length];
        for (int i=0; i<twoDimArray3[0].length; i++)
            for (int j=0; j<twoDimArray3.length; j++)
                for (int k=0; k<twoDimArray1[0].length; k++)
                              twoDimArray3[i][j] = twoDimArray3[i][j] + twoDimArray1[i][k] * twoDimArray2[k][j];

//output on display
        for (int i = 0; i < twoDimArray3.length; i++) {
            for (int j = 0; j < twoDimArray3[0].length; j++) {
                System.out.print(" " + twoDimArray3[i][j] + " ");
            }
            System.out.println();
        }
התוכנית מפלטת את התוצאה הבאה: 1 2 3 1 1 1 0 0 0

מערכים דו מימדיים לא מלבניים

מכיוון שמערכים דו מימדיים הם מערכים של מערכים ב-Java, כל אחד מהמערכים הפנימיים יכול להיות באורכים שונים. בעת יצירת מערך, נוכל לציין רק את מספר השורות ולא את מספר העמודות (כלומר, למעשה, את האורך של אותן שורות). בואו נסתכל על דוגמה.
//declaring and creating an array, specifying only the number of rows
int [][] twoDimArray = new int[5][];

//initialize the array, filling it with arrays of different lengths
        twoDimArray[0] = new int[]{1, 2, 3, 4, 5};
        twoDimArray[1] = new int[]{1,2,3,4};
        twoDimArray[2] = new int[]{1,2,3};
        twoDimArray[3] = new int[]{1,2};
        twoDimArray[4] = new int[]{1};
//display the resulting non-rectangular two-dimensional array on the screen
        for (int i = 0; i < twoDimArray.length; i++) {
            for (int j = 0; j < twoDimArray[i].length; j++) {
                System.out.print(" " + twoDimArray[i][j] + " ");
            }
            System.out.println();
        }
פלט תוכנית: 1 2 3 4 5 1 2 3 4 1 2 3 1 2 1 לפיכך, הקו האפסי של המערך שלנו מכיל את המערך {1,2,3,4,5}, והשורה הרביעית מכילה את המערך {1}.

מערכים תלת מימדיים בג'אווה

בעקבות השכל הישר וההיגיון של שפת ג'אווה, מערך תלת מימדי יכול להיקרא "מערך של מערכים של מערכים" או "מערך שכל אלמנט שלו הוא מערך דו מימדי". יתר על כן, מערכים דו מימדיים אלה יכולים להיות שונים. דוגמא:
// create a three-dimensional array consisting of two two-dimensional arrays
int[][][] threeDimArr = new int[2][][];
//create the first 2D array of a 5x2 3D array
        threeDimArr[0] = new int[5][2];
//create a second 2D array of a 1x1 3D array
        threeDimArr[1] = new int[1][1];
אבל לעתים קרובות יותר בפועל יש מערכים תלת מימדיים שבהם כל שלוש הכמויות מוגדרות בבת אחת, אנלוגי של מערכים דו מימדיים מלבניים. מערכים רב מימדיים - 7כפי שכבר הזכרנו, נעשה שימוש במערכים תלת מימדיים או יותר לעתים רחוקות מאוד. עם זאת, אתה יכול לתכנת משהו מעניין עם מערך 3D. למשל, חניון רב קומות. כל קומה יכולה להיחשב כמערך דו מימדי, וחניה יכולה להיחשב כאלמנט ספציפי של מערך תלת מימדי. אלמנט של מערך כזה יכול להיות מיוצג על ידי טיפוס booleanעם הערך false אם החלל פנוי ואמיתי אם המקום תפוס.
//set a boolean three-dimensional array. This car park has 3 floors, each of which can accommodate 2x5 = 10 cars. By default, all cells are empty (false)
boolean[][][] parkingLot = new boolean[3][2][5];
//two cars arrived and parked on the ground floor in cell [1][0] and [1][3]
        parkingLot[0][1][0] = true;
        parkingLot[0][1][3] = true;

//Output the array to the console
        for (int i = 0; i < 3; i++) {
            for (int j = 0; j < 2; j++) {
                for (int k = 0; k < 5; k++) {
                    System.out.print("arr[" + i + "][" + j + "][" + k + "] = " + parkingLot[i][j][k] + "\t");

                }
                System.out.println();
            }
        }

מערכים רב מימדיים בעבודתו האמיתית של מתכנת ג'אווה

במציאות, רוב מפתחי ג'אווה אינם נתקלים במערכים רב-ממדיים לעתים קרובות מאוד. עם זאת, ישנן מספר משימות שמבנה הנתונים הזה מתאים מאוד להן.

  1. לבדיקות והגדרת מטריצות כקבועים לבדיקת אלגוריתם מסוים.
  2. לפעמים משתמשים במערכים רב-ממדיים עבור רשתות עצביות.
  3. מערכים רב מימדיים מתאימים לארכיונים.
  4. עבודה עם תמונות.

בעיות מעניינות על מערכים דו מימדיים ותלת מימדיים

אתה יודע מספיק על מערכים רב מימדיים ב-Java, ואם אתה מרגיש בטוח, אתה יכול לנסות לפתור כמה מהבעיות למטה. הם לא קלים, אבל מעניינים. איקס עיגול. הגדר מגרש 3x3, צור שני שחקנים שמתחלפים. בתחילה, המגרש ריק, ובכל אחד מהשדות הריקים השחקן הראשון יכול לשים הצלבה, והשני אפס. המנצח הוא זה שאוסף ראשון שלושה צלבים או שלושה אפסים המסודרים בשורה אחת, בעמודה אחת או באלכסון.

מה עוד לקרוא

משחק Java למתחילים

הנמלה של לנגטון . יש שדה מסוים, מחולק לתאים (מערך דו מימדי), צבוע בשחור או לבן (ניתן להגדיר על ידי פונקציה אקראית). "נמלה" מתממשת באקראי באחד התאים, ובכל שלב היא יכולה לנוע באחד מארבעה כיוונים לתא הסמוך, אופקית או אנכית. חוקי תנועת נמלים:
  • בריבוע שחור, הנמלה חייבת להסתובב 90° שמאלה, לשנות את צבע התא שלה ללבן, ואז לצעוד קדימה לריבוע הבא.
  • בריבוע לבן, הנמלה מסתובבת 90° ימינה ומשנה את צבע התא שלה לשחור, ואז צועדת קדימה לריבוע הבא.
כתוב שיטה שמחשבת את האיטרציה במספר שלב nבהינתן המיקום ההתחלתי של הנמלה. ניתן למלא את השדה באופן אקראי באפסים ואחדים (או לסמן באותיות Wו- B, כפי שעשינו בדוגמה של לוח השחמט). אנחנו צריכים גם שני פרמטרים נוספים - המיקום האופקי והאנכי של הנמלה, כמו גם הכיוון שלה בשלב זה (צפון, דרום, מערב, מזרח), כאשר כברירת מחדל הנמלה מסתכלת צפונה. אתה יכול לנסות ליצור מודל של קוביית רוביק באמצעות מערכים תלת מימדיים. לקובייה רגילה של רוביק יש 6 פנים, וכל אחד מהם הוא מערך תלת מימדי של ריבועים צבעוניים Color[][][] rubik = new Color[6][3][3]. עם זאת, יישום קוביית רוביק אינה משימה טריוויאלית.

חומרים שימושיים על מערכים

מאמרים רבים ב-JavaRush מוקדשים למערכים (בעיקר חד-ממדיים, מכיוון שהם משמשים לעתים קרובות יותר בפועל). שימו לב אליהם.
  1. מערכים בג'אווה - על מערכים למתחילים עם דוגמאות
  2. משהו על מערכים - מאמר מפורט טוב על מערכים
  3. המחלקה Arrays והשימוש בה - המאמר מתאר כמה שיטות של המחלקהArray
  4. מערכים היא ההרצאה הראשונה של JavaRush המוקדשת למערכים.
  5. החזר מערך באורך אפס, לא ריק - מחבר תכנות יעיל ג'ושוע בלוך מדבר על איך להחזיר מערכים ריקים בצורה טובה יותר
הערות
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION