Transcript i >= 0
מערכים
קרן כליף
ביחידה זו נלמד:
מהו מערך
כיצד מערך נראה בזיכרון
גישה לאיברי המערך
אתחול מערך
הפונקציה sizeof
חריגה מגבולות המערך
השמת מערכים
מערך דו-מימדי
מערך רב-מימדי
typedef למערך
2
© Keren Kalif
מוטיבציה
אם נרצה לכתוב תוכנית הקוראת 20מספרים ומציגה את
הממוצע שלהם ,נצטרך להגדיר 20משתנים:
)(void main
{
;int num1, num2, …, num20, sum=0
;" cout << "Please insert 20 numbers:
;cin >> num1 >> num2 >> ... >> num20
;sum = num1 + num2 + … + num20
;cout << "The average is " << sum/20.0 << endl
}
התוכנית מסורבלת ומייגע לכתוב אותה ,בייחוד כי יתכן גם
שנרצה ממוצע של 100מספרים ,או אפילו יותר...
3
© Keren Kalif
הגדרה
מערך הוא אוסף של משתנים מאותו הסוג עם שם אחד ,ובעלי
תפקיד זהה
דוגמא :מערך של 20מספרים
דוגמא :מערך של 10תוים
ובאופן כללי:
;]int numbers[20
;]char letters[10
4
© Keren Kalif
;]<type> <var_name>[SIZE
איברי המערך נשמרים ברצף בזיכרון
גודל המערך צריך להיות ידוע בזמן קומפילציה ,כדי שהמחשב ידע
כמה תאים להקצות למערך ,ולכן גודלו יהיה קבוע או מספר
גודל המערך בזיכרון<*SIZE :גודל הטיפוס>
דוגמא למערך בזיכרון
1000
4
1004
???
1008
???
1012
???
1016
’‘a
int:x
int[]:arr
char: ch
1017
)(void main
{
;int x = 4
;]int arr[3
;’char ch = ‘a
}
ערכם של איברי המערך הוא זבל ,כמו כל משתנה שלא אותחל
גודל המערך בזיכרוןSIZE*sizeof(type) :
ובדוגמא זו3*sizeof(int) = 3*4 = 12 :
5
© Keren Kalif
גישה לאיברי המערך
כדי שניתן יהיה להתייחס לכל איבר בנפרד ניתנו להם
אינדקסים
האיבר הראשון בעל אינדקס ,0השני בעל אינדקס 1
והאחרון עם אינדקס SIZE-1
דוגמא:
;]int arr[3
;arr[0] = 1
הפניה לאיבר מסוים במערך היא ע"י [ ] כאשר בתוך
הסוגריים יהיה האינדקס של האיבר אליו נרצה לגשת
פניה לאיבר במערך היא כפניה למשתנה מטיפוס המערך
מתייחסים ל arr[0] -כמו שמתייחסים לint -
6
© Keren Kalif
דוגמא- גישה לאיברי המערך
void main()
???
4
int[]:arr
1000
{
???
7
1004
int arr[3];
???
3
1008
arr[0] = 4;
arr[1] = 7;
arr[2] = 3;
cout << “The values in the array:” << arr[0] << “ “
<< arr[1] << “ “ << arr[2] << endl;
}
1000 0*sizeof(int) + arr : פירושו תפנה לתא בזיכרון שנמצא בכתובתarr[0]
1004 1*sizeof(int) + arr : פירושו תפנה לתא בזיכרון שנמצא בכתובתarr[1]
1008 2*sizeof(int) + arr : פירושו תפנה לתא בזיכרון שנמצא בכתובתarr[2]
7
© Keren Kalif
גישה לאיברי המערך -לולאות
מאחר ועבודה עם איברי המערך היא עבודה זהה על כל
האיברים ,יותר חסכוני וקל להשתמש בלולאות
;const int SIZE=5
)(void main
{
;int arr[SIZE], i
;“ cout << "Please enter “ << SIZE << “ numbers:
נשים לב שבעבודה עם מערכים ולולאות iיתחיל מfor (i=0 ; i < SIZE ; i++) 0 -
;]cin >> arr[i
האינדקס שאיתו פונים לאיבר במערך יכול להיותcout << "The numbers are: “; :
מספר שלם (כמו בדוגמא הקודמת)
)for (i=0 ; i < SIZE ; i++
משתנה (כמו בדוגמא זו)
;“ “ << ]cout << arr[i
ערך של ביטוי ,למשלarr[i+2] :
;”cout << "\n
8
© Keren Kalif
ניתוח זמן הריצה של תוכנית זו:
)O(main) = O(1) + O(SIZE) + O(SIZE) = O(1) + 2*O(SIZE) = O(SIZE
}
)2( גישה לאיברי המערך – לולאות
..הפעם נרצה להדפיס את איברי המערך מהסוף להתחלה
const int SIZE=5;
void main()
{
int arr[SIZE], i;
cout << "Please enter “ << SIZE << “ numbers: “;
for (i=0 ; i < SIZE ; i++)
cin >> arr[i];
}
cout << "The numbers are: “;
for (i=SIZE-1 ; i >= 0 ; i--)
cout << arr[i] << “ “;
cout << "\n";
9
© Keren Kalif
דוגמא- גישה לאיברי המערך – לולאות
:תוכנית המוצאת את הערך המקסימלי שהוכנס
const int SIZE=4;
void main()
{
int arr[SIZE], i, max;
cout << "Enter “ << SIZE << “ numbers: “;
for (i=0 ; i < SIZE ; i++)
cin >> arr[i];
}
max = arr[0];
for ( i=1 ; i < SIZE ; i++ )
{
if (arr[i] > max)
max = arr[i];
}
cout << "The max is “ << max << endl;
???
13
1000
???
11
1004
???
17
1008
???
15
1012
int: i
???
1
2
3
4
1016
int: max
???
13
17
1020
int[]:arr
:ניתוח זמן הריצה של תוכנית זו
O(main) = O(1) + O(SIZE) + O(SIZE) = O(1) + 2*O(SIZE) = O(SIZE)
10
© Keren Kalif
מציאת האינדקס המכיל את הערך
המקסימלי
const int SIZE=4;
void main()
{
int arr[SIZE], maxIndex, i;
cout << "Enter “ << SIZE << “ numbers: “);
for (i=0 ; i < SIZE ; i++)
cin >> arr[i];
}
???
13
1000
???
11
1004
???
17
1008
???
15
1012
int: i
???
1
2
3
4
1016
int: maxIndex
???
0
2
1020
int[]:arr
maxIndex = 0;
for ( i=1 ; i < SIZE ; i++ )
{
if (arr[i] > arr[maxIndex])
maxIndex = i;
}
cout << "The max is at index “ << maxIndex
<< “ and its value is “ << arr[maxIndex] << endl;
11
© Keren Kalif
אתחול מערך
כאשר מגדירים מערך ערכי איבריו הוא זבל
ניתן לאתחל את איברי המערך באחת מהדרכים הבאות:
int arr1[3] = {5, 3, 1}; //arr1[0]=5, arr1[1]=3, arr1[2]=1
= {5, 3, 1}; //arr2[0]=5, arr2[1]=3, arr2[2]=1
!and the size of the array is 3
][int arr2
//arr3[0]=5, arr3[1]=0, arr3[2]=0
;}int arr3[3] = {5
//arr4[0]=0, arr4[1]=0, arr4[2]=0
;}int arr4[3] = {0
נשים לב כי רק בעת האיתחול ניתן לתת ערך לכמה
איברים יחד! כל נתינת ערך בהמשך הינה השמה ,ולא
איתחול ,ולכן יבוצע על כל איבר בנפרד.
12
© Keren Kalif
הגדרת הגודל והערכים:אתחול מערך
: עבור המערכים הבאים
int numbers[3] = {5, 3, 1};
char letters[3] = {‘m’, ‘A’, ‘k’};
int[]: numbers
5
3
1
char[]: letters
‘m’
‘A’
‘k’
: הזכרון יראה כך
1000
1004
1008
1012
1013
1014
13
© Keren Kalif
אתחול מערך :הגדרת הערכים בלבד
עבור המערך הבא:
;}double numbers[] = {5, 3.2, 1.1
הזכרון יראה כך:
1000
1008
1016
5.0
double[]:
numbers
3.2
1.1
נשים לב שאין צורך בהגדרת גודל המערך ,הקומפיילר
יודע זאת לבד לפי מספר הערכים שאותחלו
14
© Keren Kalif
אתחול מערך :הגדרת גודל וחלק מהערכים
כאשר נגדיר מערך באופן הבא:
;}int numbers[3] = {5
הזכרון יראה כך:
1000
1004
1008
5
int[]: numbers
0
0
כאשר מאתחלים את איברי המערך באופן חלקי ,שאר
האיברים מקבלים ערך ( 0בניגוד לזבל שהיה אם לא היינו
מאתחלים כלל)
15
© Keren Kalif
אתחול מערך :איפוס כל איברי המערך
כאשר נגדיר מערך באופן הבא:
;}int numbers[3] = {0
הזכרון יראה כך:
1000
1004
1008
0
int[]:numbers
0
0
זהו מקרה פרטי של צורת האתחול הקודמת
16
© Keren Kalif
sizeof הפונקציה
היא פונקציה המקבלת משתנה או טיפוס ומחזירה אתsizeof
מספר הבתים שהוא תופס בזיכרון
void main()
{
int
num;
double d;
char
ch;
cout <<
<<
cout <<
<<
cout <<
<<
"sizeof(int)=" << sizeof(int)
"\t sizeof(num)=" << sizeof(num) << endl;
"sizeof(double)=" << sizeof(double)
"\t sizeof(d)=" << sizeof(d) << endl;
"sizeof(char)=" << sizeof(char)
"\t sizeof(ch)=" << sizeof(ch) << endl;
}
17
© Keren Kalif
חישוב גודל המערך
SIZE*sizeof(type) גודל המערך בזיכרון הוא
יהיו מקרים בהם נרצה לדעת בזמן ריצה כמה איברים יש
: למשל, ולא תמיד הגודל מוגדר לנו,במערך
void main()
{
int arr[] = {4, 3, 2, 7};
int size = sizeof(arr) / sizeof(int);
cout << "There are “ << size << “ numbers in the array: “;
for (int i=0 ; i < size ; i++)
cout << arr[i] << “ “;
cout << "\n”;
}
18
© Keren Kalif
חישוב גודל המערך ()2
ניתן לחשב את כמות האיברים במערך גם באופן הבא:
)(void main
{
;}int arr[] = {4, 3, 2, 7
)]sizeof(arr[0
;)int size = sizeof(arr) / sizeof(int
…
}
דרך זו עדיפה ,שכן אם נשנה את טיפוס איברי המערך לא
נצטרך לתקן את השורה המחשבת את הsize -
19
© Keren Kalif
הדפסת היסטוגרמה של ערכי המערך:דוגמא
#include <iostream>
using namespace std;
void main()
{
int arr[] = {4, 3, 2, 7};
int size = sizeof(arr) / sizeof(arr[0]);
}
cout << "There are “ << size << “ numbers in the array: “;
for (int i=0 ; i < size ; i++)
{
cout << arr[i] << “:”;
for (int j=0 ; j < arr[i] ; j++)
cout << "*”;
cout << "\n”;
}
cout << "\n”;
20
© Keren Kalif
הגדרה :מערך סימטרי (פלינדרום)
מערך שאם נקרא את ערכיו משמאל לימין או ההפך נקבל
אותו הדבר
21
© Keren Kalif
האם איברי המערך סימטריים:דוגמא
const int SIZE=5;
void main()
{
int arr[SIZE], i, left, right;
bool isSymetric=true;
cout << "Enter “ << SIZE << “ numbers: “;
for (i=0 ; i < SIZE ; i++)
cin >> arr[i];
for (left=0, right=SIZE-1; left < right && isSymetric ; left++, right--)
{
if (arr[left] != arr[right])
left
isSymetric = false;
}
0
if (isSymetric)
cout << "The array is symetric\n”;
else
cout << "The array is NOT symetric\n”;
}
8
1
5
right
2
4
2
3
7
5
4
8
isSymetric = 0
1
22
© Keren Kalif
const int SIZE=5;
void main()
{
int arr[SIZE], i, left, right;
bool isSymetric=true;
שגיאה נפוצה
cout << "Enter “ << SIZE << “ numbers: “;
for (i=0 ; i < SIZE ; i++)
cin >> arr[i];
for (left=0, right=SIZE-1; left < right && isSymetric ; left++, right--)
{
if (arr[left] != arr[right])
isSymetric = false;
else
left
isSymetric = true;
}
0
if (isSymetric)
cout << "The array is symetric\n”;
else
cout << "The array is NOT symetric\n”;
}
8
1
7
right
2
4
3
7
4
9
isSymetric = 0
1
23
© Keren Kalif
דוגמא :היום המועדף בשבוע -פלט
24
© Keren Kalif
בהמשך נראה מה היה קורה אם המשתמש היה מכניס
ערך שאינו בין 1ל!7-
היום המועדף בשבוע:דוגמא
const int EXIT = -1;
void main()
{
int i, daysFrequency[7] = {0}, day, maxDayIndex;
do
{
??
1000
??
0
1004
??
0
1008
0
??
1012
1
2
??
0
1016
??
0
1020
??
0
1024
??
0
1
1028
int: day
4
??
-1
7
1032
int:
maxDayIndex
??
0
1036
int: i
int[]:
daysFreq
cout << "Insert the day you like most (1-7), “ << EXIT << “ to EXIT: “;
cin >> day;
if (day != EXIT)
daysFrequency[day-1]++;
} while (day != EXIT)
cout << "Each day and number of persons who liked it most:\n”;
for(i=1 ; i<=7 ; i++)
cout << I << “ : “ << daysFrequency[i-1] << endl;
}
maxDayIndex = 0;
for (i=1 ; i < 7 ; i++)
{
if (daysFrequency[i] > daysFrequency[maxDayIndex])
maxDayIndex = i;
}
cout << "The favorite day is: “ << maxDayIndex+1 << endl;
25
© Keren Kalif
חריגה מגבולות המערך
כדי לגשת לאחד מאיברי מערך בגודל Nניגש עם
אינדקסים N-1...0
כאשר ננסה לפנות לאינדקס שאינו בגבולות המערך אנו
למעשה מנסים לגשת בתא בזיכרון שאיננו יודעים מה יש
בו ומה השפעתו ,וזוהי גישה לא חוקית לשטח בזיכרון
1000
???
1004
???
1008
???
1012
int[]:arr
;]int arr[3
;arr[5] = 7
1016
1020
26
© Keren Kalif
7
] arr[5פירושו תפנה לתא בזיכרון שנמצא בכתובת5*sizeof(int) + arr :
כלומר לכתובת 1000+5*sizeof(int) = 1020
חריגה מגבולות המערך ()2
אחריות המתכנת לפנות לתא שבגבולות המערך
הקומפיילר אינו מתריע על ניסיון פניה לתא שאינו
בגבולות המערך (יתכן שבזמן קומפילציה אינו ידוע מהו
התא אליו מנסים לגשת)
iיכול להיות בין 0-3ואז הכל בסדר ,או לחילופין מספר
שלילי או גדול מ 3 -ואז אנו חורגים מגבולות המערך...
;]int arr[4
;int i
;cin >> i
;arr[i] = 7
יתכנו מקרים בהם פנינו לתא חשוב ,והתוכנית תעוף
יש קומפיילרים שתמיד יעיפו אותנו כאשר נפנה לתא
שאינו בגבולות המערך ,ויש כאלו שלא ,ואז הבעיות
עלולות להגיע אח"כ...
27
© Keren Kalif
השמת מערכים
כדי לבצע השמה בין משתנים מאותו הסוג אנו משתמשים
באופרטור =
;int x, y=5
;x = y
עבור מערכים לא ניתן לבצע זאת:
;]int arr1[]={1,2,3}, arr2[3
;arr2 = arr1
השמה בין מערכים תבוצע בעזרת לולאה ,בה נעתיק
איבר-איבר
28
© Keren Kalif
דוגמא- השמת מערכים
void main()
{
int arr1[] = {1,2,3}, arr2[3];
// arr2 = arr1; // DOESN'T COMPILE!!
cout << "Elements in arr2 before: “;
for (int i=0 ; i < 3 ; i++)
cout << arr2[i] << “ “;
for (int i=0 ; i < 3 ; i++)
arr2[i] = arr1[i];
cout < "\nElements in arr2 after: “;
for (int i=0 ; i < 3 ; i++)
cout << arr2[i] << “ “;
cout << "\n”;
}
29
© Keren Kalif
דוגמא :קבל מספר והחזר מהי הספרה
המופיעה הכי הרבה פעמים
למשל ,עבור המספר 12,327,293תוצג הספרה 2כי
היא מופיעה הכי הרבה פעמים במספר ( 3פעמים)
אופציה :1לספור באמצעות לולאה כמה פעמים בכל
המספר מופיעה הספרה ,1כנ"ל עבור הספרה 2וכו'
) ,10*O(nכאשר nהוא מספר הספרות במספר
)10*O(n) = O(n
אופציה :2מיון דליים
30
© Keren Kalif
) ,O(nכאשר nהוא מספר הספרות במספר
void main()
{
O(n)
int num;
int maxDigit=0, maxCount=0;
cout >> “Enter number :”;
cin >> num;
for (int i = 0; i < 10; i++)
{
int temp = num;
int count = 0;
while (temp > 0)
{
if (temp % 10 == i)
count++;
temp /= 10;
}
if (count > maxCount)
{
maxCount = count;
maxDigit = i;
}
}
cout >> “The digit that appears most
is “ >> maxDigit >> endl;
void main()
{
int num;
int counters[10] = {0};
int maxDigit;
הקוד
cout >> “Enter number :”;
cin >> num;
O(n)
while (num > 0)
{
counters[num % 10]++;
num /= 10;
}
maxDigit = 0;
for (int i = 1; i < 10; i++)
if (counters[i] > counters[max])
maxDigit = i;
cout >> “The digit that appears
most is “ >> maxDigit >> endl;
}
31
© Keren Kalif
תרגיל
הגדר מערך של 10תווים ,קלוט לתוכו נתונים מהמקלדת,
והדפס למסך את התווים שהוקלדו ללא חזרות ,וכן את
כמות התווים השונים
דוגמא :אם המשתמש הכניס את התווים הבאים:
a 0 ? T T 0 $ a T x
אזי התכנית תודיע שיש 6תווים שונים ותדפיס למסך:
a 0 ? T $ x
32
© Keren Kalif
אסטרטגיית הפתרון
המשתנים בהם נשתמש:
:counterתפקידו לספור את כמות התווים השונים
:fHasAppearדגל שתפקידו לדעת האם תו כבר הופיע
בתווים שלפניו
האלגוריתם:
אפס counter
עבור כל תו במערך:
33
© Keren Kalif
אפס דגל
עבור כל אחד מהתווים שלפניו במערך וכל עוד הדגל לא סומן:
אם התו הנבדק והתו הנוכחי זהים:
סמן את הדגל (כדי להפסיק את לולאת בדיקת התווים שלפניו)
אם הדגל נשאר כבוי ,הדפס את התו למסך והגדל את הcounter -
const int SIZE=10;
void main()
{
int count=0;
bool fHasAppear;
char str[SIZE];
cout << "Please enter “ << SIZE << “ chars: “;
for (int i=0 ; i < SIZE ; i++)
קליטת הנתונים
cin >> str[i];
}
קוד הפתרון
// print each char only once
cout << "The chars are:\n”;
for (int i=0 ; i < SIZE ; i++) עבור כל תו
}
fHasAppear = false; איפוס הדגל עבור התו הנוכחי
for (int j=0 ; j < i && !fHasAppear; j++)
וגם כל,מעבר על כל התווים שלפניו
{
עוד התו לא נמצא
אם התו זהה לאחד התווים
if (str[i] == str[j])
נדליק את הדגל,שלפניו
fHasAppear = true;
}
if (!fHasAppear)
}
נדפיס,אם התו לא הופיע
cout << str[i];
counter -אותו ונגדיל את ה
count++;
{
{
cout << "\nThere were “ count << “ different letters\n”;
34
© Keren Kalif
מערך דו-מימדי -מוטיבציה
כדי לשמור ציונים של 30סטודנטים בכיתה נגדיר מערך
בגודל :30
;]int grades[30
אם יש לנו 3כיתות שעבורן נרצה לשמור ציונים של 30
סטודנטים בכיתה נצטרך להגדיר 3מערכים:
;]int grades1[30], grades2[30], grades3[30
אבל 3הכיתות האלו הן גם אוסף של משתנים מאותו
הסוג – מערך של מספרים בגודל 30
לכן נרצה להגדיר מערך שיש בו 3איברים ,וכל איבר הוא
מערך בגודל :30
;]int grades[3][30
35
© Keren Kalif
מערך דו-מימדי
בהגדרת מערך חד-מימדי מגדירים את כמות התאים בו
(מספר העמודות):
arr
][3
arr
][2
arr
][1
arr
][0
;]int arr[4
בהגדרת מערך דו-מימדי נגדיר את כמות התאים בו ע"י
ציון מספר השורות ומספר העמודות:
arr
arr
arr
arr
arr
arr
arr
arr
][0][3
][1][3
][0][2
][1][2
][0][1
][1][1
][0][0
;]int arr[2][4
][1][0
מערך דו-מימדי הוא למעשה מטריצה ,או ניתן להסתכל
עליו כמערך של מערכים
36
© Keren Kalif
הגדרת מערך דו-מימדי
כדי להגדיר מערך חד-מימדי הגדרנו למשל:
;]double numbers[4
ובאופן כללי:
;]type <name>[SIZE
כדי להגדיר מערך דו-מימדי נגדיר למשל:
;]double numbers[2][4
ובאופן כללי:
;]type <name>[ROWS][COLS
37
© Keren Kalif
מערך דו-מימדי -פניה לאיבר
arr
arr
arr
arr
arr
arr
arr
arr
][0][3
][1][3
][0][2
][1][2
][0][1
][1][1
][0][0
;]int arr[2][4
][1][0
כדי לפנות לאיבר במערך דו-מימדי צריך לציין את מספר
השורה ואת מספר העמודה של האיבר אשר איתו אנו
רוצים לעבוד
38
© Keren Kalif
למשל ,כדי לשנות את ערכו של האיבר בשורה השנייה בעמודה
השלישית:
;arr[1][2] = 5
למשל ,כדי לשנות את ערכו של האיבר בשורה הראשונה
בעמודה הראשונה:
;arr[0][0] = 5
מערך דו-מימדי – דוגמא :קליטת ציונים
לכמה כיתות והדפסתם -פלט
39
© Keren Kalif
קליטת ציונים:מימדי – דוגמא-מערך דו
לכמה כיתות והדפסתם
const int
const int
NUM_CLASSES
= 3;
STUDENTS_IN_CLASS =5;
void main()
{
int grades[NUM_CLASSES][STUDENTS_IN_CLASS];
cout << "Please enter grades for students in " << NUM_CLASSES << " classes:\n";
for (int i=0 ; i < NUM_CLASSES ; i++)
{
cout << "Please enter grades for " << STUDENTS_IN_CLASS
<< " students in class #" << i+1 << ": ";
for (int j=0 ; j < STUDENTS_IN_CLASS ; j++)
cin >> grades[i][j];
}
}
cout << "The grades in all classes:\n";
for (int i=0 ; i < NUM_CLASSES ; i++)
{
cout << "Class #" << i+1 << ": ";
for (int j=0 ; j < STUDENTS_IN_CLASS ; j++)
cout << grades[i][j] << " ";
cout << "\n";
}
40
© Keren Kalif
מערך דו-מימדי – דוגמא :קליטת ציונים
לכמה כיתות והדפסת הממוצע -פלט
41
© Keren Kalif
קליטת ציונים:מימדי – דוגמא-מערך דו
לכמה כיתות והדפסת הממוצע
const int
const int
NUM_CLASSES
= 3;
STUDENTS_IN_CLASS =5;
void main()
{
int
grades[NUM_CLASSES][STUDENTS_IN_CLASS];
double average[NUM_CLASSES];
cout << "Please enter grades for students in " << NUM_CLASSES << " classes:\n";
for (int i=0 ; i < NUM_CLASSES ; i++)
{
cout << "Please enter grades for " << STUDENTS_IN_CLASS
<< " students in class #" << i+1 << ": ";
for (int j=0, sum=0 ; j < STUDENTS_IN_CLASS ; j++)
{
cin >> grades[i][j];
sum += grades[i][j];
}
average[i] = (double)sum/STUDENTS_IN_CLASS;
}
}
cout << "The average for each classe:\n”;
for (i=0 ; i < NUM_CLASSES ; i++)
cout << "Average for class # “ << i+1 << “: “ << average[i] << endl;
42
© Keren Kalif
מערך דו-מימדי – ייצוגו בזיכרון
כמו מערך חד-מימדי ,גם מערך דו-מימדי נשמר בזיכרון ברצף,
כאשר איברי השורה הראשונה נשמרים קודם ,ומיד אח"כ איברי
השורה השניה וכו'
arr arr arr arr
]int arr[2][4]; [0][0] [0][1] [0][2] [0][3
arr
][1][3
43
© Keren Kalif
1000
???
arr[0][0]
1004
???
arr[0][1]
1008
???
arr[0][2]
1012
???
arr[0][3]
1016
???
arr[1][0]
1020
???
arr[1][1]
1024
???
arr[1][2]
1028
???
arr[1][3]
arr
][1][2
int[2][4]:
arr
][1][1
arr
][1][0
ההתאמה בין המקום במערך
הדו -מימדי למערך החד-
מימדי היא
COLUMNS * i + j
מערך דו-מימדי – ייצוגו בזיכרון
כמו מערך חד-מימדי ,גם מערך דו-מימדי נשמר בזיכרון ברצף,
כאשר איברי השורה הראשונה נשמרים קודם ,ומיד אח"כ איברי
השורה השניה וכו'
arr arr arr arr
]int arr[2][4]; [0][0] [0][1] [0][2] [0][3
arr
][1][3
44
© Keren Kalif
1000
???
arr[0][0]
1004
???
arr[0][1]
1008
???
arr[0][2]
1012
???
arr[0][3]
1016
???
arr[1][0]
1020
???
arr[1][1]
1024
???
arr[1][2]
1028
???
arr[1][3]
arr
][1][2
int[2][4]:
arr
][1][1
arr
][1][0
ההתאמה בין המקום במערך
הדו -מימדי למערך החד-
מימדי היא
COLUMNS * i + j
למשל arr[0][3] :נמצא
במקום 4*0+3 = 3
מערך דו-מימדי – ייצוגו בזיכרון
כמו מערך חד-מימדי ,גם מערך דו-מימדי נשמר בזיכרון ברצף,
כאשר איברי השורה הראשונה נשמרים קודם ,ומיד אח"כ איברי
השורה השניה וכו'
arr arr arr arr
]int arr[2][4]; [0][0] [0][1] [0][2] [0][3
arr
][1][3
45
© Keren Kalif
1000
???
arr[0][0]
1004
???
arr[0][1]
1008
???
arr[0][2]
1012
???
arr[0][3]
1016
???
arr[1][0]
1020
???
arr[1][1]
1024
???
arr[1][2]
1028
???
arr[1][3]
arr
][1][2
int[2][4]:
arr
][1][1
arr
][1][0
ההתאמה בין המקום במערך
הדו -מימדי למערך החד-
מימדי היא
COLUMNS * i + j
למשל arr[0][3] :נמצא
במקום 4*0+3 = 3
למשל arr[1][2] :נמצא
במקום 4*1+2 = 6
מערך דו-מימדי -איתחול
ניתן לאתחל מערך דו-מימדי באחת מהדרכים הבאות:
;} }int arr1[2][3] = { {1,2,3}, {4,5,6
;} }int arr2[][3] = { {1,2,3}, {4,5,6
ניתן לאתחל בלי ציון מספר השורות ,אבל תמיד חייבים לציין את מספר העמודות
;} }int arr3[2][3] = { {5,5
;}int arr4[2][3] = {0
46
© Keren Kalif
מימדי – חישוב מספר השורות-מערך דו
const int NUM_OF_COLS=3;
void main()
{
int arr[][NUM_OF_COLS ] = { {1,2,3}, {4,5,6} };
int numOfRows = sizeof(arr)/sizeof(int)/NUM_OF_COLS;
for (int i=0 ; i < numOfRows ; i++)
{
for (int j=0 ; j < NUM_OF_COLS ; j++)
cout << arr[i][j] << “ “;
cout << "\n”;
}
}
47
© Keren Kalif
מציאת סכום:מימדי – דוגמא-מערך דו
איברי האלכסון של מטריצה ריבועית
const int SIZE=4;
void main()
{
int matrix[SIZE][SIZE] = { {1,1,1,1}, {2,4,4,2}, {3,2,1,0}, {7,6,5,4} };
int sum=0;
:)ניתוח זמן הריצה של תוכנית זו (ללא לולאת הפלט
//cout << "The matrix is:\n”;
O(main) = O(1) + SIZE*O(SIZE) = O(SIZE2)
//for (int i=0 ; i < SIZE ; i++)
//{
//
for (int j=0 ; j < SIZE ; j++)
//
cout << matrix[i][j] << “\t”;
//
cout << endl;
//}
// calc the sum of the main diagonal
for (int i=0 ; i < SIZE ; i++)
for (int j=0 ; j < SIZE ; j++)
if (i == j)
sum += matrix[i][j];
cout << "The sum of the main diagonal is “ << sum << endl;
}
48
© Keren Kalif
מציאת סכום:מימדי – דוגמא-מערך דו
)2( איברי האלכסון של מטריצה ריבועית
const int SIZE=4;
void main()
{
int matrix[SIZE][SIZE] = { {1,1,1,1}, {2,4,4,2}, {3,2,1,0}, {7,6,5,4} };
int sum=0;
//cout << "The matrix is:\n”;
//for (int i=0 ; i < SIZE ; i++)
//{
//
for (int j=0 ; j < SIZE ; j++)
//
cout << matrix[i][j] << “\t”;
//
cout << endl;
:)הפלט
//}
ניתוח זמן הריצה של תוכנית זו (ללא לולאת
O(main) = O(1) + O(SIZE) = O(SIZE)
, הדוגמאות פותרות בדרך שונה את אותה הבעיה2
לכן נעדיף פתרון זה אשר.אבל בסיבוכיות שונה
!הסיבוכיות שלו קטנה בסדר גודל שלם מהפתרון הקודם
// calc the sum of the main diagonal
for (int i=0 ; i < SIZE ; i++)
sum += matrix[i][i];
cout << "The sum of the main diagonal is “ << sum << endl;
}
49
© Keren Kalif
הדפסת:מימדי – דוגמא-מערך דו
הסכום של כל עמודה
:ניתוח זמן הריצה של תוכנית זו
const int ROWS = 3;
O(main) =
const int COLS = 4;
O(1) + ROWS*O(COLS) + COLS*O(ROWS)
void main()
O(ROWS*COLS)
{
int matrix[ROWS][COLS] = { {1,1,1,1}, {2,4,4,2}, {7,6,5,4} };
=
cout << "The matrix is:\n”;
for (int i=0 ; i < ROWS ; i++)
{
for (int j=0 ; j < COLS ; j++)
cout << matrix[i][j] << “\t”;
cout << "\n”;
}
for (int i=0 ; i < COLS ; i++)
{
for (int sum=0, j=0 ; j < ROWS ; j++)
sum += matrix[j][i];
cout << "The sum of elements in column #” << i+1 << “ “ << sum << endl;
}
}
50
© Keren Kalif
הכנסת:מימדי – דוגמא-מערך דו
מספרים למטריצה בצורת נחש
const int ROWS = 8;
const int COLS = 5;
void main()
}
int matrix[ROWS][COLS];
int value = 1;
for (int i=0 ; i < ROWS ; i++)
{
if (i%2 == 0)
for (int j=0 ; j < COLS ; j++)
matrix[i][j] = value++;
else
for (int j=COLS-1 ; j >= 0 ; j--)
matrix[i][j] = value++;
{
// print matrix
for (int i=0 ; i < ROWS ; i++)
{
for (int j=0 ; j < COLS ; j++)
cout << matrix[i][j] << “\t”;
cout << "\n";
{
{
51
© Keren Kalif
מערך רב-מימדי
עד כה ראינו מערכים חד-מימדיים ומערכים דו-מימדיים
ניתן להרחיב את ההגדרה לכל מספר סופי של מימדים
למשל :מערך תלת –מימדי
;]int matrix[LENGTH][HEIGHT][DEPTH
דוגמא לשימוש :נרצה לשמור ממוצע ציונים עבור 5בתי-ספר,
כאשר בכל בית-ספר יש 10כיתות ,ובכל כיתה 30סטודנטים:
;]double average[5][10][30
52
© Keren Kalif
במקרה זה נשתמש בלולאה ,בתוך לולאה ,בתוך לולאה..
-מימדי – דוגמאת נתוני בתי-מערך רב
הספר
const int SCHOOLS =3;
const int CLASSES = 2;
const int STUDENTS =4;
void main()
{
float grades[SCHOOLS][CLASSES][STUDENTS] = {
{ {90, 100, 95, 88}, {87, 70, 90, 98} },
{ {88, 75, 80, 60}, {55, 87, 90, 82} },
{ {60, 91, 40, 95}, {77, 66, 88, 99} }
};
for (int i=0 ; i < SCHOOLS ; i++)
{
cout << "Classes in school #“ << i+1 << “:\n”;
for (int j=0 ; j < CLASSES ; j++)
{
cout << " Grades in class #” << j+1 << “:”;
for (int k=0 ; k < STUDENTS ; k++)
cout << grades[i][j][k] << “ “;
cout << endl;
}
cout << endl;
}
}
53
© Keren Kalif
הגדרת typedefלמערך
תזכורת typedef :הוא מתן שם חילופי לטיפוס
ניתן להגדיר typedefלמערך באורך מסויים
במקום לכתוב ] int arr[6ניתן להגדיר טיפוס חדש של מערך
בעל 6איברים מטיפוס :int
;]typedef int Array[6
ניתן לראות בדיבגר שאכן הוקצה מערך בגודל 6
;const int COLS=6
;]typedef int Array[COLS
54
© Keren Kalif
)(void main
{
;Array arr
{
מימדי- למערך דוtypedef הגדרת
מימדי- גם למערך דוtypedef ניתן להגדיר
const int ROWS=2;
const int COLS =3;
typedef int Row[COLS];
typedef Row Matrix[ROWS];
void main()
}
Matrix mat;
{
55
© Keren Kalif
ביחידה זו למדנו:
מהו מערך
כיצד מערך נראה בזיכרון
גישה לאיברי המערך
אתחול מערך
הפונקציה sizeof
חריגה מגבולות המערך
השמת מערכים
מערך דו-מימדי
מערך רב-מימדי
typedef למערך
56
© Keren Kalif
תרגיל :1
כתוב תוכנית המגדירה מערך בגודל 10של מספרים שלמים
קלוט ערכים מהמשתמש ,והדפס את האינדקסים של האיברים
שערכם שווה לערך המינימלי במערך
כמו כן יש להדפיס את כמות האינדקסים שבתוכם יש ערך השווה
לערך המינימלי
דוגמא:
6
14 12 14 12 5 14 6
5
5
עבור המערך
יש להדפיס ( 5 8 9כי 5הוא המינימלי והוא נמצא באינדקסים
אלו)
וכן להדפיס את הערך ,3מאחר והערך המינימלי מופיע 3פעמים.
57
© Keren Kalif
9
8
7
6
5
4
3
2
1
0
תרגיל :2
כתוב תוכנית והגדר בה מטריצה ריבועית של תווים בגודל SIZE
יש לשים את התו '*' על איברי האלכסון הראשי והמשני ורווח בשאר
האיברים (לדמות את הצורה )X
הדפס את המטריצה
למשל ,עבור SIZE=5המטריצה תראה כך:
*
*
*
*
*
*
*
58
© Keren Kalif
*
*
תרגיל :3
כתוב תוכנית והגדר בה מטריצה בגודל ROWSxCOLSשל
מספרים
קלוט לתוכה ערכים מהמקלדת
קלוט מהמשתמש מספר והדפס את האינדקס של העמודה בה
המספר שהוקלד מופיע הכי הרבה פעמים.
אם התו כלל לא מופיע במטריצה יש לתת הודעה מתאימה
שימו לב :אין לעבור על המטריצה בהתחלה כדי לבדוק זאת!
למשל ,עבור המטריצה הבאה והמספר 3יוצג 2כי
המספר 3מופיע הכי הרבה פעמים בעמודה 2
59
© Keren Kalif
8
1
3
9
1
2
7
5
2
0
3
4
3
3
6