Download presentation
Presentation is loading. Please wait.
1
مبانی کامپیوتر و برنامه سازی
فصل دهم : آرایه ها
2
10 آرایه ها در مبحث الگوریتمها با یک ساختمان داده مهم، یعنی آرایهها آشنا شدیم. البته در C ساختمان داده های دیگر ی همچون ساختارها نیز وجود دارند، اما آرایهها همچنین مهمترین ساختمان داده موجود در این زبان هستند. آرایه در C عبارتست از مجموعه ای از داده های همنوع که تحت یک نام مشترک و در خانه های متوالی حافظه ذخیره می گردند. برای دسترسی به عناصر آرایه، باید از نام آرایه بعلاوه اندیس استفاده کرد. در قسمتهای بعدی، نحوه تعریف و استفاده از آرایهها را تشریح خواهیم کرد.
3
آرایه های یک بعدی پیش از آنکه بتوان از یک آرایه یک بعدی استفاده کرد، باید آن را اعلان کرد. اعلان آرایهها بصورت زیر انجام می گردد: <type> <var-name>[<size>] ; بعنوان مثال: int A[10]; خط بالا یک آرایه 10 تایی از اعداد صحیح بنام A ایجاد می نماید. هر کدام از عناصر این آرایه می توانند بعنوان یک متغیر مستقل مورد استفاده قرار گیرد. برای دسترسی به عناصر این آرایه باید از اندیس استفاده نمود. در زبان C اندیسها در داخل کروشه [] قرار می گیرند. نکته بسیار مهمی که باید بدان توجه کرد آنستکه در C اندیس یک عدد صحیح است که از 0 آغاز می گردد.
4
1-10 آرایه های یک بعدی int A[10] ; 8 A[2] = 8 ; A[0] A[1] A[2] A[3]
آرایه های یک بعدی int A[10] ; 8 A[0] A[1] A[2] A[3] A[9] A[2] = 8 ;
5
آرایه های یک بعدی مثال 1) برنامه ای بنویسید که شماره دانشجویی و معدل تعدادی دانشجو را دریافت، و سپس چنانچه معدل دانشجو از میانگین کلاس : بیش از یک نمره بیشتر باشد، چاپ کند : عالی حداکثر یک نمره بیشتر یا کمتر باشد، چاپ کند : خوب بیش از یک نمره کمتر باشد، چاپ کند : ضعیف #include <stdio.h> void main() { float average[100] ; //آرایه نگهداری معدل دانشجویان long int id[100] ; //آرایه نگهداری شماره دانشجویان float totalAverage; //میانگین کل دانشجویان int i, n ; printf("enter number of students : "); scanf("%d", &n); //دریافت تعداد دانشجویان
6
آرایه های یک بعدی //حلقه دریافت مشخصات دانشجویان و محاسبه میانگین معدلها for (i = 0; i < n ; i ++) { printf("enter id and average : "); scanf("%ld %f", &id[i], &average[i]); totalAverage += average[i]; } totalAverage /= n; //حلقه مقایسه معدل هر دانشجو با میانگین کلاس و چاپ پیام مناسب if (average[i] >= totalAverage + 1) printf("%ld : excellent !\n", id[i]); else if (average[i] >= totalAverage – 1) printf("%ld : good !\n", id[i]); else printf("%ld : weak !\n", id[i]);
7
آرایه های یک بعدی چند نکته مهم راجع به آرایه در C وجود دارد که حتما باید به آنها دقت کنید: اندازه آرایهها در C ثابت بوده و حتما باید توسط یک مقدار ثابت صحیح تعیین گردد. بعنوان مثال اعلان زیر خطای نحوی محسوب می گردد: int n ; n=100 ; int A[n]; اما می توان با استفاده از متغیر های ثابت (ثابتهای دارای نام)، اندازه آرایه را تعیین کرد، که در قسمتهای بعدی به آن اشاره خواهد شد. اندیس آرایهها در C عدد صحیح بوده و همیشه از 0 شروع می شود. لذا به تفاوت "عنصر چهار آرایه" یعنی A[4] و "چهارمین عنصر آرایه" یعنی A[3] دقت کنید. این مسئله معمولا باعث بروز خطاهای منطقی می گردد. در C مرز آرایهها بررسی نمی گردد. بدین معنا که چنانچه اندیسی خارج از محدوده مجاز یک آرایه استفاده شود، باعث ایجاد خطا توسط کامپایلر نمی گردد، اما مسلما برنامه را دچار یک خطای منطقی خواهد کرد. بعنوان مثال: int A[10] ; A[12] = 20 ; //this is not a syntax error but a logical error لذا بررسی مرزهای آرایه بعهده خود برنامهنویس است و باید از درستی برنامه خود و خارج نشدن از محدوده مجاز مطمئن گردد.
8
آرایه های یک بعدی مقداردهی اولیه به آرایه های یک بعدی بصورت زیر انجام می پذیرد: int A[3] = {5, 2, 8}; که در اینجا A[0] برابر 5 ، A[1] برابر 2 و A[2] برابر 8 خواهد شد. علاوه براین می توان فقط به تعدادی از عناصر آرایه مقدار داد، دراینصورت مقدار عناصر باقیمانده آرایه اتوماتیک 0 خواهد شد. int B[10] = {5, 8} ; در اینجا عناصر B[2] به بعد مقدار 0 خواهند گرفت. بنابراین می توان برای 0 کردن کلیه عناصر یک آرایه به شکل زیر عمل کرد : int C[10] = {0}; چنانچه به آرایه مقدار دهی اولیه کرده باشیم، می توان تعداد عناصر آرایه را نیز ذکر نکرد، دراینصورت اندازه آرایه بطور اتوماتیک برابر تعداد مقادیر مشخص شده خواهد شد. int C[] = {10, 15, 20}; در مثال فوق آرایه C با 3 عضو درنظر گرفته می شود.
9
2-10 متغیرهای ثابت همانطور که در قسمت قبل گفته شد، گرچه اندازه یک آرایه باید ثابت صحیح باشد؛ اما می توان از متغیرهای ثابت نیز استفاده کرد. یک متغیر ثابت، متغیری است که فقط می تواند در هنگام اعلان مقدار اولیه بگیرد و این مقدار دیگر قابل تغییر نیست. برای اعلان متغیرهای ثابت، از کلمه کلیدی const قبل از نوع متغیر استفاده می گردد. بعنوان مثال: const int k = 10; اکنون هرگونه تلاش برای تغییر مقدار k، باعث ایجاد یک خطای نحوی توسط کامپایلر خواهد شد. به این نوع متغیرها، ثابتهای نام دار نیز گفته می شود. این متغیرها در تعریف مقادیر ثابتی که مقدار آنها در طول برنامه تغییر نمیکند، بکار میروند. بعنوان مثال : const float pi = 3.14; این کار نه تنها خوانایی برنامه را بالا میبرد (بدلیل استفاده از کلمه pi که برای همه شناخته شده است)، بلکه باعث میشود تغییر پذیری برنامه نیز بالا برود. بدین معنا که در صورتیکه برنامهنویس تصمیم گرفت مقدار ثابت را عوض کند، نیازی به تغییر کل برنامه نیست و فقط کافی است مقدار اولیه متغیر را عوض نماید.
10
2-10 متغیرهای ثابت از این مسئله میتوان در تعریف آرایهها نیز استفاده کرد. بدین صورت که بجای آنکه اندازه آرایه را با یک ثابت صحیح مشخص نماییم، آن را با یک متغیر ثابت تعریف میکنیم. با اینکار، درصورتیکه نیازی به تغییر اندازه آرایه (یا آرایه ها) گردد، فقط کافی است مقدار اولیه متغیر ثابت خود را تغییر دهیم. مثال 2) برنامه ای بنویسید که سال ورود تعدادی دانشجو را دریافت و سپس تعداد ورودی های سالهای 75 تا 84 را محاسبه و چاپ نماید.
11
2-10 متغیرهای ثابت #include <stdio.h> void main() {
2-10 متغیرهای ثابت #include <stdio.h> void main() { const int startYear = 75; const int yearNo = 10; int count[yearNo] = {0}; int i, n, year; printf("enter student no :"); scanf("%d",&n); for (i=0; i<n ; i++) { printf("enter entrance year :"); scanf("%d",&year); count [year – startYear] ++; } for (i=0 ; i<yearNo ; i++) printf("year = %d count = %d \n",startYear + i , count[i]);
12
3-10 آرایههای چندبعدی همانطور که در بخش الگوریتمها گفته شد، آرایهها می توانند دارای ابعاد بیشتری نیز باشند. در زبان C نیز می توان یک آرایه چند بعدی را بصورت زیر اعلان کرد: <type> <var-name>[<size 1>][<size 2>] … [<size n>] ; بعنوان مثال، اعلان زیر یک آرایه دوبعدی را معرفی می نماید: int A[5][8] ; برای دسترسی به هر عنصر از این آرایه باید از دو علامت [] استفاده کرد. توجه کنید که اندیس سطرها و ستونها هر دو از 0 آغاز می گردند.
13
3-10 آرایههای چندبعدی ستون سطر int A[5][8] ; A[3][1] = 24 ; 1 2 3 4 5
3-10 آرایههای چندبعدی int A[5][8] ; ستون 1 2 3 4 5 6 7 سطر A[1][6] 1 2 A[2][3] 3 24 4 A[3][1] = 24 ;
14
3-10 آرایههای چندبعدی البته در مورد آرایه های با ابعاد بالاتر نیز به شکل مشابهی عمل می گردد. بعنوان مثال به نحوه استفاده از یک آرایه سه بعدی در مثال زیر دقت کنید: int B[5][8][6] ; B[2][4][0] = 12; مثال 3) یکی از اساتید قصد دارد آماری از نمرات دانشجویان خود در کوییزهای بین ترم تهیه نماید. وی 5 کوییز در طول ترم برگذار نموده است و اکنون نیاز به اطلاعات زیر دارد: میانگین نمرات هر دانشجو برای کل کوییزها میانگین نمرات کل دانشجویان برای هر کوییز برنامه ای بنویسید که نمرات دانشجویان را برای 5 کوییز دریافت و اطلاعات خواسته شده را چاپ نماید.
15
3-10 آرایههای چندبعدی کوییز اول کوییز دوم کوییز سوم کوییز چهارم
3-10 آرایههای چندبعدی کوییز اول کوییز دوم کوییز سوم کوییز چهارم کوییز پنجم دانشجوی اول دانشجوی دوم دانشجوی سوم ...
16
3-10 آرایههای چندبعدی #include <stdio.h>
3-10 آرایههای چندبعدی #include <stdio.h> const int maxStudent = 100; //حداکثر تعداد دانشجویان const int quizNo = 5; //تعداد کوئیزها void main() { float grades[maxStudent][quizNo] ; //آرایه نگهداری نمرات دانشجویان float quizAverage, //میانگین نمرات هر کوئیز studentAverage; //میانگین نمرات هر دانشجو int i, j, n; printf("enter number of students: "); scanf("%d",&n); //دریافت تعداد دانشجویان //حلقه دریافت اطلاعات دانشجویان for (i=0 ; i<n ; i++) { printf("student no %d:\n",i+1); for (j=0 ; j<quizNo ; j++) { printf("enter grade of quiz %d: ", j+1); scanf("%f", &grades[i][j]); }
17
3-10 آرایههای چندبعدی //حلقههای متداخل برای محاسبه میانگین نمرات هر دانشجو printf("Student's averages:\n"); for (i=0 ; i<n ; i++) { studentAverage = 0.0; for (j=0; j<quizNo; j++) studentAverage += grades[i][j]; studentAverage /= quizNo ; printf("student no %d: average=%f \n",i+1, studentAverage); } //حلقههای متداخل برای محاسبه میانگین نمرات هر کوئیز printf("Average of each quiz:\n"); for (j=0 ; j<quizNo ; j++) { quizAverage = 0.0; for (i=0; i<n; i++) quizAverage += grades[i][j]; quizAverage /= n ; printf("quiz no %d: average=%f \n",j+1, quizAverage);
18
3-10 آرایههای چندبعدی و نکته آخر اینکه مقداردهی اولیه به آرایه های چندبعدی امکان پذیر است و بصورت زیر انجام می پذیرد: int A[3][4] = { {12, 5, 3, 8} , {-3, 7, -9, 2}, {4, 22, 18, 6} }; یعنی یک علامت {} برای کل مقداردهی قرار می گیرد، سپس هر ردیف از آرایه در داخل یک {} مجزا قرار می گیرد. برای ابعاد بالاتر نیز به روش مشابهی عمل می گردد. بعنوان مثال برای آرایه های سه بعدی داریم: int A[2][3][4] = { { {12, 5, 3, 8} , {-3, 7, -9, 2}, {4, 22, 18, 6} } , { {8, 1, -3, 4} , {-2, 8, 11, 21} , {7, 3, -15, -8} } };
19
4-10 ارسال آرایههای یک بعدی به توابع
4-10 ارسال آرایههای یک بعدی به توابع آرایهها را نیز همچون سایر نوع دادهها میتوان به یک تابع ارسال کرد. برای اینکار ابتدا باید تابع را بگونهای تعریف کنیم که یک پارامتر از نوع آرایه را دریافت کند. فرض کنید تابعی بنام sumArray داریم که یک آرایه یک بعدی از اعداد صحیح را بعنوان ورودی دریافت مینماید و مجموع عناصر آن را باز میگرداند. تعریف این تابع بصورت زیر است: int sumArray(int A[], int size) { int i , sum = 0; for (i=0; i<size; i++) sum += A[i]; return(sum) ; }
20
4-10 ارسال آرایههای یک بعدی به توابع
4-10 ارسال آرایههای یک بعدی به توابع همانطور که میبینید، اندازه آرایه مشخص نشده است و این یک نکته مثبت است؛ چرا که تابع sumArray میتواند هر آرایه صحیحی را با هر اندازهای دریافت نماید. درواقع حتی اگر اندازه آرایه را نیز مشخص نمایید، کامپایلر از آن صرفنظر خواهد کرد. دومین پارامتر، اندازه واقعی آرایه A را مشخص مینماید. معمولا توابع بگونهای نوشته میشوند که هنگام ارسال یک آرایه به یک تابع، اندازه آن نیز بعنوان یک پارامتر ارسال گردد. در هنگام فراخوانی تابع sumArray، برای ارسال آرایه موردنظر کافی است که تنها نام آرایه را بدون کروشه استفاده نماییم. void main() { int data1[3] = {5, 10, 15}; int data2[5] = {1, 6, 4, 12, 5} ; int sum1, sum2; sum1 = sumArray(data1, 3); sum2 = sumArray(data2, 5); printf("sum1 = %d\n",sum1); printf("sum2 = %d\n",sum2); }
21
4-10 ارسال آرایههای یک بعدی به توابع
4-10 ارسال آرایههای یک بعدی به توابع نکته بسیار مهم، نحوه ارسال آرایهها به توابع است. زبانC آرایهها را توسط ارجاع به تابع ارسال مینماید، بدین معنا که در هنگام ارسال یک آرایه به تابع، بجای یک کپی از آرایه، خود آرایه ارسال میشود. در حقیقت در فصلهای بعدی خواهید دید که برای ارسال یک آرایه، آدرس اولین عنصر آن ارسال میگردد. لذا تابع میتواند از طریق این آدرس، به کلیه دادههای آرایه اصلی دسترسی پیدا کند. اما چرا C در مورد آرایهها به روش متفاوتی عمل مینماید؟ دلیل این مسئله آن است که معمولا یک آرایه حافظه بسیار زیادی را اشغال میکند، لذا تهیه یک کپی کردن از آن، نه تنها باعث اشغال حافظه میشود بلکه زمان زیادی را نیز صرف خواهد کرد. اما آیا میتوان یک آرایه را توسط مقدار به یک تابع ارسال کرد؟ متاسفانه خیر. اما اگر نگران تغییر سهوی آرایه ارسالی به یک تابع هستید میتوانید آن را بگونهای به تابع ارسال نمایید که تغییر آن در تابع ممکن نباشد. زبان C یک نحوه دیگر ارسال دادهها به توابع بنام ارسال توسط ارجاع ثابت میباشد. چنانچه در هنگام تعریف یک پارامتر از یک تابع، از کلمه کلیدی const استفاده شود، کامپایلر اجازه تغییر مقادیر آن پارامتر را در حین اجرای تابع نخواهد داد. با این ارسال آرایهها بصورت ارجاع ثابت، میتوانیم مانع از انجام تغییرات ناخواسته در آرایه شویم.
22
4-10 ارسال آرایههای یک بعدی به توابع
4-10 ارسال آرایههای یک بعدی به توابع مثال 4) برنامهای بنویسید که با استفاده از یک تابع، اشتراک دو مجموعه را محاسبه و چاپ نماید. void intersection(const int A[], int na, const int B[], int nb, int C[], int &nc) { int i,k,j,sw; k = 0; for (i=0; i<na; i++) { sw = 1; for (j=0; j<nb && sw; j++) if (A[i] == B[j]) { C[k] = A[i] ; k ++; sw = 0; } nc = k; void printSet(int set[], int size) { int i; printf("{ ") ; for (i=0; i<size; i++) printf("%d ",set[i]) ; printf("}\n");
23
4-10 ارسال آرایههای یک بعدی به توابع
4-10 ارسال آرایههای یک بعدی به توابع void main() { int set1[5] = {5, 8, 3, 12, 20}; int set2[3] = {12, 16, 8} ; int result[3] , resultSize ; intersection(set1, 5, set2, 3, result, resultSize); printf("set 1 = "); printSet(set1,5) ; printf("set 2 = "); printSet(set2,3) ; printf("intersection = "); printSet(result,resultSize) ; } set1 = { } set2 = { } intersection = { }
24
5-10 ارسال آرایههای چندبعدی به توابع
5-10 ارسال آرایههای چندبعدی به توابع در این قسمت، ابتدا به نحوه ارسال آرایههای دو بعدی به توابع میپردازیم و سپس آرایههای با ابعاد بالاتر را بررسی خواهیم کرد. شاید تصور کنید که برای تعریف یک آرایه دوبعدی بعنوان پارامتری از یک تابع، تنها قرار دادن دو علامت [] کافی است و نیازی به ذکر ابعاد آن نیست. اما متاسفانه اینگونه نیست، بلکه برنامهنویس باید تعداد ستونهای آرایه دوبعدی را صریحا مشخص نماید، اما نیازی به تعیین تعداد ردیفهای آن نیست. بعنوان مثال فرض کنید تابعی مانند test داریم که بعنوان ورودی یک آرایه دو بعدی و تعدادی پارامتر دیگر دریافت میکند. تعریف تابع بصورت زیر اشتباه است: void test(int A[][], …) { تعریف درست، تعریفی مانند زیر است: void test(int A[][10] , …) { در هنگام فراخوانی تابع test، میتوان هر آرایه دوبعدی 10 ستونی را به آن ارسال کرد. آرایه ارسالی به تابع میتواند 5×10 و یا 20×10 باشد، اما نمیتواند مثلا 5×20 باشد.
25
5-10 ارسال آرایههای چندبعدی به توابع
5-10 ارسال آرایههای چندبعدی به توابع مثال 5) تابعی بنویسید که میزان فروش تعدادی شرکت در 12 ماه سال را بعنوان ورودی دریافت، و میانگین فروش شرکتی را که بیشترین میانگین فروش را داشته است، بازگرداند. float maxSales(const long int sales[][12], int companyNo) { int i,j; float average , max; max = 0.0; for (i=0 ;i<companyNo; i++) { average = 0; for (j=0; j<12; j++) average += sales[i][j] ; average /= 12; if (average > max) max = average ; } return(max);
26
5-10 ارسال آرایههای چندبعدی به توابع
5-10 ارسال آرایههای چندبعدی به توابع مثال 6) برنامهای بنویسید که حاصلضرب دو ماتریس را با استفاده از یک تابع محاسبه نماید. #include <stdio.h> const int maxCol = 10; void multiply(const int A[][maxCol], const int B[][maxCol], int m,int p, int n, int C[][maxCol] ) { int i,j,k,sum; for (i=0; i<m; i++) for (j=0; j<n; j++) { sum = 0; for (k=0; k<p; k++) sum += A[i][k] * B[k][j] ; C[i][j] = sum; } void printMatrix(int matrix[][maxCol], int row,int col) { int i,j; for (i=0; i<row; i++) { for (j=0; j<col ;j++) printf("%d ",matrix[i][j]); printf("\n");
27
5-10 ارسال آرایههای چندبعدی به توابع
5-10 ارسال آرایههای چندبعدی به توابع void main() { int matrix1[2][maxCol] = { {7 ,3 , 2} , {-2, 6, 1} }; int matrix2[3][maxCol] = { {2 , 7 , -4, -1} , { 3 ,-3, 5, -8} , {6, -7, 2, 3} }; int result[2][maxCol] ; multiply(matrix1, matrix2, 2, 3, 4, result); printf("matrix1 is :\n"); printMatrix(matrix1,2,3) ; printf("\nmatrix2 is :\n"); printMatrix(matrix2,3,4) ; printf("\nmultiply of matrix1 and matrix2 is :\n"); printMatrix(result,2,4) ; } matrix1 is : matrix2 is : multiply of matrix1 and matrix 2 is :
28
5-10 ارسال آرایههای چندبعدی به توابع
5-10 ارسال آرایههای چندبعدی به توابع اما ارسال آرایه های با ابعاد بالاتر به توابع نیز مشابه آرایه های دوبعدی است. به این صورت که در هنگام تعریف یک پارامتر از تابع بعنوان یک آرایه چندبعدی، مشخص کردن بعد اول لزومی ندارد، اما اندازه کلیه ابعاد بعدی باید حتما مشخص گردد. بعنوان مثال به تابع زیر دقت کنید : void test(int A[][5][10], … ) { این تابع بعنوان ورودی یک آرایه سه بعدی دریافت می نماید که حتما باید بعد دوم آن 5 و بعد سوم آن 10 باشند، اما اندازه بعد اول هر مقداری می تواند باشد.
29
6-10 برخی عملیات مهم برروی آرایه ها
6-10 برخی عملیات مهم برروی آرایه ها همانطور که قبلا گفته شد، آرایهها از ساختمان داده های بسیار مهم برنامهنویسی بوده و تقریبا می توان گفت هیچ برنامه ای وجود ندارد که به نحوی از آرایهها استفاده نکند. به همین دلیل برای انجام بعضی از عملیات مهم بر روی آرایه ها، الگوریتمهای کارا و موثری توسط محققین ابداع شده است، که چند نمونه از مهمترین آنها را بررسی می نماییم.
30
1-6-10 الگوریتمهای مرتب سازی
الگوریتمهای مرتب سازی شاید مهمترین عملی که برروی یک آرایه یک بعدی انجام می شود، مرتب کردن آن بصورت صعودی یا نزولی است. بدلیل اهمیت این کار، الگوریتمهای متعددی برای آن ابداع شده است که برخی از آنها بسیار پیچیده هستند. در اینجا 3 الگوریتم ساده مورد بررسی قرار گرفتهاند که برای آرایه های کوچک بسیار کارا هستند. اما برای مرتب سازی آرایه های بزرگ، باید از روشهای پیچیده تری استفاده شود که در کتابهای پیشرفته تر مورد بررسی قرار گرفته اند. در الگوریتمهای زیر فرض شده است که قصد داریم آرایه را بصورت صعودی مرتب نماییم، گرچه با یک تغییر کوچک می توان آن را به نزولی تبدیل نمود.
31
1-1-6-10 الگوریتم مرتب سازی انتخابی
الگوریتم مرتب سازی انتخابی 16 8 8 22 22 12 12 16 22 35 35 35 ... 27 27 27 8 12 16 41 41 41 19 19 19 مرحله اول مرحله دوم مرحله سوم
32
1-1-6-10 الگوریتم مرتب سازی انتخابی
الگوریتم مرتب سازی انتخابی void selectionSort(int A[], int n) { int i,j; for (i=0; i<n; i++) for (j=i+1; j<n; j++) if (A[i] > A[j]) swap(A[i],A[j]) ; }
33
2-1-6-10 الگوریتم مرتب سازی حبابی
الگوریتم مرتب سازی حبابی 16 16 12 22 12 16 12 22 22 35 27 8 ... 27 8 27 8 35 19 41 19 35 19 41 41 مرحله اول مرحله دوم مرحله سوم
34
2-1-6-10 الگوریتم مرتب سازی حبابی
الگوریتم مرتب سازی حبابی void bubbleSort(int A[], int n) { int i, contSw; do { contSw = 0; n --; for (i=0; i<n; i++) if (A[i] > A[i+1]) { swap(A[i], A[i+1]) ; contSw = 1; } } while (contSw) ;
35
3-1-6-10 الگوریتم مرتب سازی درجی
الگوریتم مرتب سازی درجی در این روش مرتب سازی از عمل درج استفاده می شود. این روش را می توان بصورت زیر مرحله بندی کرد: مرحله 1- فرض می کنیم آرایه فقط دارای عنصر اول است و سایر عناصر را درنظر نمی گیریم. در اینصورت یک آرایه یک عنصری مرتب داریم مرحله 2 – عنصر دوم را در آرایه مرتب مرحله قبل درج می نماییم. اکنون یک آرایه دو عنصری مرتب داریم. مرحله 3- عنصر سوم را در آرایه مرتب مرحله قبل درج می نماییم. اکنون یک آرایه سه عنصری مرتب داریم. ... مرحله k – عنصر kام را در آرایه مرتب k-1 عنصری مرحله قبل درج می نماییم تا یک آرایه k عنصری مرتب بدست آوریم. مرحله n – عنصر n را در آرایه مرتب مرحله قبل درج کرده تا آرایه مرتب نهایی حاصل شود.
36
3-1-6-10 الگوریتم مرتب سازی درجی
الگوریتم مرتب سازی درجی 16 16 12 12 12 8 8 22 22 16 16 16 12 12 12 12 22 22 22 16 16 35 35 35 35 27 22 22 27 27 27 27 35 27 27 8 8 8 8 8 35 35 41 41 41 41 41 41 41 19 19 19 19 19 19 19 مرحله اول مرحله دوم مرحله سوم مرحله چهارم مرحله پنجم مرحله ششم مرحله هفتم
37
3-1-6-10 الگوریتم مرتب سازی درجی
الگوریتم مرتب سازی درجی void insertionSort(int A[], int n) { int i, j, cur; for (i=1; i<n; i++) { cur = A[i] ; for (j=i-1; j>=0 && cur<A[j]; j--) A[j+1] = A[j] ; A[j+1] = cur ; }
38
3-1-6-10 الگوریتم مرتب سازی درجی
الگوریتم مرتب سازی درجی در مورد سه الگوریتم مرتب سازی ذکرشده چند نکته قابل ذکر است: هر 3 الگوریتم برای مرتب سازی یک آرایه از اعداد صحیح (int) نوشته شده اند، اما روش بهتر آن است که آنها را بصورت یک الگو بنویسیم که قادر به مرتب سازی هر نوع آرایهای باشند. الگوها و نحوه پیاده سازی آنها در فصل گذشته مورد بحث قرار گرفتند. هر 3 الگوریتم برای مرتب سازی بصورت صعودی نوشته شده اند، اما میتوان آنها را با یک تغییر کوچک به مرتب سازی نزولی تبدیل کرد. حتی میتوان تابع را بگونهای نوشت که یک پارامتر دیگر برای تعیین نوع مرتب سازی نیز بعنوان ورودی دریافت و براساس مقدار آن، مرتب سازی را بصورت صعودی یا نزولی انجام دهد.
39
الگوریتمهای جستجو یکی دیگر از الگوریتمهای بسیار مهم برای آرایه ها، الگوریتمهای جستجو هستند. موارد زیادی پیش میآیند که قصد داریم به دنبال یک داده در یک آرایه جستجو کرده و مکان آن را پیدا کنیم. در این قسمت دو روش متداول جستجو را مورد بررسی قرار میدهیم. البته معمولا برای عمل جستجو از ساختمان دادههای پیچیده تری همچون درختهای جستجوی دودویی استفاده میگردد، که از بحث ما خارج است.
40
1-2-6-10 الگوریتم جستجوی خطی
الگوریتم جستجوی خطی جستجوی خطی، ساده ترین نوع جستجو است که در آرایههای نامرتب استفاده میشود. در این روش داده مورد نظر به ترتیب با تک تک عناصر آرایه مقایسه میشود تا مکان آن پیدا شود. int linearSearch(int A[], int n, int x) { int i; for (i=0; i<n; i++) if (x == A[i]) return(i); return(-1) ; } اگر آرایه دارای n عنصر باشد، در بدترین حالت نیاز به n مقایسه برای پیدا کردن داده مورد نظر داریم و این در صورتی است که داده در آخرین مکان آرایه قرار داشته باشد. اما از آنجا که احتمال قرار گرفتن داده در هریک از مکانهای آرایه یکسان است، بطور متوسط نیاز به n/2 مقایسه خواهیم داشت.
41
2-2-6-10 الگوریتم جستجوی دودویی
الگوریتم جستجوی دودویی چنانچه آرایه مورد جستجو مرتب شده باشد، روش بسیار کاراتری برای جستجو وجود دارد. این روش که به جستجوی دودویی موسوم است، با هربار مقایسه، نیمی از عناصر آرایه را از بازه جستجو حذف مینماید. در نتیجه جستجو در یک آرایه بزرگ با سرعت بسیار زیادی صورت میپذیرد. برای تشریح الگوریتم، فرض کنید آرایه موردنظر بصورت صعودی مرتب شده است. ابتدا عنصر وسط آرایه را پیدا کرده و داده مورد جستجو را با آن مقایسه میکنیم. سه حالت ممکن است رخ دهد: اگر داده مورد جستجو با عنصر وسط آرایه مساوی باشد، داده پیدا شده و مکان آن را باز میگردانیم. اگر داده مورد جستجو از عنصر وسط آرایه کوچکتر باشد، بنابراین باید در نیمه اول آرایه به دنبال آن جستجو نماییم. اگر داده مورد جستجو از عنصر وسط آرایه بزرگتر باشد، بنابراین باید در نیمه دوم آرایه به دنبال آن جستجو نماییم. چنانچه حالت اول رخ دهد، جستجو پایان یافته و مکان داده بازگردانده میشود. اما اگر حالت دوم یا سوم رخ دهد، عملیات جستجو به روش فوق مجددا برای نیمه اول یا نیمه دوم آرایه تکرار میشود. بدین ترتیب بازه مورد جستجو به نیمی از آرایه کاهش مییابد. عملیات تا زمانی ادامه مییابد که یا داده مورد نظر پیدا شود و یا بازه مورد جستجو آنقدر کوچک شود که دادهای باقی نماند (یعنی طول بازه مورد جستجو به صفر برسد)، که در اینصورت داده در آرایه وجود ندارد.
42
2-2-6-10 الگوریتم جستجوی دودویی
الگوریتم جستجوی دودویی … < 23 = x 24 < داده پیدا شد 25 48 … > 48 = x 49 داده پیدا شد 50 … 50 < 73 > x = 74 99 داده پیدا شد 75 99 … > 99
43
2-2-6-10 الگوریتم جستجوی دودویی
الگوریتم جستجوی دودویی int binarySearch(int A[], int n, int x) { int low, high, mid; low = 0; high = n-1; while (low <= high) { mid = (low + high) / 2; if (x == A[mid]) return(mid); else if (x < A[mid]) high = mid-1; else low = mid + 1; } return(-1);
44
2-2-6-10 الگوریتم جستجوی دودویی
الگوریتم جستجوی دودویی حد پایین 8 1 11 2 23 3 35 23 4 42 5 53 6 58 7 62 8 71 9 78 حد بالا
45
2-2-6-10 الگوریتم جستجوی دودویی
الگوریتم جستجوی دودویی int recBinarySearch(int A[], int low, int high, int x) { int mid; if (low > high) return(-1); mid = (low + high) / 2; if (x == A[mid]) return(mid); else if (x < A[mid]) return(recBinarySearch(A, low, mid-1, x)); else return(recBinarySearch(A, mid+1, high, x)) ; } نحوه فراخوانی اولیه این تابع برای جستجوی داده 52 در آرایه 100 عنصری data بصورت است: recBinarySearch(data, 0, 99, 52)
46
2-2-6-10 الگوریتم جستجوی دودویی
الگوریتم جستجوی دودویی برای محاسبه زمان مورد نیاز یک جستجو، باید به این نکته توجه کرد که با هر مقایسه، بازه جستجو نصف می شود. بدترین حالت زمانی است که داده اصلا پیدا نشود و یا در آخرین مقایسه (زمانی که تنها یک عنصر باقی مانده است) پیدا شود. سوال اینجاست که چند بار می توان اندازه آرایه را نصف کرد تا سرانجام به یک عنصر رسید؟ بعنوان مثال در یک آرایه با عنصر، تنها به 20 مقایسه نیاز است. به همین دلیل جستجوی دودویی یکی از بهترین روشهای جستجو محسوب می گردد.
47
الگوریتم ادغام یکی دیگر از الگوریتمهای مفید، ادغام دو آرایه مرتب است. ادغام دو آرایه مرتب به معنای ایجاد یک آرایه مرتب دیگر است که حاوی تمام عناصر دو آرایه اولیه باشد. یک روش ضعیف برای این کار آن است که ابتدا عناصر هر دو آرایه را در آرایه جواب کپی کنیم و سپس آرایه جواب را مرتب نماییم. اما مرتب سازی آرایه جواب زمان زیادی را صرف خواهد کرد. خوشبختانه الگوریتم بهتری وجود دارد که در آن نیازی به مرتب سازی نهایی آرایه جواب نیست. طرح کلی این الگوریتم به شرح زیر است: یک شمارنده برای هریک از دو آرایه در نظر بگیرید و آنها را برابر صفر قرار دهید. در هر مرحله، دو عنصری را که شمارندهها برروی آنها قرار دارند، با یکدیگر مقایسه نمایید؛ عنصر کوچکتر را به آرایه جواب منتقل کرده و شمارنده مربوط به آن را یک واحد افزایش دهید. این مرحله را تا پایان یافتن یکی از دو آرایه تکرار کنید. در پایان، تمام عناصر باقیمانده از آرایه ناتمام را به ترتیب به آرایه جواب منتقل نمایید.
48
الگوریتم ادغام 17 8 8 32 14 14 49 43 17 56 52 32 64 43 73 49 52 56 64 73
49
الگوریتم ادغام void merge(int A[], int na, int B[], int nb, int C[], int &nc) { int i=0, j=0, k=0; while (i<na && j<nb) { if (A[i] < B[j]) { C[k] = A[i] ; i++ ; } else if (A[i] > B[j]) { C[k] = B[j] ; j++ ; else { j ++ ; k++ ; for (; i<na; i++, k++) C[k] = A[i]; for (; j<nb; j++, k++) C[k] = B[j]; nc = k;
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.