0% found this document useful (0 votes)
542 views48 pages

Data Structure in C

Uploaded by

shekharchndr
Copyright
© Attribution Non-Commercial (BY-NC)
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOC, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
542 views48 pages

Data Structure in C

Uploaded by

shekharchndr
Copyright
© Attribution Non-Commercial (BY-NC)
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOC, PDF, TXT or read online on Scribd
You are on page 1/ 48

‫ساختمان داده‌ها ‪:‬‬

‫هر ساختمان داده يك سه تايي به صورت ( ‪ ) D,F,R‬مي‌باشد كه در آن ‪ D‬مجموعه دامنه(‪،)Domain‬‬


‫‪ F‬مجموعه توابع(‪ )Functions‬و ‪ R‬مجموعه قوانين حاكم بر ساختمان داده است‪)Rules( .‬‬

‫به عنوان مثال‬


‫اگر بخواهيم ساختمان داده صفهاي يك فروشگاه زنجيره اي را در نظر بگيريم مجموعه ‪ D‬به صورت زير‬
‫معرفي مي‌شود‪.‬‬
‫}… ‪ ,‬صف پوشاك ‪ ،‬صف مواد بهداشتي { =‪D‬‬
‫حداقل توابعي كه در اين ساختمان داده به كار گرفته مي‌شود عبارتند از‪:‬‬
‫‪ )1‬تابع ‪ Creat‬براي ايجاد صف‬
‫‪ )2‬تابع ‪ Isfull‬براي تشخيص پر بودن صف‬
‫‪ )3‬تابع ‪ Add‬براي اضافه كردن يك فرد جديد به صف‬
‫‪ )4‬تابع ‪ is Empty‬جهت تشخيص خالي بودن صف‬
‫‪ )5‬تابع ‪ Delete‬براي خارج كردن يك نفر از صف‬
‫دامنه و برد اين توابع به صورت زير تعيين مي‌گردد‪V:‬‬
‫‪Creat (name, max size ) : : = Queue‬‬
‫‪Is full (name,max size) : : = Boolean‬‬
‫)‪Add (item,queue‬‬ ‫‪: : = Queue‬‬
‫‪Is Empty (name): : = Boolean‬‬
‫‪Delete (queue ) : : = Item‬‬

‫توجه داريم كلمه ‪ Queue‬مجموعه تمام صف هاي است كه در اين فروشگاه وجود دارد و ‪ queue‬يك‬
‫صف به خصوص مثالً صف لوازم التحرير است ‪.‬‬
‫ً‬
‫همين طور ‪ Item‬مجموعه تمام مشتريان صف است و ‪ item‬يك فرد به خصوص مثال آقاي احمدي است‪.‬‬
‫قوانين‬
‫قوانيني كه بر ساختمان داده صف حكمفرماست عبارتند‪ V‬از‪:‬‬
‫‪ .1‬از صف خالي نمي توان فردي حذف كرد‪.‬‬
‫‪ .2‬به صفي كه پرشده نمي توان فردي اضافه كرد‪.‬‬
‫‪ .3‬همواره اولين نفر از صف خارج مي شود‪.‬‬
‫‪ .4‬همواره فرد جديد به انتهاي صف اضافه مي شود‪.‬‬

‫تذكر‪ :‬ممكن است توابع ديگري نيز به اين ساختمان داده اضافه كنيم مثالً تابع ‪ Merge‬براي ادغ‪VV‬ام دو ص‪VV‬ف‬
‫در يكديگر يا تابع ‪ Split‬براي شكاف يك صف به دو صف كوتاهتر و براي اين تواب‪VV‬ع ن‪VV‬يز مي ت‪VV‬وانيم ق‪VV‬انون‬
‫تعيين كنيم ‪.‬‬

‫مقايسه الگوريتم‌ها‪:‬‬

‫الگوريتم هاي مختلف را از دو جهت مي‌توان مقايسه كرد‪:‬‬


‫يكي حافظه مصرفي و ديگري سرعت اجراي الگوريتم ها‪ .‬حافظة مورد ني‪V‬از ه‪V‬ر الگ‪V‬وريتم ‪ ،‬را ب‪V‬ه دقت مي‬
‫توان تعيين‪ V‬كرد مثالً مي دانيم هر متغير صحيح ‪ 2‬بايت و هر متغير اعشاري ‪ 4‬بايت و هر متغير ك‪VV‬اراكتري‬
‫يا حرفي ‪ 1‬بايت حافظه مي گيرد‪.‬‬
‫ضمن اينكه حافظه مورد نياز براي دستور العمل ها را نيز مي دانيم ‪ ،‬بدين ترتيب مي توان ب‪VV‬دقت تع‪VV‬يين‬
‫كرد كه يك الگوريتم چند بايت حافظه مصرف مي كند و بين دو الگوريتم كه كار يكس‪VV‬اني انج‪VV‬ام مي دهن‪VV‬د مي‬
‫توانيم آن را كه حافظه كمتري مصرف مي كند تعيين كنيم‪ ،‬اما در اين درس به حافظه مص‪VV‬رفي الگ‪VV‬وريتم ه‪VV‬ا‬
‫توجه چنداني نداريم زيرا حافظه كامپيوترهاي كنوني بسيار زياد است ضمن اينكه اف‪VV‬زايش حافظ‪VV‬ه ب‪VV‬ه س‪VV‬ادگي‬
‫امكان پذير است (حافظه ارزان مي باشد)‬

‫اما نكته مهم‌تر ‪ :‬هنگام مقايسه الگوريتم ها بررسي سرعت آنهاست ‪ ،‬بديهي است هرچه تعداد دستور العمل ها‬
‫در يك الگوريتم كمتر باشد آن الگوريتم سريع ت‪VV‬ر اس‪VV‬ت ‪ . .‬بن‪VV‬ابراين اب‪VV‬زاري ني‪VV‬ازي داريم ت‪VV‬ا ش‪VV‬مار ي‪VV‬ا تع‪VV‬داد‬
‫دستور العمل ها را تعيين كند که به اين ابزار اصطالحا ً تابع ‪ O‬اطالق مي کنيم ‪.‬‬

‫‪1‬‬
‫تعريف دقيق و رياضي تابع ‪ O‬به صورت زير است ‪:‬‬

‫اگر دنباله ‪ n ‬‬


‫‪‬واگرا باشد (به سمت بي نهايت برود) آن گاه مي گوئيم مرتبه بي نه‪V‬ايت آن مانن‪V‬د مرتب‪V‬ة‬
‫دنباله ‪ n p ‬است‪ ،‬اگر عدد مثبتي مانند ‪ K‬وجود داشته باشد به طوري كه‬

‫‪ n‬‬
‫‪ K miL‬‬
‫‪‬‬ ‫‪K‬‬ ‫‪n ‬‬
‫‪np‬‬
‫نمادي كه براي مرتبه به كار مي رود به شکل زير است ‪:‬‬
‫‪ n O n‬‬ ‫‪p‬‬
‫‪‬‬
‫‪4n 3  5‬‬
‫‪‬را تعيين‪ V‬كنيد‪V.‬‬ ‫‪n‬‬ ‫{‪‬‬
‫‪n 3‬‬
‫‪‬‬ ‫مثال ‪:‬مرتبه دنباله‬

‫‪4n 3  5‬‬
‫‪ n‬‬ ‫‪n 3‬‬ ‫‪4n 3  5‬‬
‫‪miL‬‬ ‫‪n ‬‬ ‫‪‬‬
‫‪miL‬‬ ‫‪‬‬
‫‪n‬‬ ‫‪‬‬
‫‪miL‬‬ ‫‪n ‬‬ ‫‪p 1‬‬
‫‪n p‬‬ ‫‪n‬‬ ‫‪p‬‬
‫‪n‬‬ ‫‪ 3n‬‬ ‫‪p‬‬

‫‪ n‬‬ ‫‪4n 3  5‬‬


‫‪miL‬‬ ‫‪n ‬‬ ‫‪‬‬
‫‪miL‬‬ ‫‪n ‬‬ ‫‪4‬‬ ‫‪K 4‬‬
‫‪np‬‬ ‫‪n 3  3n‬‬ ‫‪2‬‬

‫‪P+1=3  P=2‬‬

‫‪4n 3 _ 5‬‬
‫‪ O (n 2,) K  4‬‬
‫‪n 3‬‬

‫مثال كنكور‬
‫زمان اجرا يا شمار قطعه برنامه زير را تعيين كنيد‪V.‬‬
‫; ‪X=0‬‬
‫) ‪For ( i=1 ; i <= n ; i++‬‬
‫) ‪For ( j=1 ; j <= n ; j++‬‬
‫{‬
‫;‪X= X +1‬‬
‫;‪Y = Z*X‬‬
‫;‪Z=Y-X‬‬
‫}‬

‫;) ‪Printf ( "%d%d%d", X , Y , Z‬‬


‫مثال‪ :‬زمان اجرا برنامه زير را تعيين كنيد‪.‬‬
‫) ‪For ( i=1 ; i <= n ; i++‬‬
‫) ‪For ( j=1 ; j <= i ; j++‬‬
‫;‪X++‬‬

‫فرمول هاي مهم‬


‫روابط زير در مورد پيداكردن زمان اجرا بسيار مفيد مي باشد‪.‬‬
‫‪n‬‬

‫‪‬‬ ‫‪1  n O n K‬‬


‫‪, 1‬‬
‫‪i1‬‬
‫‪n‬‬
‫‪n n  1 ‬‬ ‫‪1‬‬
‫‪‬‬ ‫‪ O n  K‬‬
‫‪2‬‬
‫‪i‬‬ ‫‪, ‬‬
‫‪i1‬‬ ‫‪2‬‬ ‫‪2‬‬

‫‪2‬‬
n n  1 2n  1 
 
n
1
 i1
i2 
6
 O n3 K
, 
3
n
n (n  1 )
2 2
1
i1 i 3  4  O (n 4 ) K,  4
.
.
 
n
1
i1
im O n m 1 K, 
m 1
‫مثال سوال امتحان‬
For ( i=1 ; i <= n ; i++ )
For ( j=1 ; j <= i ; j++ )
For ( k=1 ; k <= i * j ; k++)
X++;

)Arrays( ‫آرايه ها‬


‫ هر جا كه با داده هاي مرتب سرو‬،‫هر آرايه تعدادي خانه متوالي از حافظه است كه از يك جنس مي باشند‬
‫نبه‬VV‫ه از ش‬VV‫ت ك‬VV‫ر اس‬V‫ عنص‬7 ‫ه داراي‬VV‫كار داشته باشيم مي توانيم از آرايه استفاده كنيم مثالً آرايه روزهاي هفت‬
‫کل‬VV‫شروع مي شود و به جمعه ختم مي گردد همين طور آرايه سال هاي تحصيل يك فرد در دانشگاه به اين ش‬
. ‫مي باشد‬
Structure array is
Objects : A set of pairs < index , value > where for each value of index there
is a value from the set item . index is a finite ordered set of one or more
dimensions , for example , {0, … ,n-1} for one dimention , {(0,0), (0,1) , (0,2) ,
(1,0) , (1,1) , (1,2) , (2,0) , (2,1) , (2,2)} for two dimentions , etc .
Functions :

For all A  Array , i  index , x  item , j , size  integer


Array Create(j,list) ::= return an array of j dimentions where list is a j-
tuple whose ith element is the size of
the ith dimention. Items are undefined .
Item Retrieve (A,i) ::= if ( i  index ) return the item associated with
index value i in array A
Else return eror
Array Store (A,i,x) ::= if (i in index)
Return an array that is identical to array A
except the new pair <i,x> has been inserted
else return eror .
end Array
‫ورد‬VV‫د مثالً در م‬VV‫ديس) مي‌باش‬VV‫ ان‬،‫دار‬VV‫ورت (مق‬VV‫ه ص‬VV‫رتب ب‬VV‫اي م‬V‫ه از زوج ه‬VV‫ك مجموع‬VV‫ع ي‬VV‫ه در واق‬VV‫ر آراي‬V‫ه‬
: ‫روزهاي هفته آرايه به صورت زير است‬
‫) و‬2 ‫ و (يك شنبه و‬... ‫) و‬7‫(جمعه و‬
) 1‫(شنبه و‬
: ‫توابع اصلي آرايه‬
‫راي‬VV‫ ب‬Store ‫ري‬VV‫ ديگ‬، ‫اد‬VV‫راي ايج‬VV‫ ب‬Create ‫د يكي‬VV‫سه تابع اصلي در ساختمان داده هر آرايه حضور دارن‬
. ‫ براي بازيابي عناصر آرايه است‬Retrieve ‫ذخيره سازي آرايه و سومي‬

3
‫ساختمان دادة آرايه ها ‪Structure Array is‬‬

‫مجموعه اي از زوج ها كه براي هر مقدار انديس يك مقدار از مجموعه عناصر( ‪ ) item‬در نظ‪VV‬ر گرفت‪VV‬ه ‪:‬‬
‫‪ Objects‬مي شود‪ .‬انديس مجموعه متناهي مرتب از يك بع‪VV‬د ي‪VV‬ا بيش‪V‬تر مثالً ي‪VV‬ك مجموع‪VV‬ه ان‪VV‬ديس ي‪V‬ك بع‪VV‬دي‬
‫است {‪}n,…,1,2‬و يك مجموعه انديس دو بعدي است‪)2,2(,)2,1(,)1,2(,)1,1({{.‬‬
‫‪Functions‬توابع‬
‫تابع ‪ Create‬خروجي آرايه‬
‫يك آرايه ‪ j‬بعدي اعالن مي كند برد بعد ‪ i‬توسط عنصر ‪ i‬ام ليست داده ش‪VV‬ده اس‪VV‬ت ض‪VV‬منا ً عناص‪VV‬ر آراي‪VV‬ه از‬
‫جنس يا نوع ‪ item‬هستند‪ j .‬و ‪ list‬و ‪ item‬مهم‌اند‪.‬‬
‫; ] ‪int a [ 10‬‬
‫تابع ‪Retrieve‬‬
‫اگر ‪ i‬يك انديس از مجموعه ‪ A‬باشد در اين صورت عنص‪V‬ر متن‪VV‬اظر ب‪V‬ا آن ان‪V‬ديس ‪ i‬در آراي‪VV‬ه ‪ A‬برگردان‪V‬ده‬
‫مي شود درغير اين صورت خطا‪.‬‬
‫ورودي (يك آرايه ‪ A‬و انديس ‪ i‬و ‪) item x‬‬ ‫تابع ‪Store‬‬
‫= ‪store (A , i , x) : Array: :‬‬
‫اگر ‪ i‬در مجموعه انديس هاي ‪ A‬باشد در اين صورت آرايه ‪ A‬زوج جديد(( ‪ i , x‬اضافه مي گردد يا درج‬
‫مي شود و حاصل كه يك آرايه جديد است برگردانده مي شود‪ ،‬در غير اين صورت ‪ Error‬مي دهد‪V.‬‬

‫جبر چند جمله اي‪:‬‬


‫منظور از جبر چند جمله اي ها يعني تعريف تعدادي چند جمله اي و سپس انجام محاسبات ساده رياضي نظير‬
‫جمع ‪ ،‬ضرب ‪ ،‬تقسيم ‪ ،‬مشتق گيري‪ ... ،‬روي چند جمله اي ها است‪.‬‬

‫يك چند جمله اي درجه ‪ n‬داراي شكل كلي زير است‪:‬‬ ‫‪‬‬
‫‪n‬‬

‫‪‬‬ ‫‪i 0‬‬


‫‪C Xi i C ‬‬
‫‪‬‬
‫‪‬‬
‫‪ C 1X  C 2X 2 ...  C nX‬‬ ‫‪n‬‬

‫‪C‬ها ضريب و اعداد (‪ )n,…,1‬توان مي‌باشند‪.‬‬ ‫‪i‬‬

‫‪A(X)= 3x  5 x  2 x  4‬‬
‫‪7‬‬ ‫‪3‬‬

‫)‪ A(X‬يك چند جمله اي درجه ‪ 7‬مي باشد‪ ،‬در واقع چند جمله اي )‪ A(x‬را مي توان به صورت زير نمايش‬
‫داد‪:‬‬
‫) ‪3 x 7  0 x 60 x 5  0 x 4  ( 5 )x 3  0 x 2  2 x  ( 4‬‬
‫يك راه مناسب‬
‫يك راه مناسب براي نمايش اين چند جمله اي استفاده از آرايه است‪ ،‬مي توانيم آرايه ‪ 8‬عنصري تعريف‬
‫كنيم و ضرايب چند جمله اي )‪ A(x‬را در آن آرايه قرار دهيم‪ .‬با اين حساب چند جمل‪VV‬ه اي )‪ A(x‬در آراي‪VV‬ه ‪a‬‬
‫به صورت زير ذخيره مي شود‪:‬‬
‫‪a‬‬
‫‪0‬‬ ‫‪0‬‬ ‫‪3‬‬ ‫‪0‬‬ ‫‪0‬‬ ‫‪0‬‬ ‫‪5-‬‬ ‫‪0‬‬ ‫‪2‬‬ ‫‪4-‬‬

‫براي‬
‫يافتن مجموع‬

‫اگر بخواهيم )‪ A(x‬را با يك چند جمله اي ديگر مانند )‪B(x‬جمع كنيم بايد )‪ B(x‬را در يك آرايه ‪ 10‬عنصري‬
‫به نام ‪ b‬به صورت ‪ =B(x) X 9  2X 7  5X 3  X 2‬زير ذخيره كنيم ‪:‬‬

‫‪1‬‬ ‫‪0‬‬ ‫‪2-‬‬ ‫‪0‬‬ ‫‪0‬‬ ‫‪0‬‬ ‫‪5‬‬ ‫‪1‬‬ ‫‪0‬‬ ‫‪0‬‬
‫‪b‬‬
‫سپس براي يافتن مجموع )‪ A(x)+ B(x‬بايد ابتدا دو خانه صفر در سمت چپ آرايه ‪ a‬ق‪V‬رار دهيم ت‪V‬ا دو چن‪VV‬د‬
‫جمله اي هم درجه شود‪ .‬سپس با استفاده از قطعه برنامه زير مي توانيم حاصل دو چند جمله اي زير را داخل‬
‫آرايه قرار دهيم‪:‬‬
‫)‪FOR ( i = 0 ; i <= 9 ; i++‬‬

‫‪4‬‬
‫;]‪C[i] = a[i] + b[i‬‬
‫تذكر‪:‬‬
‫در ح‪VV‬الت كلي اگ‪VV‬ر )‪ A(x‬درج‪VV‬ه ‪ m‬و )‪ B(x‬درج‪VV‬ه ‪ n‬باش‪VV‬د‪ ،‬زم‪VV‬ان اج‪VV‬راي الگ‪VV‬وريتم ف‪VV‬وق ب‪VV‬ه ص‪VV‬ورت‬
‫))‪ O (max(m,n‬خواهد بود‪.‬‬
‫روش قبل اولين روشي است كه به ذهن مي رسد اما كارايي چنداني ندارد‪ ،‬مثالً فرض كني‪VV‬د بخ‪VV‬واهيم دو چن‪VV‬د‬
‫‪ =P(x)20001‬و ‪ =Q(x) x 2  3‬را با هم جمع كنيم ‪.‬‬‫‪x‬‬ ‫جمله اي ‪ 5‬‬
‫اوالً براي ذخيره سازي )‪ P(x‬به آرايه اي به طول ‪ 1001‬نياز داريم كه ‪ 999‬خانه آن ص‪VV‬فر اس‪VV‬ت ض‪VV‬منا ً‬
‫براي جمع )‪ Q(x‬و )‪ P(x‬بايد سمت چپ ‪ Q(x) 998‬صفر ق‪V‬رار دهيم ت‪V‬ا هم درج‪VV‬ه ش‪V‬ود‪ ،‬ب‪VV‬ا توج‪V‬ه ب‪V‬ه اين‬
‫مشكالت اين روش نه از لحاظ حافظه مطلوب است و نه از لحاظ سرعت اجرا ‪ ،‬زيرا عمالً باي‪VV‬د از حلق‪VV‬ه اي‬
‫به طول ‪ 1001‬جهت جمع چند جمله اي استفاده كنيم‪ ،‬به همين خاطر هم‪VV‬انطور ك‪VV‬ه در رياض‪VV‬يات از نوش‪VV‬تن‬
‫جمالت با ضريب صفر خودداري مي كنيم‪ ،‬در جبر چند جمله اي ها ن‪VV‬يز جمالت ص‪VV‬فر را ذخ‪VV‬يره نمي ك‪VV‬نيم‪.‬‬
‫اگر بخواهيم تنها جمالت غير صفر را ذخيره كنيم همراه با ضريب( ‪ ، )Coeficient‬بايد حتما ً توان يا نم‪VV‬ا [‬
‫‪ ]Exponet‬را نيز ذخيره كنيم‪.‬‬
‫‪Coef‬‬
‫‪Exp‬‬
‫به همين خاطر هر جمله يك چند جمله اي يك ساختار دو عنصري خواهد بود چنين س‪VV‬اختاري را در زب‪VV‬ان ‪C‬‬
‫مي توانيم هنگام تعريف نوع داده (‪ )Typedef‬تعريف كنيم‪ ،‬در واقع هر جمل‪VV‬ه (‪ )Term‬ي‪VV‬ك چن‪VV‬د جمل‪VV‬ه اي‬
‫ساختار زير را دارد‪:‬‬
‫{ ‪Typedef struct‬‬
‫; ‪float coef‬‬
‫; ‪int expon‬‬
‫; ‪} term‬‬
‫براي تعريف يك چند جمله اي مي توانيم در قس‪V‬مت متغيره‪V‬ا (‪ )VAR‬چن‪V‬د جمل‪V‬ه اي ‪ terms‬را ب‪V‬ه ص‪V‬ورت‬
‫زير تعريف كنيم‪:‬‬
‫; ]‪VAR term terms [1000‬‬
‫براي ذخيره ساختن مقدار در اين ساختمان داده (همان تابع‪ ) Store‬ب‪V‬ا اس‪VV‬تفاده از عملگ‪VV‬ر(‪ )dot‬توس‪VV‬ط‬
‫نقطه (‪ )0‬مقداردهي را انجام مي دهيم ‪ .‬مثالً اگر بخواهيم جمله اول ‪ terms‬را مق‪V‬دار دهيم در قس‪V‬مت ‪coet‬‬
‫عدد ‪ 2‬و در قسمت ‪ exp‬عدد ‪ 1000‬را قرار مي دهيم‪.‬‬
‫‪Start A finishA start B finish B free‬‬
‫‪0‬‬ ‫‪1‬‬ ‫‪2‬‬ ‫‪3‬‬ ‫‪4‬‬ ‫‪999‬‬
‫‪Coef‬‬ ‫‪2‬‬ ‫‪5‬‬ ‫‪1‬‬ ‫‪3-‬‬
‫‪exp 1000‬‬ ‫‪0‬‬ ‫‪2‬‬ ‫‪0‬‬

‫;‪Term[1].Coef = 2‬‬

‫;‪Term[1].exp=1000‬‬

‫تمام جمالت چند جمله اي هاي )‪ A(x‬و )‪ B(x‬را مي توانيم به صورت زير در آرايه عمومي ‪terms‬‬
‫قرار دهيم ‪ .‬براي اين منظور بايد خانه شروع چند جمله اي (‪ a) Start A‬و پايان چند جمله اي (‪)finishA‬‬
‫‪ ،a‬همچنين شروع و پايان چند جمله اي )‪ B(x‬تعيين شود ضمنا ً اولين خانه خالي چند جمله اي ‪ terms‬باي‪VV‬د‬
‫با يك متغير سراسري به نام ‪ Free‬مشخص باشد‪.‬‬

‫جمع چند جمله اي ها( ‪)Padd‬‬


‫در قسمت قبل ديديم كه چگونه مي توان يك چند جمله اي را به صورت فشرده يعني بدون در نظر گرفتن‬
‫جمالت صفر ذخيره كرد‪ ،‬در اينجا طي الگوريتم ( (‪ padd‬حاصل جم‪VV‬ع چن‪VV‬د جمل‪VV‬ه اي ه‪VV‬اي )‪ A(x‬و )‪B(x‬‬
‫را تعيين مي كنيم براي اين منظور بايد روي تك تك جمالت چند جمله اي )‪ A(x‬و همين ط‪VV‬ور )‪ B(x‬ح‪VV‬ركت‬
‫كنيم‪ ،‬ب‪VV‬راي اين منظ‪VV‬ور از دو متغ‪VV‬ير ‪ a‬و‪ b‬اس‪VV‬تفاده مي ك‪VV‬نيم ‪،‬متغ‪VV‬ير ‪ a‬روي جمالت )‪ A(x‬ح‪V‬ركت مي كن‪VV‬د‬
‫يعني محدوده تغييرات آن از ‪ start A‬تا ‪ finish A‬مي باشد به همين ترتيب متغ‪V‬ير ‪ . b‬در ه‪V‬ر ب‪V‬ار قس‪V‬مت‬

‫‪5‬‬
‫مي توان جمله اي را كه ‪ a‬به آن اشاره مي‌كند با قسمت توان جمله اي را كه ‪ b‬ب‪VV‬ه آن اش‪VV‬اره مي كن‪VV‬د مقايس‪VV‬ه‬
‫مي‌كنيم ( اين مقايسه توسط دستور ‪ )Compare (terms(a) . exp ) , terms (b) . exp‬انجام‬
‫مي‌شود‪).‬‬
‫سه حالت ممكن است رخ دهد‪:‬‬
‫الف) ‪terms (a) . exp > terms (b) . exp‬‬
‫در اين حالت جمله چند جمل‪VV‬ه اي )‪ A(x‬ت‪VV‬واني بزرگ‪VV‬تر از چن‪VV‬د جمل‪VV‬ه اي )‪ B(x‬دارد پس باي‪VV‬د عين‪V‬ا ً آن جمل‪VV‬ه‬
‫)‪ A(x‬را در چند جمله اي حاصل جمع كه آن را )‪ C(x‬مي ناميم بنويس‪VV‬يم (عم‪VV‬ل نوش‪VV‬تن جمل‪VV‬ه جدي‪VV‬د در چن‪VV‬د‬
‫جمله اي )‪ C(x‬توسط زير برنامه ‪ Next Term‬انج‪VV‬ام مي ش‪VV‬ود) در نه‪VV‬ايت پس از نوش‪VV‬تن جمل‪VV‬ه )‪ A(x‬در‬
‫)‪ C(x‬يك واحد به ‪ a‬اضافه مي كنيم زيرا تكليف آن جمله مشخص شود‪.‬‬

‫ب)‬
‫حالت مساوي ‪terms(s) . exp = terms(b) . exp‬‬
‫در اين حالت جمله ه‪V‬اي )‪ A(x‬و )‪ B(x‬ت‪V‬وان مس‪V‬اوي دارن‪V‬د س‪V‬پس باي‪V‬د ض‪V‬رايب آنه‪V‬ا ب‪V‬ا هم جم‪V‬ع ش‪V‬ود اگ‪V‬ر‬
‫مجموع ضرايب مخالف صفر بودآنگاه حاصل جمع را به همراه يكي از توان ها در چن‪VV‬د جمل‪VV‬ه اي )‪ C(x‬مي‬
‫نويسيم‪ ،‬اما اگر مجموع ضرايب صفر شد در )‪ C(x‬چيزي نمي نويسيم‪ ،‬در نهايت چه مجموع ضرايب ص‪VV‬فر‬
‫باشد و چه غير صفر يك واحد به ‪ a‬اضافه مي كنيم و يك واحد هم به ‪.b‬‬
‫ج) ‪terms(a) . exp < terms(b) . exp‬‬
‫در اين حالت چون كه توان جمله چند جمله اي )‪ B(x‬بزرگتر است آن جمله )‪ B(x‬را در )‪ C(x‬مي نويسيم و‬
‫سپس ‪ b‬را يك واحد پيش مي بريم‪.‬‬
‫عمليات فوق را آنقدر ادامه مي دهيم تا يكي از چن‪VV‬د جمل‪VV‬ه اي ه‪VV‬اي )‪ A(x‬تم‪VV‬ام ش‪VV‬ود‪ A(x) ،‬زم‪VV‬اني تم‪VV‬ام مي‬
‫شود كه ‪ a>finish A‬باشد به همين ترتيب )‪ B(x‬زماني تمام مي شود كه ‪ b> finish B‬شود هنگامي ك‪VV‬ه‬
‫يكي از چند جمله اي ها تمام شد عينا ً جمالت چند جمل‪VV‬ه اي ديگ‪VV‬ر را در )‪ C(x‬مي نويس‪VV‬يم‪ .‬در نه‪VV‬ايت ب‪VV‬راي‬
‫آنكه پايان چند جمله اي )‪ C(x‬مشخص شود ‪ Finish C = free- 1‬قرار مي دهيم ‪.‬‬

‫تابع الزم براي جمع دو چند جمله اي‬


‫)‪void padd (int starta , int finisha , int startb , int finishb , int *startd , int *finishd‬‬
‫{‬
‫‪/* add A (x) and B (x) to obtain D (x) */‬‬
‫; ‪float coefficient‬‬
‫; ‪*startd = avail‬‬
‫)‪while (starta <= finisha && startb <= finishb‬‬
‫{ ))‪switch (COMPARE (terms [starta] . expon, terms [startb] . expon‬‬
‫‪case -1 : /* a expon < b expon */‬‬
‫; )‪attach (terms [startb] . coef , terms [startb] . expon‬‬
‫; ‪startb++‬‬
‫; ‪break‬‬
‫‪case 0 : /* equal exponents */‬‬
‫; ‪coefficient = terms [starta] .coef + terms [startb] . coef‬‬
‫)‪if (coefficient‬‬
‫; )‪attach (coefficient , terms [starta] .expon‬‬
‫; ‪starta++‬‬
‫; ‪startb++‬‬
‫; ‪break‬‬
‫‪case 1 : /* a expon > b expon */‬‬
‫; )‪attach (terms [starta] . coef , terms [starta] .expon‬‬
‫; ‪starta++‬‬
‫}‬
‫‪/* add in remaining terms of A (x) */‬‬

‫‪6‬‬
For (; starta <= finisha ; starta++)
Attach (terms [starta] .coef , terms [starta] . expon) ;
/* add in remaining terms of B (x) */
For ( ; startb <= finishb ; startb++)
Attach (terms [startb] . coef , terms [startb] . expon) ;
*finishd = avail-1 ;
}
.‫ را بدست مي آورد‬C ‫ را جمع مي كند و‬b ‫ و‬a )2
.‫) متغيرها را معرفي مي كند‬3
‫)خط مقداردهي آغازين‬5
.‫ تمام نشده‬B(x) ‫ و‬A(x) ‫) هنوز‬6
.‫ مي گذاريم‬t ‫) مجموع ضرايب در‬9
.‫ صدا زده مي شود‬Attach ‫) پروسيجر‬10
  efoc
pxe /  C  ‫ دو متغير ورودي مي گيرد‬New term
term ‫ طول آرايه‬Max term
.‫ را بنويس‬A(x) ‫) جمالت باقيمانده از‬22
finish A ‫ را مي نويسد تا زماني كه برسد به‬a ‫ جمالت‬27 ‫) تا‬23
.‫ برسد‬finish B ‫ را مي نويسد تا زماني كه به‬b ‫ جمالت‬33 ‫) تا‬29
V.‫ را مشخص مي كند‬C ‫) پايان‬34
‫تابعي براي اضافه نمودن يک جمله جديد‬
void attach (float coefficient , int exponent )
{
/* add a new term to the polynomial */
if (avail >= MAX_TERMS)
{
fprintf (stderr , "too many terms in the polynomial \n") ;
exit (1) ;
}
Terms [avail] . coef = coefficient ;
Terms [avail++] .expon = exponent ;
}
Start finish start finish free f f f finish free
A A B B C
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
16
‫ ضريب‬2 4 6- 2 1 1- 4- 1 1 1 1 6- 2
Term
‫ توان‬7 5 1 0 9 7 5 3 9 7 3 1 0

x 9  x 7  x 3 6 x  2
A(x)= 2x 7 4 x 5  6 x  2
 c (x )  x 9  x 7  x 3  6 x  2
B(x)= x 9  x 7  4 x 5  x 3
: Bubble Sort ‫روش مرتب سازي حبابي‬
‫ سپس‬،‫ بزرگترين عنصر را به سمت انتهاي آرايه هل مي دهيم‬n ‫در اين روش ابتدا در آرايه اي به طول‬
)n-2( ‫ول‬VV‫ه ط‬VV‫ه اي ب‬VV‫ در آراي‬V‫د‬V ‫رار بع‬VV‫ در تك‬، ‫نيم‬VV‫رار مي ك‬VV‫ار را تك‬VV‫) همين ك‬n-1( ‫ول‬VV‫ه ط‬VV‫در آرايه‌اي ب‬
‫ه‬VV‫مت خان‬VV‫ه س‬VV‫تر را ب‬VV‫ر بزرگ‬VV‫ عنص‬2 ‫ول‬VV‫اين كار را مي كنيم و مرتبا ً آن را تكرار كرده تا در آرايه اي به ط‬

7
‫دوم هل مي دهيم‪ ،‬سپس يك حلقه با متغير ‪ i‬نياز داريم كه از ‪ n‬ت‪V‬ا ‪ ، 2‬يكي يكي كم مي ش‪V‬ود و ي‪V‬ك حلق‪V‬ه ب‪V‬ا‬
‫متغير ‪ J‬نياز داريم كه از‪ 1‬تا (‪ )i-1‬يكي يكي اضافه مي‌شود‪.‬‬
‫قطعه برنامه زير عمل مرتب سازي حبابي را انجام مي دهد‪:‬‬
‫) ‪For ( i = 1 ; i < n ; i++‬‬
‫) ‪For ( j = 1 ; j < n - i ; j++‬‬ ‫‪an‬‬
‫]‪if a [ j] > a [ j+1‬‬ ‫‪an-1‬‬
‫{‬ ‫‪a3‬‬
‫;]‪Temp = a [ j‬‬ ‫‪a2‬‬
‫;]‪a [ j] = a [ j+1‬‬
‫; ‪a [ j+1 ] = temp‬‬ ‫‪a1‬‬
‫}‬

‫‪i= 5‬‬ ‫‪27‬‬ ‫‪19‬‬ ‫‪41‬‬ ‫‪18‬‬ ‫‪20‬‬


‫‪19‬‬ ‫‪27‬‬ ‫‪18‬‬ ‫‪41‬‬ ‫‪41‬‬
‫‪20‬‬
‫‪19‬‬ ‫‪27‬‬ ‫‪18‬‬ ‫‪20‬‬ ‫‪41‬‬
‫‪i = 40‬‬
‫‪18‬‬ ‫‪27‬‬ ‫‪27‬‬
‫‪20‬‬
‫‪19 18‬‬ ‫‪20‬‬ ‫‪27‬‬ ‫‪41‬‬
‫‪i= 3‬‬
‫مقايسه مي شوند ولي جابجا نمي شوند ‪18 19‬‬
‫‪i=2‬‬
‫‪18‬‬ ‫‪19‬‬ ‫‪20‬‬ ‫‪27‬‬ ‫‪41‬‬
‫زمان اجرا‬
‫‪‬‬
‫‪2‬‬ ‫‪i1‬‬ ‫‪2‬‬ ‫‪i1‬‬ ‫‪2‬‬
‫) ‪(n (n  1‬‬ ‫‪3‬‬ ‫‪3‬‬
‫‪i n j13  ‬‬
‫‪3‬‬
‫‪i n j1‬‬
‫‪1 ‬‬
‫‪3 ( i 1 )  3‬‬
‫‪i n‬‬ ‫‪2‬‬
‫‪ 1 )  (n (n  1 ) 2 ‬‬
‫‪2‬‬
‫‪) O (n 2,) K ‬‬
‫‪2‬‬

‫ماتريس هاي اسپارس (تنك) ‪Sparse Matrix‬‬


‫ً‬
‫هر ماتريسي را كه تعداد صفرهاي آن زياد باشد ماتريس اسپارس مي گويند‪ ،‬معم‪VV‬وال م‪VV‬اتريس ه‪VV‬ايي ك‪VV‬ه بيش‬
‫از نيمي از عناصر آن ها صفر باشد جزو ماتريس هاي اسپارس در نظر گرفته مي ش‪VV‬وند‪ ،‬ام‪VV‬ا در عم‪VV‬ل اگ‪VV‬ر‬
‫در حدود ‪ 80‬درص‪V‬د عناص‪V‬ر ي‪VV‬ك م‪V‬اتريس ص‪V‬فر باش‪VV‬ند خاص‪V‬يت اس‪V‬پارس ب‪V‬ودن م‪V‬اتريس ب‪V‬ه ص‪V‬ورت ب‪VV‬ازه‬
‫مشخص مي شود‪ .‬مثالً ماتريس زير يك ماتريس اسپارس است ‪:‬‬
‫‪0‬‬ ‫‪0‬‬ ‫‪0‬‬ ‫‪0‬‬ ‫‪3‬‬ ‫‪0‬‬ ‫‪0‬‬
‫‪ 2‬‬ ‫‪0‬‬ ‫‪0‬‬ ‫‪0‬‬ ‫‪0‬‬ ‫‪0‬‬ ‫‪0 ‬‬
‫‪‬‬
‫‪0‬‬ ‫‪0‬‬ ‫‪0‬‬ ‫‪0‬‬ ‫‪0‬‬ ‫‪0‬‬ ‫‪0‬‬
‫‪A ‬‬ ‫‪‬‬
‫‪4‬‬ ‫‪0‬‬ ‫‪0‬‬ ‫‪0‬‬ ‫‪1‬‬ ‫‪0‬‬ ‫‪0‬‬
‫‪0‬‬ ‫‪3‬‬ ‫‪0‬‬ ‫‪0‬‬ ‫‪2‬‬ ‫‪7‬‬ ‫‪0‬‬
‫‪‬‬ ‫‪‬‬
‫‪ 0‬‬ ‫‪0‬‬ ‫‪0‬‬ ‫‪2‬‬ ‫‪0‬‬ ‫‪0‬‬ ‫‪0  6 7‬‬

‫همانطور كه مشاهده مي شود در اين ماتريس نزديك به ‪ 80‬درصد عناصر ص‪44‬فر هس‪44‬تند بن‪44‬ابراين ب‪44‬ه نظ‪44‬ر مي‬
‫رسد كه عناصر صفر را ذخيره نكنيم و تنها عناصر غير صفر را ذخيره كنيم‪ ،‬سپس باي‪44‬د عالوه ب‪44‬ر مق‪44‬دار ي‪44‬ك‬
‫عنصر صفر حتما ً محل آن يعني سطر و ستون را نيز ذخيره كنيم پس براي هر عنصر غير صفر باي‪44‬د ي‪44‬ك س‪44‬ه‬
‫تايي به صورت زير در نظر بگيريم ‪.‬‬
‫‪Row‬‬ ‫‪column‬‬ ‫‪Value‬‬

‫‪8‬‬
‫با اين حساب ماتريس اسپارس ‪ A‬در مثال قبل مي تواند به‬ ‫سطر‬ ‫ستون‬ ‫مقدار‬
‫صورت زير ذخيره شود‪:‬‬

‫‪ C‬فشرده شده ‪A‬‬ ‫‪A‬‬ ‫‪:‬‬ ‫‪1‬‬ ‫‪5‬‬ ‫‪3‬‬


‫‪2‬‬ ‫‪1‬‬ ‫‪2-‬‬
‫‪4‬‬ ‫‪1‬‬ ‫‪4‬‬
‫‪4‬‬ ‫‪5‬‬ ‫‪1-‬‬
‫‪5‬‬ ‫‪2‬‬ ‫‪3‬‬
‫‪5‬‬ ‫‪5‬‬ ‫‪2‬‬
‫‪5‬‬ ‫‪6‬‬ ‫‪7‬‬
‫‪6‬‬ ‫‪4‬‬ ‫‪2‬‬

‫براي آن كه اين ساختار سه قس‪VV‬متي را در زب‪VV‬ان ‪ C‬تعري‪VV‬ف ك‪VV‬نيم باي‪VV‬د در قس‪VV‬مت ن‪VV‬وع داده( ‪ ) Typedef‬ب‪VV‬ا‬
‫استفاده از دستور العمل ركورد ‪ Struct‬ن‪V‬وع داده ي‪V‬ك رك‪V‬ورد ‪ Matrix term‬را ب‪V‬ه ص‪V‬ورت زي‪V‬ر تعري‪V‬ف‬
‫كنيم‪:‬‬

‫‪#define max-terms 101‬‬


‫{ ‪Typedef struct‬‬
‫; ‪int col‬‬
‫; ‪int row‬‬
‫; ‪float value‬‬
‫; ‪} term‬‬
‫; ] ‪term a [ max-terms‬‬

‫و در نه‪VV‬ايت در قس‪VV‬مت متغيره‪VV‬ا( ‪ )var‬مي ت‪VV‬وانيم م‪VV‬اتريس اس‪VV‬پارس ‪ CA‬را ي‪VV‬ك آراي‪VV‬ه از جنس م‪VV‬اتريس‬
‫‪ Term‬تعريف كنيم‪:‬‬
‫‪Var‬‬ ‫; ] ‪Matrixterm ca [ max-terms‬‬
‫تذكر‪ :‬براي آنكه ابعاد ماتريس ‪ A‬در نظر گرفته شود خانه صفرم ‪ Ca‬را براي اين منظور در نظر گرفتيم ‪،‬‬
‫در خانه صفرم ‪ Ca‬به ترتيب تعداد سطرها‪ .‬تعداد ستون ها و تعداد عناصر غ‪VV‬ير ص‪VV‬فر م‪VV‬اتريس ‪ A‬را ق‪VV‬رار‬
‫مي دهيم ‪ ،‬پس عمالً ‪ Ca‬به صورت زير در نظر گرفته مي شود‪:‬‬
‫تعداد‪ V‬عناصرغير صفر تعداد ستون تعداد‪ V‬سطر‬

‫خانه‌ صفرم ‪Ca‬‬ ‫‪6‬‬ ‫‪7‬‬ ‫‪8‬‬


‫‪CA‬‬ ‫‪1‬‬ ‫‪5‬‬ ‫‪3‬‬
‫‪2‬‬ ‫‪1‬‬ ‫‪-2‬‬
‫‪4‬‬ ‫‪1‬‬ ‫‪4‬‬
‫‪4‬‬ ‫‪5‬‬ ‫‪-1‬‬
‫‪5‬‬ ‫‪2‬‬ ‫‪3‬‬
‫‪5‬‬ ‫‪5‬‬ ‫‪2‬‬
‫‪5‬‬ ‫‪6‬‬ ‫‪7‬‬
‫‪6‬‬ ‫‪4‬‬ ‫‪2‬‬

‫تذكر مهم‪ :‬همانطور ك‪VV‬ه در تعري‪VV‬ف ‪ Ca‬مش‪VV‬خص ش‪VV‬ده آراي‪VV‬ه ‪ Ca‬ي‪VV‬ك بع‪VV‬دي اس‪VV‬ت يع‪VV‬ني ب‪VV‬ه ص‪VV‬ورت زي‪VV‬ر‬
‫مي‌باشد‪:‬‬

‫‪9‬‬
‫خانه صفرم‬ ‫خانه يكم‬ ‫خانه دوم‬ ‫خانه هشتم‬
‫‪6‬‬ ‫‪7‬‬ ‫‪8‬‬ ‫‪1‬‬ ‫‪5‬‬ ‫‪3‬‬ ‫‪2‬‬ ‫‪1‬‬ ‫‪2‬‬ ‫‪6‬‬ ‫‪4‬‬ ‫‪2‬‬

‫براي سادگي كار به اين صورت نمايش داده مي‌شود‪.‬‬

‫ترانهاده كردن ماتريس‪:‬‬


‫يكي از ساده ترين عملياتي كه روي ماتريسها انجام مي شود پيدا كردن ترانهادة آنها است همانطور كه از‬
‫رياضيات مقدماتي مي دانيم ‪ ،‬در ترانهاده ماتريس جاي سطر و ستون‌هاي ماتريس عوض مي شود يع‪VV‬ني اگر‬
‫‪ m  n‬‬
‫‪ Ajia‬يك ماتريس با ‪ m‬سطر و ‪ n‬ستون باشد آن گاه ترانهاده آن ك‪VV‬ه ب‪VV‬ا نم‪VV‬اد ‪ AT‬ي‪VV‬ا ‪ `A‬نش‪VV‬ان داده‬
‫مي شود ماتريسي ‪ m × n‬به صورت زير خواهد بود‪:‬‬
‫‪A‬‬ ‫‪T‬‬
‫‪‬‬
‫‪jia‬‬ ‫‪nm‬‬

‫براي ماتريس هاي معمولي قطعه برنامه ساده زير عمل ترانهاده را انجام مي‌دهد‪:‬‬

‫)‪For ( i =1 ; i < m ; i++‬‬


‫) ‪For ( j = 1 ; j < n ; j++‬‬
‫;]‪at [ j] [ i] = a [ i] [ j‬‬

‫زمان اجراي اين الگوريتم )‪ O(mn‬است (به تعداد‪ V‬درايه هاي ماتريس ‪) A‬‬
‫حال ببينيم براي پيدا كردن ترانهاده يك ماتريس اس‪VV‬پارس ك‪VV‬ه ب‪VV‬ه ص‪VV‬ورت فش‪VV‬رده ذخ‪VV‬يره ش‪VV‬ده اس‪VV‬ت‬ ‫‪‬‬
‫چگونه مي توان عمل كرد‪:‬‬
‫ماتريس مثال قبل را در نظرمي گيريم ‪:‬‬
‫‪0‬‬ ‫‪0 0 0 3 0 0‬‬ ‫‪6 7 8‬‬
‫‪ 2 0 0 0 0 0 0 ‬‬ ‫‪CA:‬‬ ‫‪1 5 3‬‬
‫‪‬‬ ‫‪‬‬
‫‪0‬‬ ‫‪0 0 0 0 0 0‬‬ ‫‪2 1 -‬‬
‫‪A ‬‬ ‫‪‬‬ ‫فشرده‬ ‫‪2‬‬
‫‪4‬‬ ‫‪0 0 0 1 0 0‬‬
‫‪0‬‬ ‫‪0 0 0 2 7 0‬‬ ‫‪4 1 4‬‬
‫‪‬‬ ‫‪‬‬ ‫‪4 5 -‬‬
‫‪ 0‬‬ ‫‪3 0 2 0 0 0 ‬‬
‫‪1‬‬
‫‪5 2 3‬‬
‫‪5 5 2‬‬
‫‪5 6 7‬‬
‫‪6 4 6‬‬

‫به نظر مي‌رسد براي پيدا كردن ترانهاده ‪ A‬از روي شكل فشرده آن يعني ‪ CA‬س‪VV‬اده ت‪VV‬رين راه آن اس‪VV‬ت ك‪VV‬ه‬
‫جاي ستون‌هاي اول و دوم ‪ CA‬را عوض كنيم با اين كار عمالً جاي س‪4‬طر و س‪4‬تون عناص‪4‬ر غير‌ص‪4‬فر ع‪4‬وض‬
‫مي شود و داريم‪:‬‬
‫‪6‬‬ ‫‪7‬‬ ‫‪8‬‬ ‫‪0  2 0 4 0 0 ‬‬
‫)‪(CA‬‬ ‫‪0‬‬ ‫‪3 0 ‬‬
‫‪5‬‬ ‫‪1‬‬ ‫‪3‬‬ ‫‪‬‬ ‫‪0‬‬ ‫‪0 0‬‬
‫‪T‬‬
‫‪:‬‬ ‫‪1‬‬ ‫‪2‬‬ ‫‪2-‬‬ ‫‪0‬‬ ‫‪0‬‬ ‫‪0 0‬‬ ‫‪0 0‬‬
‫‪1‬‬ ‫‪4‬‬ ‫‪4A  0 0 0 0 0 2 ‬‬
‫‪T‬‬ ‫‪‬‬
‫‪‬‬ ‫‪‬‬
‫‪5‬‬ ‫‪4‬‬ ‫‪1-‬‬ ‫‪3‬‬ ‫‪0‬‬ ‫‪0 1 2 0‬‬
‫‪2‬‬ ‫‪5‬‬ ‫‪3‬‬ ‫‪‬‬ ‫‪‬‬
‫‪0‬‬ ‫‪0‬‬ ‫‪0 0 7 0‬‬
‫‪5‬‬ ‫‪5‬‬ ‫‪2‬‬ ‫‪0‬‬
‫‪‬‬ ‫‪0‬‬ ‫‪0 0‬‬ ‫‪0 0  7 6‬‬
‫‪6‬‬ ‫‪5‬‬ ‫‪7‬‬
‫‪4‬‬ ‫‪6‬‬ ‫‪2‬‬
‫‪A‬ش‪VV‬كل فش‪VV‬رده آن را بنويس‪VV‬يم در‬ ‫‪T‬‬
‫اما اگر ابتدا ماتريس ‪ A‬را ترانهاده كنيم‪ ،‬سپس از روي م‪VV‬اتريس ترانه‪VV‬اده يع‪VV‬ني‬
‫نهايت ‪ CA‬به صورت زير بدست مي آيد‪:‬‬‫‪T‬‬

‫‪10‬‬
‫‪6 7 8‬‬
‫‪CAT:‬‬ ‫‪1 2 2-‬‬
‫‪1 4 4‬‬
‫‪2 5 3‬‬
‫‪4 6 2‬‬
‫‪5 1 3‬‬
‫‪5 4 1-‬‬
‫‪5 5 2‬‬
‫همانطور كه مشاهده مي شود شكل هاي (‪ T)CA‬و ‪ CAT‬باهم يكي نيس‪VV‬تند‪ ، V‬در ش‪VV‬كل فش‪VV‬رده م‪VV‬اتريس اس‪VV‬پارس عناص‪VV‬ر‬
‫غير صفر به ترتيب شماره سطر مرتب شده اند ‪ ،‬ضمنا ً در آن هايي كه شماره سطر يكسان دارند براساس شماره ستون‬
‫مرتب شده اند‪ ،‬مي بي‪V‬نيم (‪ T)CA‬چ‪VV‬نين خاص‪VV‬يتي ن‪VV‬دارد ‪ ،‬اولين اي‪V‬ده اي ك‪V‬ه ب‪V‬ه ذهن مي رس‪VV‬د آن اس‪V‬ت ك‪V‬ه در ‪( A ) t‬‬
‫‪C‬‬
‫عناصر را مرتب كنيم ‪ ،‬اگر ماتريس ‪ A‬و ‪ t‬عنصر غير صفر داشته باشد ‪ ،‬زمان مورد نياز ب‪VV‬راي تع‪VV‬ويض س‪VV‬تون اول‬
‫‪O ( t‬خواهد بود سپس براي مرتب كردن اگر از يك روش مرتب سازي معم‪VV‬ولي مانن‪VV‬د‬ ‫و دوم ماتريس فشردة ‪) C A‬‬
‫‪2‬‬
‫مرتب سازي حبابي استفاده كنيم زمان مورد نياز براي آن نيز ) ‪O ( t‬خواهد بود و در نهايت زمان اين روش ‪:‬‬
‫‪‬‬ ‫‪‬‬
‫) ‪O t t 2  O ( t 2‬‬
‫‪‬‬
‫‪O t t 2‬‬ ‫‪‬‬
‫‪ : t‬براي جابجايي ستون هاي اول و دوم ‪CA‬‬
‫‪ : t2‬براي مرتب كردن‬

‫اگر ماتريس ‪ A‬يك ماتريس ‪ m×n‬باشد در بدترين‪ V‬حالت ‪ mn = t‬عنصر غير صفر دارد و در اينجا زمان مورد نياز‬
‫‪O m‬خواهد بود كه بسيار بدتر از الگوريتم ترانهاده معمولي است كه زمان آن ‪ ‬‬
‫‪Onm‬بود‪.‬‬ ‫الگوريتم ) ‪( 2n 2‬‬

‫روش بهتر براي ترانهاده كردن‬ ‫‪‬‬

‫الگوريتم ترانهاده ‪Transpose‬‬


‫در روش قبل ديديم زمان اجرا بسيار زياد است ‪ ،‬در اين قسمت الگوريتم ترانه‪VV‬اده معم‪VV‬ولي را مع‪VV‬رفي مي ك‪VV‬نيم در اين‬
‫الگوريتم به ستون دوم ماتريس ‪ CA‬توجه مي‌كنيم ‪ ،‬در واق‪V‬ع در س‪VV‬تون دوم ‪ CA‬ش‪VV‬مارة س‪VV‬تون عناص‪VV‬ر غ‪V‬ير ص‪V‬فر ‪A‬‬
‫قرار دارد ك‪VV‬ه ق‪VV‬رار اس‪VV‬ت در ترانه‪VV‬اده ب‪VV‬ه ش‪VV‬ماره س‪VV‬طر تب‪VV‬ديل ش‪VV‬ود ‪ ،‬در س‪VV‬تون دوم م‪VV‬اتريس ‪ CA‬و ‪ t‬عنص‪VV‬ر داريم‬
‫( يادآوري مي شود كه ‪ t‬تعداد عناصر غير صفر است) بار اول كليه عناصر شماره يك را ب‪VV‬ه م‪VV‬اتريس جدي‪VV‬د ك‪VV‬ه ق‪VV‬رار‬
‫است ترانهاده ‪ A‬باشد منتقل مي كنيم‪ ،‬ب‪VV‬اردوم عناص‪VV‬ري ك‪VV‬ه ش‪VV‬ماره ‪ 1‬دارن‪VV‬د منتق‪VV‬ل مي ك‪VV‬نيم ‪ ،‬و همين ط‪VV‬ور ب‪VV‬ار ‪ n‬ام‬
‫عناصري كه شماره ‪ n-1‬دارند منتقل مي كنيم ( ‪ n‬تعداد‪ V‬ستون هاي ماتريس ‪ A‬است)‬
‫ترانهاده يک ماتريس اسپارس‬
‫) ] [ ‪void transpose ( term a[ ] , term b‬‬
‫‪/* b is set to the transpose of a */‬‬
‫{‬
‫; ‪int n , i , j , cuurentb‬‬
‫‪n = a [0] .value ; /* total number of elements */‬‬
‫‪b [0] . row = a [0] . col ; /* rows in b = columns in a */‬‬
‫; ‪b [0] .col = a [0] . row‬‬ ‫‪/* columns in b = rows in a */‬‬
‫; ‪b [0] . value = n‬‬
‫‪if ( n > 0 ) { /* non zero matrix */‬‬
‫; ‪currentb = 1‬‬
‫) ‪for ( i = 0 ; i < a [0] .col ; i++‬‬
‫‪/* transpose by columns in a */‬‬
‫) ‪for ( j = 1 ; j <= n ; j++‬‬
‫‪/* find elements from the current column */‬‬
‫{ ) ‪if ( a [ j] .col = = i‬‬
‫‪/* element is in current column , add it to b */‬‬

‫‪11‬‬
‫; ‪b [currentb] . row = a[ j] .col‬‬
‫; ‪b [cuurentb] .col = a [ j] . row‬‬
‫; ‪b [currentb] . value = a[ j] .value‬‬
‫;‪cuurentb++‬‬
‫}‬
‫}‬
‫}‬
‫‪ b )2‬برابر با ترانهاده ‪ a‬قرار داده مي شود ‪.‬‬
‫‪ terms )3‬هم‪VV‬ان تع‪VV‬داد عناص‪VV‬ر غ‪VV‬ير ص‪VV‬فر ‪ C ،‬تع‪VV‬داد س‪VV‬تون ه‪VV‬اي م‪VV‬اتريس ‪ A ، i‬ي‪VV‬ك متغ‪VV‬ير و ش‪VV‬مارنده ‪،‬‬
‫روي خانه‌هاي ‪ B‬حركت كند ‪.‬‬ ‫‪BtnerruC‬جاري ‪ ،‬در جريان ‪‬‬ ‫‪B‬‬
‫‪ 5‬تا ‪ )8‬مقدار دهي آغازين ‪Initial‬‬
‫‪terms= b[0] . value)6‬‬
‫‪ )9‬شرط‪ :‬اگر ماتريس ‪ ،‬ماتريس صفر باشد‪ terms = 0 :‬برنامه كارش تمام شده است‬

‫‪( 13‬‬ ‫‪0‬‬ ‫ترانهاده‬ ‫‪8 13 0‬‬ ‫(ماتريس‪:8 × 13‬‬

‫اگر غير صفر باشد مراحل زير انجام مي شود‪:‬‬


‫‪ )12‬دفعه اول ‪C =1‬‬
‫‪ i )13‬از ‪ 1‬تا ‪ 8‬تغيير مي كند‪.‬‬
‫‪ )14‬عناصر در ستون ‪ c‬را مي يابد‪V.‬‬
‫‪ )15‬داخل اين شرط زماني مي آييم ‪ a[ i ] = C‬يا ‪ col‬برابر ‪ 1‬است ‪.‬‬

‫زمان اجراي الگوريتم ترانهاده معمولي برابر )‪ O(nt‬است كه در آن ‪ n‬تعداد ستون هاي ماتريسي ‪ A‬است و ‪t‬‬
‫تعداد عناصر غير صفر ‪ A‬مي باشد‪.‬‬
‫‪( ‬‬
‫‪O nt‬‬ ‫)‬ ‫‪Onm‬بدترين حالت‬ ‫‪ 2‬‬
‫‪7‬‬ ‫‪6 8‬‬
‫‪1‬‬ ‫‪2 -2‬‬
‫‪1‬‬ ‫‪4 4‬‬
‫‪2‬‬ ‫‪5 3‬‬
‫‪4‬‬ ‫‪6 2‬‬
‫‪5‬‬ ‫‪1 3‬‬
‫‪5‬‬ ‫‪4 -1‬‬
‫‪5‬‬ ‫‪5 2‬‬
‫‪6‬‬ ‫‪5 7‬‬

‫ترانهاده سريع (تند) ‪Fast Transpose‬‬


‫در روش ترانهاده معمولي زمان اجرا )‪ O(nt‬شد و در حالتي كه ‪ mn = t‬باشد (بدترين‪ V‬حالت) زمان‬
‫مناسبي نيست در اين قسمت با روشي سريعتر آشنا مي‌شويم ‪ ،‬در اين روش از ‪ 2‬آراي‪V‬ه كمكي‪ Row size‬و‬
‫‪ Row start‬كمك مي گيريم كه طول هر دوي آن ها ‪ n‬است (ب‪VV‬ه تع‪VV‬داد‪ V‬س‪VV‬تون ه‪VV‬اي م‪VV‬اتريس ‪ ) A‬در واق‪VV‬ع‬
‫) ‪ Row size ( i‬تع‪VV‬داد عناص‪VV‬ر در س‪VV‬تون ‪ i‬ام ‪( A‬ي‪VV‬ا تع‪VV‬داد‪ V‬عناص‪VV‬ر در س‪VV‬طر‪ i‬ام ‪ ) B‬مي‌باش‪VV‬د و‬
‫) ‪ Row start ( i‬را كه در واقع مكان شروع سطر ‪ i‬ام در ماتريس ترانهاده ‪ B‬مي باشد به صورت زير‬
‫محاسبه مي كنيم ‪:‬‬
‫;‪Row start (0) = 1‬‬
‫;]‪Row start ( i ) = Row start [i – 1] + Row siza [ i – 1‬‬

‫‪12‬‬
‫نقش كليدي را در الگوريتم ترانهاده سريع آرايه ‪ Row start‬برعهده دارد زيرا در واقع مكان شروع را در‬
‫ماتريس ترانهاده مشخص مي كند ‪ ،‬ب‪VV‬ا اس‪VV‬تفاده از اين آراي‪VV‬ه مي ت‪VV‬وانيم تم‪VV‬ام عناص‪VV‬ر غ‪VV‬ير ص‪V‬فر ‪ A‬را ب‪VV‬ه ‪B‬‬
‫منتقل كنيم ‪.‬‬
‫ترانهاده سريع يک ماتريس اسپارس‬
‫) ] [ ‪Void fast_transpose (term a [ ] , term b‬‬
‫{‬
‫‪/* the transpose of a is placed in b */‬‬
‫; ]‪int row_terms [MAX_COL] , starting_pos [MAX_COL‬‬
‫; ‪int i , j , num_cols = a[0] . col , num_terms = a [0] . value‬‬
‫; ‪b [0] . row = num_cols ; b[0] . col = a[0] . row‬‬
‫; ‪b [0] .value = num_terms‬‬
‫‪if (num_terms > 0 ) { /* nonzero matrix */‬‬
‫)‪for (i = 0 ; i < num_cols ; i++‬‬
‫; ‪row_terms [i] = 0‬‬
‫)‪for ( i = 1 ; i <= num_terms ; i++‬‬
‫; ‪row_terms [a [i] .col ] ++‬‬
‫; ‪starting_pos [0] = 1‬‬
‫)‪for (i = 1 ; i< num_cols ; i++‬‬
‫; ]‪starting_pos [i] = starting_pos [ i-1] + row_terms [ i-1‬‬
‫)‪for (i = 1 ; i <= num_terms ; i++‬‬
‫{‬
‫; ‪j = starting_pos [ a [i] .col ] ++‬‬
‫; ‪b [ j] . row = a [i] .col ; b[ j] . col = a [i] .row‬‬
‫; ‪b [ j] .value = a[i] . value‬‬
‫}‬
‫}‬
‫}‬
‫‪ )1‬يك متغير ‪ a‬از جنس اسپارس و ‪ b‬هم همين طور‪.‬‬
‫‪ )2‬ترانهاده ‪ a‬در ‪ b‬قرار داده مي شود ضمنا ً زمان اجرا( ‪ (Ot n‬است كه ‪ t‬تعداد عناصر غير صفر‬
‫و ‪ n‬تعداد‪ V‬ستون ها مي باشد‪.‬‬
‫‪ )3‬تعريف دو آرايه‬
‫‪6‬و‪ )7‬مقداردهي آغازين‬
‫‪ terms )8‬كار تمام‬
‫‪ )10‬مقدار ) ‪ Rowsiza ( i‬را كه برابر تعداد عناصر در سطر ‪ i‬ام ‪ b‬مي باشد محاسبه مي كند ‪.‬‬
‫‪ )11‬همه را صفر قرار مي دهد و مقدار دهي آغازين‬
‫‪ )12‬محاسبات انجام مي دهد‪V.‬‬
‫) ‪Row size (a [ i] . Col‬‬
‫عدد ‪ 2‬‬
‫خانه‪2‬‬
‫‪ )13‬توضيح) ‪ Row start ( i‬را كه مكان شروع سطر ‪ i‬ام در ماتريس ترانهاده مي باشد مشخص‬
‫مي كند (خط ‪14‬و ‪)15‬‬
‫‪ 16‬تا ‪ )23‬انتقال از ماتريس اصلي ‪ a‬به ماتريس ترانهاده ‪b‬‬
‫‪ )22‬حتما ً يكي افزايش پيدا مي كند چون اعداد بعدي را روي اين ننويسد‪V.‬‬
‫زمان اجرا ) ‪O (n +t )  O ( n + t + n + t‬‬
‫زمان الزم براي اجراي الگوريتم ترانهاده سريع برابر )‪ O (n + t‬مي باشد زيرا ‪:‬‬
‫‪O n‬‬‫براي انتقال از ‪ a‬به ‪  t n  t  b‬‬

‫براي مقدار دهي آغازين ‪Rowsize‬‬ ‫براي ‪Rowstart‬‬


‫براي تشكيل ‪RowSize‬‬

‫‪0 1‬‬ ‫‪2‬‬ ‫‪3‬‬ ‫‪4‬‬ ‫‪5 6‬‬

‫‪13‬‬
‫‪CA‬‬ ‫‪6‬‬ ‫‪7‬‬ ‫‪8‬‬ ‫‪Rowsize‬‬ ‫‪0‬‬ ‫‪0‬‬ ‫‪0‬‬ ‫‪0‬‬ ‫‪0‬‬ ‫‪0‬‬ ‫‪0‬‬ ‫‪2‬‬ ‫‪1‬‬ ‫‪0‬‬ ‫‪1‬‬ ‫‪3‬‬ ‫‪1‬‬ ‫‪0‬‬
‫‪(1‬‬ ‫‪1‬‬ ‫‪5‬‬ ‫‪3‬‬ ‫‪1‬‬ ‫‪1‬‬ ‫‪1‬‬ ‫‪1‬‬ ‫‪1‬‬
‫)‬ ‫‪2‬‬ ‫‪1‬‬ ‫‪2-‬‬ ‫(‪)2‬‬ ‫‪2‬‬ ‫‪2‬‬

‫‪4‬‬ ‫‪1‬‬ ‫‪4‬‬ ‫‪Rowstart‬‬ ‫‪3‬‬


‫‪4‬‬ ‫‪5‬‬ ‫‪1-‬‬
‫‪5‬‬ ‫‪2‬‬ ‫‪3‬‬ ‫‪0 1 2 3 4 5 6‬‬
‫‪5‬‬ ‫‪5‬‬ ‫‪2‬‬ ‫‪1 3 4 4 5 8 9‬‬
‫‪5‬‬ ‫‪6‬‬ ‫‪7‬‬
‫‪Rowstart‬‬
‫‪6 4‬‬ ‫‪2‬‬ ‫‪0 1 2 3 4 5 6‬‬
‫‪1 3 4 4 5 8 9‬‬
‫‪2 4‬‬ ‫‪5 6 9‬‬
‫‪3‬‬ ‫‪7‬‬
‫‪8‬‬

‫; ‪Row Start ( 0 ) = 1‬‬


‫;)‪Row Start [ i ] = Row Start ( i – 1) + Row Size(i – 1‬‬

‫(‬
‫‪)3‬‬

‫‪CAT:‬‬ ‫‪7‬‬ ‫‪6‬‬ ‫‪8‬‬


‫‪1‬‬ ‫‪1‬‬ ‫‪2‬‬ ‫‪2-  0‬‬ ‫‪0‬‬ ‫‪4‬‬ ‫‪0‬‬ ‫‪0‬‬ ‫‪0‬‬ ‫‪0‬‬ ‫‪0‬‬ ‫‪0‬‬
‫‪2‬‬ ‫‪1‬‬ ‫‪4‬‬ ‫‪4‬‬ ‫‪ 5‬‬ ‫‪0‬‬ ‫‪0‬‬ ‫‪0‬‬ ‫‪0‬‬ ‫‪4‬‬ ‫‪0‬‬ ‫‪0‬‬ ‫‪0 ‬‬
‫‪3‬‬ ‫‪‬‬
‫‪2‬‬ ‫‪5‬‬ ‫‪3‬‬ ‫‪0‬‬ ‫‪0‬‬ ‫‪0‬‬ ‫‪0‬‬ ‫‪6‬‬ ‫‪1‬‬ ‫‪0‬‬ ‫‪0‬‬ ‫‪0‬‬
‫‪4‬‬ ‫‪4‬‬ ‫‪6‬‬ ‫‪2A   0‬‬ ‫‪‬‬
‫‪‬‬ ‫‪0‬‬ ‫‪4‬‬ ‫‪0‬‬ ‫‪0‬‬ ‫‪0‬‬ ‫‪0‬‬ ‫‪0‬‬ ‫‪0‬‬
‫‪5‬‬ ‫‪5‬‬ ‫‪1‬‬ ‫‪3‬‬ ‫‪0‬‬ ‫‪3‬‬ ‫‪1‬‬ ‫‪0‬‬ ‫‪0‬‬ ‫‪0‬‬ ‫‪0‬‬ ‫‪2‬‬ ‫‪0‬‬
‫‪6‬‬ ‫‪5‬‬ ‫‪4‬‬ ‫‪1- ‬‬ ‫‪‬‬
‫‪7‬‬ ‫‪ 0‬‬ ‫‪0‬‬ ‫‪0‬‬ ‫‪1‬‬ ‫‪0‬‬ ‫‪0‬‬ ‫‪0‬‬ ‫‪0‬‬ ‫‪5  69‬‬
‫‪5‬‬ ‫‪5‬‬ ‫‪2‬‬
‫‪8‬‬ ‫‪6‬‬ ‫‪5‬‬ ‫‪7‬‬

‫نمايش آرايه‌ها‪:‬‬
‫همان طور كه قبالً اشاره شده كه هر آرايه به تعدادي خانه هم جنس و متوالي در حافظه است كه همگي‬
‫يك اسم داشته باشند در زبان‌هاي سطح باال نظير پاسكال ي‪VV‬ا ‪ C‬ب‪VV‬راي رس‪VV‬يدن ب‪VV‬ه ي‪VV‬ك خان‪VV‬ه ب‪VV‬ه خص‪VV‬وص در‬
‫آرايه‌ها كافي است از انديس آن خانه استفاده كنيم اما در زبان سطح پايين نظير اسمبلي از آرايه ها فقط آدرس‬
‫اولين خانه را داريم و براي آنكه به يك خانه به خصوص دسترسي پيدا كنيم بايد حتما ً در خانه هاي حافظ‪VV‬ه ب‪VV‬ا‬
‫استفاده از آدرس خانه اول پيش برويم تا به خانه مورد نظر برسيم ي‪VV‬ك آراي‪VV‬ه ‪ n‬بع‪VV‬دي در زب‪VV‬ان ‪ C‬در ح‪VV‬الت‬
‫‪n‬‬
‫‪ in‬‬
‫كلي به شكل زير مي باشد ‪ .‬تعداد عناصر چنين آرايه اي برابر است با ‪( iL  1 ) :‬‬
‫‪i1‬‬

‫] ‪a [ L1 . . . n1 , L2 . . . n2 , . . . , Ln . . . nn‬‬
‫در حالت خاص اگر محدوده پايين تمام ابعاد را(‪ ) Li‬برابر يك در نظر بگيريم‪ )‌)Li = 1‬در اين صورت‬
‫تعداد عناصر آراي‪VV‬ه حاصلض‪VV‬رب ‪n n‬ت‪VV‬ا ‪n 1‬خواه‪VV‬د ب‪VV‬ود در ادام‪VV‬ه س‪VV‬عي مي‌ك‪VV‬نيم آدرس ي‪VV‬ك خان‪VV‬ه ب‪VV‬ه‬
‫خصوص از آرايه را در مورد آرايه هاي يك بعدي و دو بعدي و سه بعدي تعيين كنيم‪.‬‬

‫الف) آرايه هاي يك بعدي‬

‫‪14‬‬
‫شكل كلي اين آرايه ها به صورت] ‪ a [ i‬مي باشد‪ ،‬اگر آدرس اولين خانه آرايه برابر ‪‬باشد ‪ ،‬براي‬
‫پيداكردن آدرس خانه ‪ i‬ام بايد(‪ )i –1‬خانه پيش برويم و اگر فرض كنيم هرخانه آرايه ب‪VV‬ه ط‪VV‬ول ‪ d‬ب‪VV‬ايت‬
‫باشد آنگاه آدرس ‪ ai‬به صورت زير به دست مي آيد ‪:‬‬
‫‪ = di‬آدرس‬
‫‪ai‬‬

‫‪a‬‬ ‫‪0‬‬ ‫‪a1‬‬ ‫‪a‬‬ ‫‪i‬‬ ‫‪a‬‬ ‫‪i1‬‬ ‫‪a‬‬ ‫‪n1‬‬

‫‪‬‬ ‫‪ di‬‬


‫براي سادگي كار فرض مي كنيم ‪ d‬نيز ‪ 1‬باشد (‪) d = 1‬‬

‫ب ) آرايه هاي دو بعدي‬


‫شكل كلي اين آرايه ها به صورت ])‪(a [n 1 ,n 2‬مي باشد ‪ ،‬براي پيدا كردن آدرس خانه سطر ‪ i‬ام‬
‫و ستون ‪ j‬ام همان( ‪ )a ji‬ابتدا بايد از عناصر ‪ i - 1‬سطر عبور كنيم از آنجا كه در هر سطر ‪n 2‬‬
‫عنصر داريم‪ ،‬آدرس ابتداي سطر ‪ i‬ام به صورت زير تعيين مي شود ‪.‬‬
‫‪ a11‬‬ ‫‪a21‬‬ ‫‪.‬‬ ‫‪.‬‬ ‫‪.‬‬ ‫‪a 1n 2 ‬‬
‫‪a‬‬ ‫‪a22‬‬ ‫‪.‬‬ ‫‪.‬‬ ‫‪.‬‬ ‫‪a 2n 2 ‬‬
‫‪ 12‬‬
‫‪ .‬‬ ‫‪‬‬
‫‪ =  i* n 2‬آدرس ابتداي سطر ‪i‬ام‬ ‫‪a ‬‬ ‫‪‬‬
‫‪ .‬‬ ‫‪‬‬
‫‪ .‬‬ ‫‪‬‬
‫‪‬‬ ‫‪‬‬
‫‪ 11 na 21‬‬
‫‪na‬‬ ‫‪.‬‬ ‫‪.‬‬ ‫‪. na 1n 2 ‬‬

‫در سطر‪ i‬ام براي رسيدن به عنصر ‪ j‬ام مشابه آرايه هاي يك بعدي بايد از ( ‪ ) j – 1‬عنصر عبور كنيم‪ ،‬پس‬
‫آدرس ‪ aji‬به صورت زير به دست مي آيد ‪:‬‬
‫‪‬‬
‫‪ = +j + 2 * i‬آدرس ‪aji‬‬ ‫‪n‬‬
‫تذكر‪:‬‬
‫عناصر آرايه دو بعدي ‪ a‬به صورت سطري در حافظه ذخيره مي شود يعني ابتدا تمام عناص‪VV‬ر س‪VV‬طر اول‬
‫ذخيره مي شود سپس عناصر سطر دوم و الي آخر يعني در حافظه ماتريس يا آرايه دو بعدي ‪ a‬به ش‪V‬كل زي‪V‬ر‬
‫ذخيره مي‌گردد ‪:‬‬

‫‪‬‬
‫‪a00‬‬ ‫‪a10‬‬ ‫‪a 1n2‬‬ ‫‪a12‬‬ ‫‪a 2 n2‬‬ ‫‪a n11 n 21‬‬

‫ج) آرايه هاي سه بعدي‬


‫شكل اين آرايه ها به صورت ] ‪a [n 1 ,n 2 ,n 3‬مي باشد مثال اگر]‪a[1. . 2,1 . . 4, 1 . . 3‬‬
‫‪k‬‬ ‫‪j‬‬
‫‪i‬‬
‫يك آرايه سه بعدي مي باشد آن را به صورت زيردر نظر مي گيريم ‪.‬‬

‫‪15‬‬
‫‪a111‬‬ ‫‪a211‬‬ ‫‪a311‬‬ ‫‪‬‬ ‫‪a112‬‬ ‫‪a212‬‬ ‫‪a312‬‬ ‫‪‬‬
‫‪a‬‬ ‫‪a221‬‬ ‫‪a321‬‬ ‫‪‬‬ ‫‪a‬‬ ‫‪a222‬‬ ‫‪a322‬‬ ‫‪‬‬
‫‪i 1 121‬‬ ‫‪‬‬ ‫‪i 2  122‬‬ ‫‪‬‬
‫‪a131‬‬ ‫‪a231‬‬ ‫‪a331‬‬ ‫‪‬‬ ‫‪a132‬‬ ‫‪a232‬‬ ‫‪a332‬‬ ‫‪‬‬
‫‪‬‬ ‫‪‬‬ ‫‪‬‬ ‫‪‬‬
‫‪a141‬‬ ‫‪a241 qa 341‬‬ ‫‪‬‬ ‫‪a142‬‬ ‫‪a242‬‬ ‫‪a342‬‬ ‫‪‬‬

‫‪a 111‬‬ ‫‪a‬‬


‫‪211‬‬ ‫‪311‬‬ ‫‪121‬‬ ‫‪a‬‬
‫‪341‬‬ ‫‪a‬‬
‫‪112‬‬ ‫‪212‬‬ ‫‪a‬‬ ‫‪a‬‬
‫‪312‬‬ ‫‪342‬‬

‫‪a‬‬ ‫‪a‬‬ ‫‪a‬‬

‫در اين گونه آرايه ها ابتدا تمامي عناصر صفحه(ماتريس اول) ذخيره مي شود س‪V‬پس عناص‪VV‬ر ص‪V‬فحه و همين‬
‫طور در نهايت عناصر صفحه‪ n1‬ام براي آنكه آدرس‪ aijk‬را به دست آوريم ابتدا بايد از عناصر‪ i -1‬صفحه‬
‫يا ماتريس عبور كنيم و چون در هر صفحه به اندازه‪ n2n3‬عنصر وجود دارد آدرس ابتداي صفحه‪ i‬ام براب‪V‬ر‬
‫است با ‪:‬‬
‫= آدرس ابتداي صفحه ‪ i‬ام‬ ‫‪‬‬ ‫‪‬‬ ‫‪ni‬‬ ‫‪n‬‬
‫‪2 3‬‬

‫از اينجا به بعد مانند‪ V‬آرايه هاي دو بعدي عمل مي كنيم در صفحه‪ i‬ام براي رسيدن به س‪VV‬طر‪ j‬ام باي‪VV‬د از ‪j-1‬‬
‫سطر عبور كنيم و هر سطر ‪ n3‬عنصر دارد ‪.‬‬
‫= آدرس ابتداي سطر ‪ j‬ام در صفحه (ماتريس )‬ ‫‪ ni 2n 3  nj 3‬‬
‫‪i‬ام‬

‫‪akji‬برابر است با ‪:‬‬ ‫و در نهايت آدرس‬


‫‪ = ni 2n 3  nj 3  k‬آدرس ‪a‬‬
‫]‪[ i,j,k‬‬

‫صف( ‪ )Queue‬و پشته( ‪)Stack‬‬

‫به طور كلي براي بازيابي داده هاي ترتيبي از دو شيوه مي توانيم استفاده كنيم ‪:‬‬

‫‪ ‬در شيوه اول‬


‫اولين داده ورودي اولين داده اي است كه بازيابي مي‌شود ((‪ FIFO = first in first out‬اين شيوه بازيابي‬
‫را ص‪VV‬ف ( ‪ ) Queue‬مي‌ن‪VV‬اميم ‪ ،‬درك‪VV‬امپيوتر ن‪VV‬يز از اين س‪VV‬اختار ب‪VV‬ه وف‪VV‬ور اس‪VV‬تفاده مي ش‪VV‬ود ‪ .‬مثالً هنگ‪VV‬ام‬
‫ترجمه يك برنام‪VV‬ه توس‪VV‬ط م‪VV‬ترجم ابت‪VV‬دا خ‪VV‬ط اول ترجم‪VV‬ه مي ش‪V‬ود س‪VV‬پس خ‪VV‬ط دوم الي آخ‪VV‬ر ي‪VV‬ا در حافظه‌ه‪V‬اي‬
‫ميانگير( ‪ ) Buffer‬نيز از سيستم صف استفاده مي شود‪ .‬در شيوه دوم بازي‪VV‬ابي اطالع‪VV‬ات ترتي‪VV‬بي اس‪VV‬تفاده از‬
‫(‪LIFO =last‬‬ ‫پشته (‪) Stack‬مي‌باشد در پشته آخرين داده ورودي اولين داده خ‪VV‬روجي مي باش‪VV‬د‬
‫‪ . )in first of‬اين ساختار نيز كاربردهاي ف‪VV‬راواني در ك‪V‬امپيوتر دارد مثالً در م‪V‬ورد پرانتزه‪V‬اي ت‪V‬و در ت‪VV‬و‬
‫اولين پرانتزي كه بسته مي شود مربوط به آخ‪V‬رين پران‪V‬تزي اس‪V‬ت ك‪V‬ه ب‪V‬از نش‪V‬ده اس‪V‬ت ي‪V‬ا حلق‪V‬ه اي ت‪V‬و در ت‪V‬و‬
‫آخرين حلقه اي كه باز مي شود يا شروع مي شود اولين حلقه اي است كه به اتمام مي رسد ‪.‬‬
‫نوع داده مجرد پشته‬
‫‪Structure stack is‬‬
‫‪Objects : a finite ordered list with zero or more elements .‬‬
‫‪Functions :‬‬
‫‪For all stack  stack , item  elements , max_stack_size  positive‬‬
‫‪integer‬‬
‫= ‪Stack creates (max_stack_size) ::‬‬

‫‪16‬‬
Create an empty stack whose maximum size is
max_stack_size
Boolean isfull (stack , max_stack_size) :: =
If (number of elements in stack = = max_stack_size)
Return true
Else return false
Stack add (stack ,item) :: =
If (isfull(stack)) stack_full
Else insert item into top of stack and return
Boolean isempty (stack) :: =
If (stack = = creates (max_stack_size))
Return true
Else return false
Element delete (stack) :: =
If (isempty(stack)) return
Else remove and return item on the top of the stack
‫نوع داده مجرد صف‬
Structure queue is
Objects : a finite ordered list with zero or more elements .
Functions :
For all queue  Queue , item  elements , max_ queue _size 
positive integer
queue creates (max_ queue _size) :: =
Create an empty queue whose maximum size is max_ queue
_size
Boolean isfullq (queue , max_ queue _size) :: =
If (number of elements in queue = = max_ queue _size)
Return true
Else return false
queue addq (queue ,item) :: =
If (isfull(queue)) queue _full
Else insert item at rear of queue and return queue
Boolean isemptyq (queue) :: =
If (queue = = createq (max_ queue _size))
Return true
Else return false
Element deleteq (queue) :: =
If (isemptyq(queue)) return
Else remove and return item on at front of queue
‫ تعدادي متناهي ليست مرتب با صفر عنصر يا بيشتر‬:‫ عناصر‬Object

Function‫توابع‬

Integer Positive ‫اعداد صحيح مثبت‬


‫ ايجاد مي كند كه حداكثر اندازه آن‬queue ‫ يك صف خالي به نام‬، ) ‫ (نام صف و اندازه صف‬Creat‫تابع‬
‫ افراد و عناصر در صف مساوي‬V‫ اگر تعداد‬،‫ است‬False‫ و‬True ‫ خروجي‬is full ‫ سايز است تابع‬max
. ‫ در غير اين صورت غلط است‬، ‫ ساز شده درست‬max

Add ‫تابع‬
.‫ درج مي كند و صف جديد در اختيار قرار مي‌دهد‬queue ‫ را در انتهاي صف‬item ‫ عنصر‬else

17
‫قانون‪ :‬هر صف بايد انتهاي آن مشخص باشد و انتها يك متغير براي ‪rear‬‬
‫هر موقع نفر خواست اضافه مي شود به ته صف اضافه مي شود‪.‬‬ ‫‪‬‬
‫تابع ‪ Is Empty‬صفي خالي مي باشد كه تعداد عناصرش صفر باشد و در غير اين صورت پر است و (‬
‫‪ )Maxsize = 0‬است‪.‬‬
‫تابع ‪ Delete‬اسم صف مي خواهد و خروجي از جنس ‪ Item‬و چك شود كه صف خالي نباشد‪.‬‬
‫قانون عنصر ابتداي صف را از صف خارج مي كند و آن را ارجاع مي دهد ‪ return =( .‬ارجاع )‬
‫‪ Front‬جلو‬
‫هيچ وقت از نفر سوم صف كسي خارج نمي شود‪.‬‬

‫=‪Queue CreateQ (max_queue_size) ::‬‬


‫‪#define MAX_QUEUE_SIZE 100 /* Maximum queue size */‬‬
‫{ ‪typedef struct‬‬
‫; ‪int key‬‬
‫‪/* other fields */‬‬
‫; ‪} elemnt‬‬
‫; ]‪element queue [MAX_QUEUE_SIZE‬‬
‫; ‪int rear = -1‬‬
‫; ‪int front = -1‬‬
‫‪Boolean IsEmptyQ(queue) ::= front = = rear‬‬
‫‪Boolean IsFullQ(queue) ::= rear = = MAX_QUEUE_SIZE -1‬‬
‫تابع ‪ Create‬در قسمت ‪Var‬يك آرايه است و‪ Front‬و‪ rear‬صفر مي شوند‪V.‬‬
‫‪ Rear‬هميشه به آخرين نفر اشاره مي كند ‪،‬‬
‫‪F‬‬ ‫‪r‬‬ ‫‪f‬‬ ‫‪r‬‬
‫‪A‬‬ ‫‪B‬‬ ‫‪C‬‬ ‫‪ Front‬به يكي قبل از اولين نفر‬
‫دراين صف يك نفر آنهم ‪C‬‬
‫تذكرات مربوط به ساختمان داده صف‬
‫‪ .1‬هر صف نياز به دو متغ‪VV‬ير (پ‪VV‬ارامتر) دارد‪ .‬يكي ‪ front‬ب‪VV‬راي تع‪VV‬يين‪ V‬مك‪VV‬ان ش‪VV‬روع ص‪VV‬ف (ابت‪VV‬داي‬
‫صف) و ديگر‪ rear‬كه انتهاي صف را مشخص مي‌كند ‪.‬‬
‫‪ .2‬همواره ‪ rear‬ب‪VV‬ه آخ‪VV‬رين نف‪VV‬ر ص‪VV‬ف اش‪VV‬اره مي كن‪VV‬د ام‪VV‬ا ‪ front‬يكي قب‪VV‬ل از اولين نف‪VV‬ر ص‪VV‬ف را‬
‫مشخص مي‌كند‬
‫‪ .3‬هنگامي صف خالي است كه ‪ rear‬مساوي ‪ front‬باشد‪.‬‬
‫‪ .4‬هنگامي صف پر است كه ‪ rear‬مساوي ‪ n‬يا ‪ Maxsize‬باشد‪.‬‬

‫ساختار پشته‬
‫نكات مربوط به ساختمان داده پشته‬
‫‪1‬ـ اولين نكته ‪ :‬در ساختار پشته فقط يك پ‪VV‬ارامتر داريم و آن ‪ Top‬اس‪V‬ت ك‪V‬ه هم‪V‬واره ب‪V‬ه عنص‪V‬ر ب‪V‬االي پش‪VV‬ته‬
‫اشاره مي كند‪.‬‬
‫‪2‬ـ هنگامي پشته خالي است كه ‪ Top‬مساوي ( ‪) -1‬باشد ( ‪) Top = 1-‬‬
‫‪3‬ـ هنگامي پشته پر است كه ‪ Top‬مساوي ‪ Maxsize -1‬باشد‪)Top = maxsize - 1 ( .‬‬

‫‪top‬‬

‫‪C‬‬

‫‪18‬‬
‫‪B‬‬
‫‪A‬‬

‫تفاوت عمده ساختار صف يا پشته ‪:‬‬


‫{‪Top‬‬
‫‪ADD:‬‬
‫;‪Top = top+1‬‬
‫‪A‬‬ ‫;‪Stack[top] =item‬‬

‫{‪Top‬‬ ‫‪Delete:‬‬
‫‪B‬‬ ‫;]‪Item=stack[top‬‬
‫‪A‬‬ ‫;‪Top=top-1‬‬

‫جايگذاري در صف‬
‫)‪Void addq (int *rear , element item‬‬
‫{‬
‫‪/* add an item to the queue */‬‬
‫{ )‪if (*rear = = max_queue_size -1‬‬
‫; ) ( ‪queue_full‬‬
‫; ‪return‬‬
‫}‬
‫; ‪queue [++*rear] = item‬‬
‫}‬
‫حذف عنصري از يک صف‬
‫)‪Element deleteq (int *front , int rear‬‬
‫{‬
‫‪/* remove element at the front of the queue */‬‬
‫)‪if (*front = = rear‬‬
‫‪return queue_empty ( ) ; /* return an error key */‬‬
‫; ]‪return queue [++*front‬‬
‫}‬
‫عمل اضافه كردن عنصر به پشته ‪ Push‬و كم كردن عنصر ‪ Pop‬است ‪.‬‬
‫ارزشيابي عبارات‬

‫عباراتي نظير‪ 7*6+5‬از نظر محاسباتي عب‪VV‬ارات مبهم هس‪VV‬تند‪ ، V‬زي‪VV‬را اگ‪VV‬ر ابت‪VV‬دا ‪ 5‬و‪ 6‬را جم‪VV‬ع ك‪VV‬رده س‪VV‬پس‬
‫حاصل را در‪ 7‬ضرب كنيم نتيجه ‪ 77‬خواهد بود ‪ ،‬اما اگر ابتدا عمل ضرب را انجام دهيم س‪VV‬پس عم‪VV‬ل جم‪VV‬ع‬
‫حاصل ‪ 47‬مي شود ‪.‬‬
‫يك راه س‪pp‬اده براي رف‪VV‬ع ابه‪VV‬ام اين گون‪VV‬ه عب‪VV‬ارات پران‪VV‬تز گ‪VV‬ذاري اس‪VV‬ت ‪ ،‬در پرانتزگ‪VV‬ذاري مي ت‪VV‬وان اول‪VV‬ويت‬
‫عملگرها را تعيين كرد اما اين كار در رياضيات موسوم نيست در رياضيات عمل ضرب نسبت به جمع مق‪VV‬دم‬
‫است بنابراين عبارت ‪ a+bc‬هيچ گونه ابهامي ندارد ‪ ،‬در ك‪VV‬امپيوتر ي‪VV‬ا ماش‪VV‬ين حس‪VV‬اب ن‪VV‬يز مي ت‪VV‬وانيم ب‪VV‬راي‬
‫عملگرهاي مختلف اولويت تعيين‪ V‬كنيم مثالً آنجا نيز بگوييم ضرب نسبت به جمع مقدم است ‪.‬‬
‫اما كامپيوتر يا ماشين حساب چگونه مي تواند اولويت عملگرها را اعمال كند؟‬
‫براي جواب دادن به اين سئوال باي‪V‬د ب‪V‬ا س‪V‬اختار عب‪V‬ارات بيش‪V‬تر آش‪V‬نا ش‪V‬ويم ‪ ،‬اعم‪V‬ال رياض‪V‬ي معم‪V‬والً اعم‪V‬ال‬
‫دوتايي هستند يعني هر عملگري روي دو عملوند ( ‪ ) Operand‬اثر ميكند مثالً ب‪VV‬راي جم‪VV‬ع دو مق‪VV‬دار ‪ A‬و‬
‫(‬ ‫‪ B‬مي نويسيم ‪ A+B‬در اين شكل نوشتاري كه عملگر درمي‪VV‬ان دو عملون‪VV‬د آم‪VV‬ده اس‪VV‬ت ش‪VV‬كل ميانون‪VV‬دي‬
‫‪ ) Infix‬داريم‪ ،‬اگر عملگر را پيش از دو عملون‪V‬د بنويس‪V‬يم يع‪V‬ني ‪ AB+‬ش‪V‬كل پيش‪V‬وندي ( ‪ ) Prefix‬خ‪V‬واهيم‬
‫داشت‪ ،‬و اگر عملگر را پس از دو عملوند بنويسيم شكل پسوندي ( ‪ ) Postfix‬داريم در اين حالت مي‌نويس‪VV‬يم‬

‫‪19‬‬
‫‪ ،+AB‬در عمل براي رفع ابهام عبارات رياضي در كامپيوتر يا ماشين حساب آن ها را به ص‪VV‬ورت پس‪VV‬وندي‬
‫تبديل مي كنيم سپس حاصل عبارت را با استفاده از يك پشته محاسبه مي كنيم ‪.‬‬
‫براي آنكه يك عبارت را از حالت ميانوندي به حالت پسوندي تبديل كنيم دو راه وجود دارد‪:‬‬
‫يكي به صورت مستقيم وديگري با استفاده ا زپشته‬
‫در روش مستقيم با توجه به ج‪V‬دول اول‪V‬ويت عملگره‪V‬ا ك‪V‬ه در پ‪V‬ايين آم‪V‬ده اس‪V‬ت ابت‪V‬دا ت‪V‬رتيب انج‪V‬ام اعم‪V‬ال را‬
‫مشخص ميكنيم سپس هر عمل را به صورت ‪ Postfix‬تب‪VV‬ديل‪ V‬مي ك‪VV‬نيم و در نه‪VV‬ايت ب‪VV‬ا كن‪VV‬ار هم ق‪VV‬رار دادن‬
‫تمام عباراتي كه به پسوندي تبديل‪ V‬شده اند شكل پسوندي كل عبارت را تعيين‪ V‬مي كنيم ‪.‬‬

‫در جدول اولويت عملگرها‬

‫‪ = unarx‬تفريق يكتايي (منفي ) ‪U‬‬ ‫‪or‬‬ ‫‪0‬‬ ‫‪1‬‬ ‫*دربيسيك توان هم رده ‪ not‬است‬
‫‪5-3‬‬ ‫‪U 7‬‬ ‫‪0‬‬ ‫‪0‬‬ ‫‪1‬‬
‫دوتايي‬ ‫‪1‬‬ ‫‪1‬‬ ‫‪1‬‬

‫ياي مانع جمع‬


‫‪0‬‬ ‫‪1‬‬ ‫براي برعكس ك‪V‬ردن بيته‪VV‬اي ‪ 0‬و‪ 1‬از ‪ Xor‬اس‪V‬تفاده مي ك‪V‬نيم‪.‬‬
‫‪Xor‬‬
‫‪1‬‬ ‫‪11010001‬‬
‫‪0‬‬ ‫‪0‬‬
‫‪0‬‬ ‫‪11111111‬‬
‫‪1‬‬ ‫‪1‬‬
‫‪00101110‬‬ ‫مكمل‬

‫نكته ‪:‬‬
‫در بين عملگرهاي هم اولويت آن عملگري كه سمت چپ باشد مقدم است‪.‬‬
‫عملگر‬
‫اولويت‬
‫‪1‬‬ ‫(‬ ‫پرانتز )‬
‫تفريق يكتايي (منفي)‬ ‫‪U‬‬
‫‪2‬‬
‫‪3‬‬ ‫‪not‬‬
‫‪4‬‬ ‫‪* , / , % , and‬‬
‫‪5‬‬ ‫‪+ , - , or , xor‬‬
‫‪6‬‬ ‫>‪<,<=,=,<>,>=,‬‬

‫اولويت عملگرها در ‪C‬‬

‫مثال ‪ :‬عبارت زير را به صورت پسوندي بنويسيد‪.‬‬


‫‪A+B*(C+D/E)/F‬‬

‫روش قبل بسيار ساده است اما دو ايراد اصلي دارد‪:‬‬

‫‪20‬‬
‫يكي آنكه عبارت بايد دو بار پيمايش شود بار اول عملگرهاي موجود در آن تع‪V‬يين‪ V‬مي ش‪V‬وند و اول‪V‬ويت آنه‪VV‬ا‬
‫مشخص مي شود باردوم عبارت تبديل به پسوندي مي شود اين عمليات ضمن آنكه زم‪V‬ان گ‪VV‬ير مي‌باش‪V‬د گ‪V‬اهي‬
‫اوقات حتي انجام پذير نيست ‪ .‬مثالً در ماشين حساب كل عبارت در دست نيس‪VV‬ت ت‪V‬ا تم‪V‬ام عملگره‪V‬اي موج‪VV‬ود‬
‫در آن اولويت بندي شوند‪.‬‬
‫براي رفع اين مشكل‬
‫ً‬
‫از روشي استفاده مي كنيم كه عمال در ماشين حساب و ك‪V‬امپيوتر انج‪V‬ام مي ش‪V‬ود دراين روش از ي‪VV‬ك پش‪VV‬ته(‬
‫‪ ) Stack‬براي تبديل عبارات ميانوندي به پسوندي استفاده مي كنيم به دو نكته اساسي توجه داريم‪:‬‬
‫اول اينكه در عبارت پسوندي هيچ پرانتزي نداريم‪.‬‬
‫دوم آنكه عملوندها از شكل ميانوندي به پسوندي تغيير نمي كند يعني تنها جاي عملگرها عوض مي‌شود‬
‫قوانين زير را رعايت مي كنيم‬
‫قانون ‪ : 1‬تنها عملگر ها داخل پشته قرار مي گيرند و هيچ عملوندي را در پش‪VV‬ته نمي نويس‪VV‬يم ب‪VV‬ه محض‬
‫رسيدن به يك عملوند آن را مستقيما ً در خروجي مي نويسيم ‪.‬‬
‫قانون ‪ p: 2‬تنها عملگري مي تواند در پشته باالي عملگر ديگر قرار بگيرد كه اولويتي بيش از آن داشته‬
‫باشد اگر عملگر جديد اولويتي كمتر يا مساوي عملگر باالي پشته داشته باشد ابت‪V‬دا آن عملگ‪V‬ر از پش‪V‬ته خ‪V‬ارج‬
‫مي شود سپس عملگر جديد در پشته قرار مي گيرد ‪.‬‬
‫قانون ‪ : 3‬عملگر ) باالترين اولويت را داراست اين عملگر مي تواند در پشته باالي ه‪V‬ر عملگ‪VV‬ر ديگ‪V‬ري‬
‫حتي باالي يك) ديگر قرار بگيرد ‪.‬‬
‫تذكر ‪ :‬عملگر ) دو نوع اولويت دارد ‪.‬‬
‫يكي اولويت جاري ( ‪ ) ICP‬و ديگري اولويت در پشته اولويت در پشته (‪) ‌ISP‬‬
‫اولويت جاري عملگر ) از همه باالتر است اما ب‪VV‬ه محض اينك‪VV‬ه در پش‪VV‬ته قرارگ‪VV‬رفت پ‪VV‬ايين ت‪VV‬رين اول‪VV‬ويت را‬
‫خواهد داشت يعني اگر عملگر ) داخل پشته بود هر عملگر ديگري مي تواند باالي آن قرار بگيرد ‪.‬‬
‫قانون ‪ p: 4‬به محض رسيدن به عملگر (كليه عملگرهاي موجود در پشته را از پشته خارج مي كنيم تا به‬
‫اولين عملگر پرانتز باز برسيم آن عملگر ها را در خروجي مي نويسيم عملگ‪VV‬ر ) را ن‪VV‬يز ازپش‪VV‬ته خ‪VV‬ارج مي‬
‫كنيم ولي در خروجي نمي نويسيم ‪.‬‬
‫قانون ‪ : 5‬هنگام رسيدن به انتهاي عبارت كه با نماد ‪ ) number sign( #‬نشان داده مي شود پشته را‬
‫خالي مي‌كنيم يعني تمام عملگرها موجود را در آن را خارج مي سازيم و در خروجي مي نويسيم ‪.‬‬
‫مثال‪ :‬عبارت قبل را با استفاده از پشته به ‪ postfix‬تبديل كنيد ‪.‬‬

‫‪post1‬‬ ‫‪ Tokenize‬جزبندي‬
‫‪A‬‬ ‫‪+‬‬ ‫‪B‬‬ ‫*‬ ‫(‬ ‫‪C‬‬ ‫‪+‬‬ ‫‪D‬‬ ‫‪/‬‬ ‫‪E‬‬ ‫)‬ ‫‪/‬‬ ‫‪F‬‬ ‫‪#‬‬

‫عبارت بعدي ‪next token‬‬ ‫پشته ‪stack‬‬ ‫خروجي ‪out put‬‬


‫هيچي‬ ‫‪#‬‬ ‫هيچي‬
‫‪A‬‬ ‫‪#‬‬ ‫‪A‬‬
‫‪+‬‬ ‫‪+#‬‬ ‫‪A‬‬
‫‪B‬‬ ‫‪+#‬‬ ‫‪AB‬‬
‫*‬ ‫‪*+#‬‬ ‫‪AB‬‬
‫(‬ ‫‪(*+#‬‬ ‫‪AB‬‬
‫‪C‬‬ ‫‪(*+#‬‬ ‫‪ABC‬‬
‫‪+‬‬ ‫‪+(*+#‬‬ ‫‪ABC‬‬
‫‪D‬‬ ‫‪+(*+#‬‬ ‫‪ABCD‬‬
‫‪/‬‬ ‫‪/+(*+#‬‬ ‫‪ABCD‬‬
‫‪E‬‬ ‫‪/+(*+#‬‬ ‫‪ABCDE‬‬

‫‪21‬‬
) *+# +/ABCDE
/ /+# *+/ABCDE
F /+# ABCDE/+*F
# ‫خالي‬ +/ABCDE/+*F

postfix ‫ به‬infix ‫تابع براي تبديل از‬


void postfix (void)
{
/* output the postfix of the expression . the expression string , the stack , and
top are global */
char symbol ;
precedence token ;
int n = 0 ;
int top = 0 ; /* place eos on stack */
stack [0] = eos ;
for (token = get_token (&symbol,&n) ; token != eos ; token = get_token
(&symbol,&n))
{
if (token = = operand)
printf ("%c" ,symbol) ;
else if (token = = rparen) {
/* unstack tokens until left parenthesis */
while (stack [top] != lparen)
print_token (delete(&top)) ;
delete (&top) ; /* discard the left parenthesis */
}
else {
/* remove and print symbols whose isp is greater than or equal to
the current token s icp */
while (isp [stack[top]] >= icp[token])
print_token (delete (&top)) ;
add (&top , token) ;
}
}
while ((token = delete (&top)) ! = eos )
print_token (token) ;
printf ("\n") ;
}

. ‫ كه يك عبارت است‬e ‫ورودي‬e:expression


eval ‫ و پشته مشابه برنامه‬Next token .‫ مي باشد‬e ‫ خروجي شكل پسوندي عبارت ميانوندي‬: ‫توضيح‬
. ‫ در ته پشته قرارداده شده است‬# ً ‫ باشد ضمنا‬# ، e ‫ فرض شده كه آخرين جز عبارت‬V.‫مي باشند‬
; Stack [ 1] = `#` ; top = 1}‫{ مقدار دهي آغازين پشته‬
‫ جاري وارد پشته مي‌خواهد‬icp ‫ مقايسه مي كند و‬icp ‫ در پشته را با‬isp: )‫ دومي( داخلي‬while ‫در حلقه‬
.‫شود‬
. ‫ مي كند و در خروجي چاپ مي كند‬Delete ‫ از باالي پشته‬y ‫تا زماني كه عملگر جديد يكي يكي‬

22
postfix ‫تابع ارزشيابي يک عبارت‬
int eval (void)
{
/* evaluate a postfix expression , expr , maintained as a global variable . '\0' is
the end of the expression . the stack and top of the stack are global variables .
get_token is used to return the tokentype and the character symbol .
operands are assumed to be single character digits */
precedence token ;
char symbol ;
int op1 , op2 ;
int n = 0 ; /* counter for the expression string */
int top = -1 ;
token = get_token (&symbol , &n) ;
while (token != eos) {
if (token = = operand)
add (&top , symbol –'0') ; /* stack insert */
else {
/* remove two operands , perform operation , and return result to
the stack*/
op2 = delete (&top) ; /* stack delete */
op1 = delete (&top) ;
switch (token) {
case plus : add (&top , op1 + op2) ;
breake ;
case minus : add (&top , op1 - op2) ;
breake;
case times : add (&top , op1 * op2) ;
breake;
case divide : add (&top , op1 / op2) ;
breake;
case mod : add (&top , op1 % op2) ;
}
}
token = get_token (&symbol , &n) ;
}
return delete (&top) ; /* return result */
}
‫ مقدار دهي كردن‬proc
‫ چه طور مي توان ارزشيابي كرد؟‬، ‫ شده را‬postfix ‫ به‬V‫يك عبارتي تبديل‬
‫ عملوندها را‬. ‫ با استفاده از پشته مي توان عبارتي را كه به صورت پسوندي تبديل شده ارزشيابي نمود‬: ‫تذكر‬
‫در پشته قرار مي دهيم و به محض رسيدن به يك عملگر از باالي پشته به اندازه مورد نياز عملوند خارج مي‬
‫ه مي‬VV‫ار را ادام‬VV‫ اين ك‬،‫يم‬VV‫كنيم و پس از آنكه آن عمل روي عملوندها انجام شد حاصل را باالي پشته مي نويس‬
.‫دهيم تا به انتهاي عبارت پسوندي برسيم‬

23
‫مثال‪:‬‬
‫عبارت مثال قبل را به ازاي مقادير زير بدست آوريد‪.‬‬
‫‪At 4   ABCD E / +*F/+‬‬
‫‪A= 5 , B= -3 , C= 1 , D=6 , E= 2‬‬ ‫‪, F=4‬‬

‫‪5‬‬ ‫‪-3‬‬ ‫‪1‬‬ ‫‪6‬‬ ‫‪2‬‬ ‫‪/‬‬ ‫‪+‬‬ ‫*‬ ‫‪4‬‬ ‫‪/‬‬ ‫‪+‬‬ ‫‪/‬‬

‫‪‬‬ ‫‪‬‬
‫‪5‬‬ ‫‪5‬‬ ‫‪3-‬‬ ‫‪1‬‬ ‫‪6‬‬ ‫‪2‬‬ ‫‪4‬‬ ‫‪12‬‬
‫‪3-‬‬ ‫‪5‬‬ ‫‪3-‬‬ ‫‪1‬‬ ‫‪6‬‬ ‫‪3‬‬ ‫‪3-‬‬ ‫‪5‬‬
‫‪1‬‬ ‫‪5‬‬ ‫‪3-‬‬ ‫‪1‬‬ ‫‪1‬‬ ‫‪5‬‬ ‫‪4‬‬
‫‪‬‬
‫‪6‬‬ ‫‪5‬‬ ‫‪3-‬‬ ‫‪3-‬‬ ‫*‬
‫‪‬‬ ‫‪2‬‬ ‫‪5‬‬ ‫‪5‬‬
‫‪4‬‬ ‫‪/‬‬ ‫‪+‬‬
‫‪‬‬
‫‪-12‬‬ ‫‪-3‬‬
‫‪5‬‬ ‫‪5‬‬ ‫‪2‬‬
‫‪/‬‬ ‫‪+‬‬

‫صف حلقوي‬
‫در صف هاي عادي ممكن است واقعا صف پر نباشد اما با پيغام پ‪VV‬ر ب‪VV‬ودن ص‪VV‬ف مواج‪VV‬ه ش‪V‬ويم ك‪VV‬ه ي‪VV‬ك پيغ‪VV‬ام‬
‫كاذب است مثالً صفي به طول ‪ 5‬را در نظر بگيريد كه بخواهيم عمليات زير را روي آن انجام دهيم‪:‬‬
‫‪F‬‬ ‫‪r‬‬
‫‪A‬‬ ‫‪B‬‬ ‫‪C‬‬ ‫‪1‬ـ ‪ A‬و ‪ B‬و ‪ C‬وارد مي شوند‬
‫‪F‬‬ ‫‪r‬‬
‫‪A‬‬ ‫‪B‬‬ ‫‪C‬‬ ‫‪2‬ـ ‪ A‬و‪ B‬خارج مي شوند‬
‫‪F‬‬ ‫‪r‬‬
‫‪A‬‬ ‫‪B‬‬ ‫‪C‬‬ ‫‪D‬‬ ‫‪3‬ـ ‪ D‬وارد مي شود‬
‫‪F‬‬ ‫‪r‬‬
‫‪A‬‬ ‫‪B‬‬ ‫‪C‬‬ ‫‪D‬‬ ‫‪4‬ـ ‪ C‬خارج مي شود‬
‫‪F‬‬ ‫‪r‬‬
‫‪A‬‬ ‫‪B‬‬ ‫‪C‬‬ ‫‪D‬‬ ‫‪E‬‬ ‫‪5‬ـ ‪ E‬و ‪ F‬وارد مي شوند‬

‫براي ورود ‪ F‬با پيغام پر بودن صف مواجه مي شويم‪.‬‬

‫در واقع در اين صف تنها دو نفر داخل صف هستند (‪ )E,D‬اما چون كه ‪ rear‬مساوي ‪ max size‬شده‬
‫است پيغام پربودن صف صادر مي شود ‪ ،‬اولين راهي كه براي رف‪V‬ع اين مش‪VV‬كل ب‪V‬ه ذهن مي رس‪V‬د آنس‪V‬ت ك‪VV‬ه‬
‫فرد جديد يعني ‪ F‬را به جاي ‪ A‬قرار دهيم يعني به صورت منطقي فكر كنيم خانه بعد از خانه پنجم‪ ،‬خانه اول‬
‫است به عبارت ديگر صف را به صورت حلقوي يا دايره اي در نظر مي گيريم ‪.‬‬

‫‪E‬‬
‫‪D‬‬
‫‪A‬‬
‫‪F‬‬
‫‪C‬‬ ‫‪B‬‬

‫‪24‬‬
‫در رياضيات براي آنكه بگوييم عددي مقدار بيش از ‪ n‬نداشته باشد يعني از ‪ n‬به يك برسيم مي توانيم‬
‫از ‪ mod‬استفاده كنيم يعني رابطه زير را قرار دهيم ‪:‬‬
‫محدوده از ‪ 1‬تا ‪n‬‬
‫‪rear = ( rear + 1) % n‬‬
‫تذكر مهم‪:‬‬
‫در صف هاي حلقوي يك شكل بوجود مي آيد و آن اين است كه پر و خالي بودن ص‪V‬ف قاب‪V‬ل تش‪V‬خيص‬
‫نيست در اين صف ها اگر ‪ front‬مساوي ‪ rear‬باشد ممكن است صف كامالً پر يا كامالً خالي باشد و ب‪VV‬راي‬
‫رفع اين مشكل يك راه آن است كه ‪:‬‬
‫بين ‪ rear‬و ‪ front‬يك خانه خالي بگذاريم يعني اجازه ندهيم ‪ rear‬به ‪ front‬برسد در اين ح‪VV‬الت ب‪VV‬ه ج‪VV‬اي ‪n‬‬
‫خانه صف از ( ‪ )n-1‬خانه استفاده مي كنيم‪.‬‬

‫(طول صف در مثال قبل ‪ 5‬است ولي ‪ 4‬تا استفاده مي كنيم‪).‬‬

‫‪25‬‬
‫ليست هاي پيوندي‬
‫در فصل هاي قبل با ساختار آرايه ها آشنا شديم آرايه ها تعدادي خانه همنام متوالي و هم جنس در حافظ‪VV‬ه مي‬
‫باشند مهم ترين مزيت آنها همين ترتيب مشخص آنهاس‪VV‬ت ولي گ‪VV‬اهي اوق‪VV‬ات اين م‪VV‬زيت ب‪VV‬ه ض‪VV‬عف تب‪VV‬ديل مي‬
‫شود ‪.‬‬
‫مثالً فرض كنيد در آرايه اي به طول ‪ 1000‬بخواهيم عنصر دهم را حذف كنيم ‪.‬‬
‫ب‪VVV‬راي اين ك‪VVV‬ار باي‪VVV‬د عنص‪VVV‬ر ي‪VVV‬ازدهم را ب‪VVV‬ه ج‪VVV‬اي عنص‪VVV‬ر دهم بنويس‪VVV‬يم س‪VVV‬پس دوازدهم را ب‪VVV‬ه ج‪VVV‬اي‬
‫يازدهم بنويسيم و همين طور عنصر هزارم را به جاي ‪ 999‬بنويسيم ‪ .‬در اين صورت عمالً باي‪VV‬د ‪ 990‬خان‪VV‬ه‬
‫آرايه هر كدام يكي به سمت چپ منتقل شود (شيفت ب‪VV‬ه چپ) ‪ .‬در همين آراي‪VV‬ه اگ‪VV‬ر بخ‪VV‬واهيم بين خان‪VV‬ه پنجم و‬
‫ششم يك خانه جديد اضافه كنيم عمالً بايد ‪ 995‬خانه به سمت راست منتقل شوند تا جا براي خان‪VV‬ه جدي‪VV‬د ايج‪VV‬اد‬
‫شود ‪ ،‬عمالً در ساختارهايي كه عمليات حذف و اضافه در آن ه‪V‬ا زي‪V‬اد باش‪VV‬د اس‪VV‬تفاده از آراي‪V‬ه ه‪V‬ا مق‪V‬رون ب‪V‬ه‬
‫صرفه نيست ‪ ،‬به همين منظور بهتر آنست كه ‪:‬‬
‫ترتيب خانه ها را به شكل منطقي در نظر بگيريم يعني خان‪VV‬ه ه‪VV‬اي اول ت‪VV‬ا ه‪VV‬زارم ب‪VV‬ه ص‪VV‬ورت ف‪VV‬يزيكي پش‪VV‬ت‬
‫سرهم نباشند چنين ساختاري را ليست پيوندي ( ‪ ) Linked List‬مي ناميم ‪.‬‬
‫هر ليس‪V‬ت پيون‪VV‬دي ي‪V‬ا زنج‪VV‬ير( ‪ )chain‬از تع‪V‬دادي گ‪V‬ره ( ‪ )node‬تش‪VV‬كيل ش‪VV‬ده ك‪VV‬ه در آن ه‪V‬ر گ‪VV‬ره ح‪VV‬داقل‬
‫دوقسمت دارد ‪:‬‬
‫يكي قسمت ‪ data‬و ديگري ربط يا پيوند( ‪ )Link‬كه به گره بعدي اشاره مي كند‪. V‬‬
‫‪node‬‬
‫‪data‬‬ ‫‪Link‬‬
‫مثالً‬
‫‪head‬‬ ‫زنجير زير به نام ‪ head‬شامل ‪ 1000‬گره است ‪:‬‬
‫‪a0‬‬ ‫‪a1‬‬ ‫‪a2‬‬ ‫‪a3‬‬ ‫‪a999‬‬ ‫^‬

‫به هيچ جا اشاره نمي كند و تهي و به عبارتي ^ يعني ‪NULL‬‬

‫ساختار ‪node‬‬
‫در زب‪VV‬ان ‪ C‬مي ت‪VV‬وانيم س‪VV‬اختار ‪ node‬را ب‪VV‬ه ص‪VV‬ورت زي‪VV‬ر مع‪VV‬رفي ك‪VV‬نيم اين س‪VV‬اختار در قس‪VV‬مت ن‪VV‬وع داده‬
‫‪ Struct‬با استفاده از دستور ‪ Struct‬به صورت زير تعريف مي شود‪:‬‬
‫ساختار ‪node‬‬
‫{ ‪Struct node‬‬
‫‪int‬‬ ‫; ‪data‬‬
‫; ‪struct node *link‬‬
‫;}‬

‫‪ Pointer‬در واقع اشاره گري به يك ساختار از نوع ‪ node‬مي باشد بنابراين بايد ساختار اشاره گر را ن‪VV‬يز‬
‫در قسمت‪ typedef‬قبل از معرفي ساختار‪ node‬تعريف كنيم ‪ ،‬عالمت اشاره گره‪V‬ا در زب‪V‬ان ‪ * ، C‬مي‬
‫باشد ‪.‬‬
‫مثال‪ :‬برنامه زير يك ليست پيوندي با سه گره به نام‌هاي ‪first‬و ‪ second‬و ‪ third‬به ش‪VV‬كل زي‪VV‬ر ايج‪VV‬اد‬
‫مي‌گردد‪(.‬تذكر‪ :‬دربرنامه كلمات كليدي حروف بزرگتر و متغيرها حروف كوچك)‬
‫‪First‬‬ ‫‪second‬‬ ‫‪third‬‬
‫‪10‬‬ ‫‪20‬‬ ‫‪30 Null‬‬

‫>‪#include <stdio.h‬‬
‫{ ‪Struct node‬‬
‫‪int‬‬ ‫‪data‬‬
‫‪struct node‬‬
‫;}‬
‫; ‪Typedef struct node chain‬‬
‫; ‪Typedef chain *ptrnode‬‬

‫‪26‬‬
‫; ) ( ‪Main‬‬
‫{‬
‫;‪Chain first,second,third,ptrnode,p‬‬
‫;‪First.data = 10‬‬
‫; ‪First.link = &second‬‬
‫; ‪Second.data = 20‬‬
‫;‪Second.link = &third‬‬
‫; ‪Third.data = 30‬‬
‫; ‪Third.link = ( ptrnode ) null‬‬
‫}‬
‫برنامه اوليه هيچ خروجي ندارد ‪ ،‬لذا در پايين برنامه را طوري نوشته ايم تا داراي خروجي باشد ‪:‬‬
‫; ‪P = &first‬‬
‫) ‪While ( p!= ( ptrnode ) null‬‬
‫{‬
‫‪Printf ( "%d\n", p‬‬ ‫; )‪data‬‬
‫‪p=p‬‬ ‫; ‪link‬‬
‫}‬

‫‪P‬‬

‫‪data‬‬ ‫‪Link‬‬
‫در زبان ‪ C‬توسط تابع ‪ malloc‬مي توانيم حافظه تخصيص دهيم ‪ p = malloc(sizeof(chain)) .‬باعث‬
‫مي شود که در حافظه به اندازه ‪ ))size‬ساختار ‪ ، chain‬حافظه در نظر گرفته مي شود و ضمنا ً ‪ P‬يک‬
‫اشاره گر به آن حافظه مي باشد ‪ .‬با اين خاصيت مي توانيم هرگاه که يک گره الزم بود آن را ايجاد کنيم‪.‬‬

‫تذكر‪ :‬قسمت اول برنامه مثال قبل هيچ خروجي روي صفحه نمايش ن‪V‬دارد ام‪V‬ا زنج‪V‬ير رادر حافظ‪V‬ه ايج‪V‬اد مي‬
‫كند ‪.‬‬

‫تذكر‪ :‬عمالً مهم‌ترين كاربرد ليست هاي پيوندي پويايي آنهاست يعني اينكه بتوانيم هر زمان كه به يك گره نياز‬
‫داشتيم آنرا ايجاد كنيم ‪ ،‬در برنامه زير اين پويايي به كار گرفته مي شود ‪ .‬در برنامه زير تعدادي ع‪VV‬دد حقيقي‬
‫نامنفي از ورودي خوانده مي شود و توسط آنهايك ليست پيوندي ايجاد مي شود كه اولين گره آن با اش‪VV‬اره گ‪VV‬ر‬
‫‪ head‬مشخص شده است ‪ ،‬سپس زنجير پيمايش ش‪VV‬ده و مجم‪VV‬وع مق‪VV‬اديري ك‪VV‬ه در گ‪VV‬ره ه‪VV‬اي آن وج‪VV‬ود دارد‬
‫تعيين مي شود ‪ ،‬همچنين فرض مي كنيم اولين عدد حتما ً نامنفي باشد ‪.‬‬
‫در اين برنامه ‪ Pointer‬را به اختصار ‪ Ptr، data‬را ‪ d‬و ‪ link‬را ‪ L‬قرار مي دهيم ‪.‬‬
‫برنامه زير تعدادي عدد حقيقي نا منفي از ورودي مي خواند و آن را در يک ليست به نام ‪ Head‬قرار مي‬
‫دهد ‪ .‬سپس ليست را پيمايش کرده و مجموع مقادير عناصري که در گره ها وجود دارد را محاسبه و چاپ‬
‫مي کند ‪ ( .‬زماني که استفاده کننده عدد منفي وارد کند از برنامه خارج مي شود ‪) .‬‬

‫>‪#include <alloc.h‬‬
‫>‪#include <stdio.h‬‬
‫{ ‪Struct node‬‬
‫; ‪Float d‬‬
‫; ‪Struct node *L‬‬
‫;}‬
‫; ‪Typedef struct nodes‬‬
‫; ‪Typedef nodes *ptrnode‬‬
‫) ( ‪Main‬‬
‫{‬
‫; ‪Ptrnode head,p1,p2‬‬
‫; ‪Float x, sum = 0‬‬

‫‪27‬‬
Scanf ("%f",&x) ;
P1 = ( ptrnode ) malloc ( sizeof ( nodes)) ;
P1 d=x;
Head = p1 ;
Scanf ( "%f", &x ) ;
While ( x >= 0 )
{
p2 = ( ptrnode ) malloc ( sizeof ( nodes )) ;
p2 d=x;
p1 L = p2 ;
p1 = p2 ;
scanf ( "%f" , &x) ;
}
P2 L = ( ptrnode ) null ;
P1 = head ;
While ( p1 != ( ptrnode ) null) ;
{
Sum = sum + p1 d;
P1 = p1 L;
}
Printf ( "sum = %f\n" , sum ) ;
}

. ‫) نماييد‬Trace (‫ رديابي‬x=13.5‫ و‬11‫ و‬8.5 ‫ و‬13 ‫و‬1- ‫مثال قبل را به ازاي‬


‫شرط مقابل‬ Sum ‫خروجي‬
WHILE X
13.5 0 sum = 46
11 true 13.5
8.5 true 24.5
13 true 33
-1 false 46

Head q q q
13.5 11 8.5 13
×P× P× P× P
Head q
13.5 11 8.5 13 ^
×P P× P× P× P× P

: ‫تمرين‬
‫برنامه‌اي بنويسيد كه يك ليست پيوندي از تعدادي عدد حقيقي نامنفي ايجاد كند سپس ليست را پيمايش كرده و‬
‫ت را‬V‫ل ليس‬V‫داد داخ‬VV‫انگين اع‬VV‫ موجود در ليست را به همراه كوچكترين عدد ليست و همچنين مي‬V‫بزرگترين عدد‬
. ‫در خروجي چاپ كند‬

28
‫رشته‌ها‬
‫‪ Concat‬الحاق دو رشته‬
‫‪SubStr ( S , i , j): string‬‬

‫‪S:a‬‬ ‫‪b‬‬ ‫‪c‬‬ ‫‪d‬‬ ‫‪e‬‬ ‫‪f‬‬ ‫‪g‬‬ ‫‪h‬‬

‫; )‪SubStr ( S , 1 , 3‬‬ ‫‪a‬‬ ‫‪b‬‬ ‫‪c‬‬

‫از كاركتر ‪ i‬ام رشته ‪ S‬به طول ‪ j‬جدا مي كند مثالً در اين مثال اگر بگوييم ‪:‬‬
‫)‪ sub str ( s,4,2‬و ‪ d‬مي دهد ‪.‬‬ ‫‪b‬‬
‫يافتن يك الگو در يك رشته‬

‫‪Pos S‬‬

‫‪S : C b a b C a b C a d a a a b C a b C a C a b d d‬‬
‫برابر‬
‫نابرابر‬ ‫نابرابر‬

‫‪P:a b C a b C a C a b‬‬

‫‪Pos P‬‬
‫يك ‪ abc‬پيدا كرديم به اندازه ‪ abc‬برمي گرديم عقب ‪ .‬اين عقب و جلو رفتن ها در اين رشته هاي زمان گير‬
‫مي باشد ‪.‬‬
‫)‪ O ( lengh p , lengh S‬زمان اجرا‬
‫فقط روي ‪ P‬برگشت به عقب و در ‪ S‬به اين صورت نيست و برگشت به عقب ندارد و جلو مي رود ‪.‬‬
‫مثال ‪ :‬در رشته مقابل ‪A B C D E F G H I J‬‬
‫اينجا براي پيداكردن‪ GH V‬مشكلي نيست چون يكي بيشتر نيست ‪.‬‬

‫‪29‬‬
‫تابع شكست‬
‫تابع شكست در واقع يك بردار يك آرايه است‪.‬‬
‫اگر در كاراكتر اول شكست بخوريم بايد به خانه اول برگرديم بنابراين خانه اول صفر است‪.‬‬
‫محاسبه تابع شکست‬
‫) ‪void fail ( char *pat‬‬
‫{‬
‫‪/* compute the pattern s failure function */‬‬
‫; )‪int n = strlen (pat‬‬
‫; ‪failure [0] = -1‬‬
‫{ )‪for ( j = 1 ; j < n ; j ++‬‬
‫; ]‪i = failure [ j-1‬‬
‫))‪while (( pat [ j] != pat [ i+1] && (i >= 0‬‬
‫; ]‪i =if failure [i‬‬
‫)]‪if (pat [ j] = = pat [ i+1‬‬
‫; ‪failure [ j] = i+1‬‬
‫; ‪else failure [ j] = -1‬‬
‫}‬
‫}‬

‫در كاراكتر ‪ 5‬شكست‪ V‬خورد به كاراكتر ‪ 2‬بيايد‪.‬‬

‫‪j:‬‬ ‫‪0‬‬ ‫‪1‬‬ ‫‪2‬‬ ‫‪3‬‬ ‫‪4‬‬ ‫‪5‬‬ ‫‪6‬‬ ‫‪7‬‬ ‫‪8‬‬
‫‪9‬‬
‫‪:F‬‬ ‫‪0‬‬ ‫‪0‬‬ ‫‪0‬‬ ‫‪1‬‬ ‫‪2‬‬ ‫‪3‬‬ ‫‪4‬‬ ‫‪0‬‬ ‫‪1‬‬ ‫‪2‬‬
‫‪P:‬‬ ‫‪a‬‬ ‫‪b‬‬ ‫‪c‬‬ ‫‪a‬‬ ‫‪b‬‬ ‫‪c‬‬ ‫‪a‬‬ ‫‪c‬‬
‫با توجه به ‪ p‬و‬ ‫از اينجا برمي گرديم ابتدا‬
‫‪s‬‬
‫‪i‬‬
‫‪j‬‬
‫‪0‬‬
‫‪2‬‬
‫‪1‬‬
‫‪3‬‬
‫‪ Failure‬شكست‬ ‫‪2‬‬
‫‪4‬‬
‫‪P 5‬‬ ‫‪3‬‬ ‫محاسبه مي كند تابع شكست را براي الگوي ‪2 :‬خط‬
‫‪4‬‬
‫‪6‬‬
‫‪1‬‬
‫‪7‬‬
‫‪0‬‬
‫‪8‬‬

‫‪9‬‬

‫‪10‬‬
‫اگر در كاراكتر چهارم شكست خوردي بيايد كاراكتر اول چون يكسانند‪.‬‬
‫تطابق الگو توسط تست انديس ها در ابتدا‬
‫) ‪int nfind (char *string , char *pat‬‬

‫‪30‬‬
‫{‬
‫‪/* match the last character of pattern first , and then match from the beginning‬‬
‫‪*/‬‬
‫; ‪int i , j , start = 0‬‬
‫; ‪int lasts = strlen ( string) -1‬‬
‫; ‪int lastp = strlen ( pat) -1‬‬
‫; ‪int endmatch = lastp‬‬
‫{ )‪for (I = 0 ; endmatch <= lasts ; endmatch++ , start++‬‬
‫)]‪if (string [endmatch] = = pat [lastp‬‬
‫)‪for ( j = 0 ; I = start ; j < lastp && string[i] = = pat [ j] ; i++ , j++‬‬
‫;‬
‫)‪if ( j = = lastp‬‬
‫‪return start ; /* successful */‬‬
‫}‬
‫; ‪return -1‬‬
‫}‬
‫( ‪ match maker‬معرف )‬ ‫‪ Match‬منطبق بودن (يكسان بودن)‬
‫زير رشته ‪ Pat‬و رشته ‪ S‬و تابع ‪F‬‬
‫‪1 2 3 4 5 6 7 8 9 10‬‬
‫‪P: a b c a b c a c a b‬‬
‫‪Pos s‬‬
‫‪0‬‬ ‫‪1‬‬ ‫‪2‬‬ ‫‪3‬‬ ‫‪4‬‬ ‫‪5‬‬ ‫‪6‬‬ ‫‪7‬‬ ‫‪8‬‬ ‫‪9‬‬ ‫‪10‬‬ ‫‪11‬‬ ‫‪12‬‬ ‫‪13‬‬ ‫‪14 15‬‬ ‫‪16 17 18 19‬‬
‫‪S: C‬‬ ‫‪b‬‬ ‫‪a‬‬ ‫‪b‬‬ ‫‪C‬‬ ‫‪A‬‬ ‫‪b‬‬ ‫‪C‬‬ ‫‪a‬‬ ‫‪b‬‬ ‫‪A‬‬ ‫‪a‬‬ ‫‪A‬‬ ‫‪b‬‬ ‫‪C‬‬ ‫‪a‬‬ ‫‪B‬‬ ‫‪C Acab‬‬

‫حلقه را تا زماني ادامه مي دهيم كه يكي از ‪ pos p‬يا ‪ pos s‬تمام شود‪.‬‬
‫‪Pos S‬‬ ‫‪Pos P‬‬
‫‪1‬‬ ‫‪1‬‬
‫‪2‬‬ ‫)مساوي نيستند سراغ كاراكتر سوم مي رويم( ‪2‬‬
‫‪3‬‬ ‫‪3‬‬
‫‪4‬‬ ‫‪4‬‬
‫‪5‬‬ ‫‪5‬‬
‫‪6‬‬ ‫)وقتي مساويند هردو يكي جلو مي روند( ‪6‬‬
‫‪7‬‬ ‫‪7‬‬
‫‪8‬‬ ‫) مساوي نيست ( ‪8‬‬
‫‪9‬‬ ‫‪9‬‬ ‫روي كاراكتر پنجم‬
‫مي‌ آييم‬
‫‪10‬‬ ‫‪6‬‬ ‫‪Pos P : = F ( Pos P – 1‬‬
‫‪)+1=5‬‬
‫‪11‬‬ ‫‪3‬‬
‫‪12‬‬ ‫‪1‬‬
‫‪13‬‬ ‫‪2‬‬
‫‪1‬‬ ‫‪2‬‬
‫صف و پشته پيوندي‬
‫در فصل قبل ديديم كه با استفاده از آرايه چگونه مي ت‪VV‬وان س‪VV‬اختار ص‪VV‬ف را ش‪VV‬بيه س‪VV‬ازي ك‪VV‬رد ب‪VV‬ا اس‪VV‬تفاده از‬
‫ليست پيوندي نيز چنين كاري امكان پذير است در يك صف پيوندي دو اشاره گر الزم داريم كه يكي به ابتداي‬
‫صف اشاره كند ( ‪ ) Front‬و ديگري به انتهاي صف (‪ rear‬يا ‪) tail‬‬
‫‪Front‬‬ ‫‪rear‬‬

‫‪n‬‬
‫به راحتي مي توان يك گره جديد به انتهاي صف اضافه كرد ‪.‬‬

‫‪31‬‬
‫اضافه کردن يک گره به انتهاي يک ليست‬
void attach (float coefficient , int exponent , poly_pointer *ptr)
{
/* create a new node with coef = coefficient and expon = exponent , attach it
to the node pointed to by ptr . ptr is updated to point to this new node */
poly_pointer node ;
temp = (poly_pointer) malloc (sizeof (poly_node)) ;
if (IS_FULL(temp)) {
fprintf (stderr , "the memory is full \n" ) ;
exit ( l ) ;
}
temp -> coef = coefficient ;
temp -> expon = exponent ;
(*ptr) -> link = temp ;
*ptr = temp ;
}
.‫ به پروسيجر ارسال مي شود‬y‫ و‬i ‫ مي گيرد و دو پارامتر‬X ‫يك گره جديد به نام‬
}{ ‫توضيح‬
V.‫ ام اضافه مي كند‬i ‫ را به صف‬y ‫گره‬
‫ درغير اين صورت اگر صف خالي نبود‬front ‫ جديد‬X ‫شرط براي اين است كه اگر صف خالي بود گره‬
X .‫ شود‬rear ‫بايد‬
Front

Delete
‫ حافظه را آزاد مي كند‬Dispose

‫حذف از ابتداي يک صف پيوندي‬


element deleteq (queue_pointer *front)
{
/* delete an element from the queue */
queue_pointer temp = *front ;
element item ;
if (IS_EMPTY (*front)) {
fprintf ( stderr , "the queue is empty \n") ;
exit ( l ) ;
}
item = temp -> item ;
*front = temp -> link ;
free (temp) ;
return item ;
}
.‫ را حذف مي كنيم‬Data ‫وقتي يك نفر از صف برمي داريم يك‬

F rear

32
‫‪X‬‬

‫در مورد پشته‬


‫‪Top‬‬
‫ساختار پشته پيوندي‬
‫‪Top‬‬
‫براي اضافه يك ‪ X‬جديد مي‌گيريم‬ ‫يا‬ ‫^‬

‫^‬

‫در مورد پشته پيوندي نيز عمليات به سادگي امكان پذير است زيربرنامه‌هاي ‪ ADD Stack‬و ‪Delete‬‬
‫‪ Stack‬که عمليات اضافه و حذف را انجام مي دهند در باال آمده است‪.‬‬
‫‪ null‬است بنابراين چك نمي كنيم پشته خالي است يا نه ‪.‬‬ ‫چون هنگام ايجاد پشته ‪top‬‬ ‫‪‬‬
‫‪X‬‬
‫‪Top‬‬ ‫^‬
‫بعد‬

‫‪Top‬‬
‫چند جمله‌ايهاي پيوندي ‪:‬‬
‫در فصل هاي قبل با استفاده از آرايه ها توانستيم چند جمله اي ها را ذخيره كنيم و عمليات ساده رياض‪pp‬ي را‬
‫روي آن ها انجام دهيم ‪ ،‬با استفاده از ليست هاي پيوندي نيز به راحتي مي توان چند جمل‪pp‬ه اي ه‪p‬ا را ش‪p‬بيه‬
‫سازي كرد براي اين منظور هر جمله يك چند جمله اي را يك گره از ليست پيوندي مي گيريم كه س‪pp‬ه قس‪pp‬مت‬
‫دارد يكي قسمت ضريب كه عدد حقيقي است ‪ ،‬ديگري قسمت توان كه عدد صحيح است و سومي اش‪pp‬اره گ‪pp‬ر‬
‫( گره چند جمله اي)‪node poly‬‬ ‫به گره بعدي (جمله بعدي )‬
‫‪Coef‬‬ ‫‪exp‬‬ ‫‪Link‬‬

‫جمع دو چند جمله اي‬


‫)‪poly_pointer padd (poly_pointer a , poly_pointer b‬‬
‫{‬
‫‪/* return a polynomial which is the sum of a and b */‬‬
‫; ‪poly_pointer front , rear , temp‬‬
‫; ‪int sum‬‬
‫; ))‪rear = (poly_pointer) malloc (sizeof (poly_node‬‬
‫{ ))‪if (IS_FULL(rear‬‬
‫; )"‪fprintf (stderr , "the memory is full \n‬‬
‫; ) ‪exit ( l‬‬
‫}‬
‫; ‪front = rear‬‬
‫)‪while (a && b‬‬
‫{ ))‪switch (COMPARE (a -> expon , b -> expon‬‬

‫‪33‬‬
case -1 : /* a -> expon < b->expon */
attach (b -> coef , b -> expon , &rear) ;
b = b -> link ;
breake;
case 0 : /* a ->expon = b ->expon */
sum = a -> coef + b -> coef ;
if (sum) attach (sum , a -> expon , &rear) ;
a= a -> link ; b = b -> link ;break ;
case 1 : /* a ->expon > b ->expon */
attach (a -> coef , a -> expon , &rear) ;
a = a -> link ;
}
/* copy rest of list a and then list b */
for ( ; a ; a = a -> link ) attach ( a -> coef , a -> expon , &rear ) ;
for ( ; b ; b = b -> link ) attach (b -> coef , b -> expon , &rear) ;
rear -> link = NULL ;
/* delete extra initial node /*
temp = front ; front = front -> link ; free (temp) ;
return front ;
}
V.‫ ضميمه مي كند‬، ‫= ملحق كردن‬attack
. ‫ را انجام مي‌دهد‬New term ‫ كار همان‬attack
: ‫نمونه سوال‬
1.
For ( i = 1 ; i =< n ; i++)
{
j = 2*i ; K=n-i ;
While ( j <= k )
j=2*j;
}
4.
F(q):= IF isemptr (q) Thenq;
F(ADD Q [ i,q]) : : = IF Isempty (q) Then ADD Q (i,q);
Else ADD Q (Delete Q, F (Delete Q));

34
‫گراف ها و درخت ها‬
‫هر گراف ‪ G‬از دو مجموعه تشكيل شده است يكي ‪ V‬و ديگري ‪. E‬‬
‫‪ V‬يك مجموعه غير تهي و متناهي است ك‪VV‬ه آن را مجموع‪VV‬ه رئ‪VV‬وس ي‪VV‬ا گ‪VV‬ره ه‪VV‬ا ي‪VV‬ا نق‪VV‬اط گ‪VV‬راف مي ن‪VV‬اميم و‬
‫‪E‬نيز تعدادي از زيرمجموعه هاي دو عضوي‪ V‬است ‪ E ،‬را مجموعة يالها ي‪V‬ا لب‪VV‬ه ه‪V‬ا ي‪V‬ا خط‪V‬وط گ‪V‬راف مي‬
‫ناميم‪ .‬در هر گراف اگر بين دو راس يال وجود داشته باشد آنها را مجاور مي ناميم و تعداد رئوسي را ك‪VV‬ه ب‪VV‬ا‬
‫يك راس دلخواه مجاور هستند درجه رأس مي ناميم ‪.‬‬
‫مثالً در گراف زير راس ‪ b‬درجه ‪ 2‬است و رأس ‪ d‬درجه ‪ 3‬مي باشد‪ V ) .‬رئوس و ‪ E‬يالها)‬
‫)‪G=(V,E‬‬ ‫‪C‬‬
‫‪a‬‬
‫‪b‬‬
‫‪e‬‬ ‫‪d‬‬ ‫}‪V={a,b,c,d,e,f,p,q‬‬

‫‪p‬‬
‫‪f‬‬
‫‪q‬‬
‫‪G‬‬
‫اگر بتوانيم از يك راس گراف شروع كرده و با گذشتن از يالها و رئوس گراف ب‪V‬ه ي‪V‬ك راس ديگ‪V‬ر برس‪VV‬يم ب‪VV‬ه‬
‫شرط آنكه هيچ راس و يالي تكراري نباشد مي گوييم بين دو راس مسير وجود دارد‪.‬‬

‫اگر بين هر دو راس دلخواه گراف حداقل يك مسير وجود داشته باشد آن گراف را همبند يا مرتبط مي ناميم‪.‬‬
‫مثال قبل مثالي از يك گراف همبند مرتبط نبود زيرا بين ‪ b‬و ‪ e‬هيچ مسيري وجود ندارد ‪.‬‬

‫اگر از يك راس شروع كرده و با گذشتن از يال ها و رئوس بتوانيم مجدداً به همان رأس بازگرديم ب‪V‬دون آنك‪V‬ه‬
‫راس و يال تكراري وجود داشته باشد ‪ ،‬آنگاه يك دوره خواهيم داشت ‪.‬‬
‫‪ C‬يك دوره به طول ‪ 3‬است زيرا سه يال دارد ‪.‬‬ ‫‪d‬‬ ‫‪e‬‬ ‫مثالً درگراف قبل ‪C‬‬
‫‪ d‬يك دوره به طول ‪ 4‬است ‪.‬‬ ‫‪F‬‬ ‫‪e‬‬ ‫‪c‬‬ ‫‪d‬‬

‫تعريف درخت‬
‫هر گراف همبند بدون دوره را درخت مي ناميم ‪.‬‬
‫مثال‪:‬‬
‫درخت مقابل ‪ 11‬راس و ‪10‬يال دارد ‪.‬‬

‫نقطه يك درخت مي باشد که تنها يك راس دارد و بدون يال مي باشد ‪.‬‬ ‫‪‬‬

‫نكات زير در مورد درختها هم ارزي باشند (معادلند ) ‪:‬‬

‫‪ G‬يك درخت است ‪.‬‬ ‫‪)1‬‬


‫بين هر دو راس دلخواه ‪ G‬فقط يك مسير منحصر به فرد داريم ‪.‬‬ ‫‪)2‬‬
‫‪ G‬يك گراف همبند ‪ n‬راسي است كه ‪ n-1‬يال دارد ‪.‬‬ ‫‪)3‬‬
‫‪ G‬يك گراف ‪ n‬راسي با ‪ n-1‬يال است كه همبند باشد ‪.‬‬ ‫‪)4‬‬
‫‪ G‬يك گراف ‪ n‬راسي با ‪ n-1‬يال است كه دوره نداشته باشد ‪.‬‬ ‫‪)5‬‬
‫‪ G‬يگ گراف ‪ n‬راسي بدون دوره است كه ‪ n-1‬يال دارد ‪.‬‬ ‫‪)6‬‬
‫‪ G‬مي نيمال همبند است يعني گراف همبندي است ك‪VV‬ه اگ‪VV‬ر ي‪VV‬ك ي‪VV‬ال آن برداش‪VV‬ته ش‪VV‬ود ناهمبن‪VV‬د مي‬ ‫‪)7‬‬
‫شود ‪.‬‬
‫‪ G‬يك گراف ماكزيمال نادوره است يعني با اضافه شدن يك يال به آن حتما ً دوره خواهد داشت ‪.‬‬ ‫‪)8‬‬

‫‪35‬‬
‫در كامپيوتر درخت ها را به صورت بازگشتي تعريف مي كنند به صورت زير‪:‬‬
‫تعريف ‪:‬‬
‫درخت مجموعه‌اي از چندگره به صورت زير مي‌باشد ‪:‬‬
‫الف ـ گره خاصي به نام ريشه دارد ‪.‬‬
‫‪T 1 ,T,...,‬افراز شده اند ‪ ،‬به طوري ك‪V‬ه ه‪V‬ر ك‪V‬دام از‬
‫‪2‬‬ ‫‪T‬‬ ‫‪N‬‬ ‫هاي‬ ‫مجموعه‬ ‫ب ـ بقيه گره‌ها به جز ريشه به‬
‫ها را يك زير درخت ريشه مي‌ناميم‪.‬‬ ‫‪T i‬‬
‫مثال‪:‬‬
‫‪T3‬‬
‫‪T2‬‬

‫‪T1‬‬

‫دردرخت هر گره اي را مي توان ريشه گرفت‪.‬‬ ‫‪‬‬


‫در هر درختي كه ريشه داشته باشد سطح يا ‪ Level‬تعريف مي كنيم‪.‬‬

‫تعاريف مقدماتي دردرخت‬


‫در هر درخت ريشه را در سطح (‪ )Level‬يك تعريف مي كنيم و تمام رئوسي را كه فاصله آن‌ها ت‪VV‬ا‬
‫ريشه برابر ‪ K‬باشد در سطح ‪ K+1‬در نظر مي گيريم‪ ،‬اگر يك راس بخصوص در سطح ‪ k‬ام با رئوس‪VV‬ي در‬
‫سطح ‪ k+1‬ام مجاور باش‪VV‬د راس س‪V‬طح ‪ K‬را پ‪VV‬در ي‪VV‬ا وال‪VV‬د رئ‪VV‬وس س‪VV‬طح ‪ k+1‬مي ن‪VV‬اميم و آن رئ‪VV‬وس س‪V‬طح‬
‫‪ K+1‬را فرزن‪VV‬دان راس س‪VV‬طح ‪ K‬ام نامگ‪VV‬ذاري مي ك‪VV‬نيم ‪ ،‬خ‪VV‬ود فرزن‪VV‬دان (هم ني‪VV‬ا) نامي‪VV‬ده مي ش‪VV‬وند مثالً در‬
‫درخت زير راس ‪ C‬سه فرزند به نام هاي ‪ G , H , I‬دارد ‪ ،‬بنايراين ‪ G , H , I‬هم نيا هستند توجه داريم‬
‫كه ‪ J,I‬هم نيا نيستند ‪.‬‬
‫حداكثر سطح در يك درخت را عمق درخت مي ناميم ‪.‬‬
‫مثالً در درخت زير عمق ‪ 5‬است ‪.‬‬
‫ً‬
‫در هر درخت درجه راس براب‪VV‬ر تع‪VV‬داد‪ V‬فرزن‪VV‬دان وي اس‪VV‬ت مثال رأس ‪ C‬درجة‪ 3‬اس‪VV‬ت و راس ‪ D‬درج‪VV‬ه ي‪VV‬ك‬
‫است ‪.‬‬
‫راس ‪ K‬نيز درجة صفر است زيرا فرزندي ندارد ‪ ،‬رئوس درجة صفر را برگ مي ناميم ‪.‬‬
‫* تعريف درجه در گراف و درخت با هم متفاوت است ‪.‬‬
‫‪A‬‬

‫‪B‬‬
‫‪E‬‬
‫‪C‬‬ ‫‪D‬‬
‫‪F‬‬ ‫‪K‬‬ ‫‪L‬‬
‫‪G‬‬ ‫‪H‬‬ ‫‪I‬‬ ‫‪J‬‬

‫‪P‬‬ ‫‪O‬‬ ‫‪N‬‬ ‫‪M‬‬

‫‪Q‬‬

‫نمايش درخت‪:‬‬
‫دو ابزار اساسي براي نمايش درخت ها وجود دارد يكي آراي‪VV‬ه ه‪VV‬ا و ديگ‪VV‬ري ليس‪VV‬ت ه‪VV‬اي پيون‪VV‬دي ‪ ،‬معم‪VV‬والً‬
‫براي نمايش درخت از آرايه استفاده نمي شود ‪ ،‬براي استفاده از ليست پيوندي بايد گره هايي تعريف ك‪VV‬نيم ك‪VV‬ه‬
‫يك قسمت ‪ Data‬و چند قسمت پيوند‪ Link V‬داشته باش‪VV‬د ‪ ،‬تع‪VV‬داد‪ Link V‬ه‪VV‬ا در واق‪VV‬ع براب‪VV‬ر ب‪VV‬ا بيش‪VV‬ترين درج‪VV‬ة‬
‫رئوس درخت است ‪.‬‬
‫در مثال قبل بيشترين فرزندان را ‪ A‬دارد كه ‪ 4‬فرزند است پس بايد گره هايي ‪ 5‬قسمتي تعريف كنيم كه ي‪VV‬ك‬
‫قسمت ‪ Data‬دارد و ‪ 4‬اشاره گر به نامهاي ‪ ch1 , ch4‬كه به فرزندان گره اشاره مي كنيم‪.‬‬

‫‪36‬‬
‫‪data‬‬ ‫‪Child 1‬‬ ‫‪Child n‬‬
‫اشاره گرها‬

‫‪data‬‬ ‫‪Ch 1‬‬ ‫‪Ch 2‬‬ ‫‪Ch 3‬‬ ‫‪Ch 4‬‬

‫با اين حساب درخت مثال قبل را مي توان به شكل زير نشان داد ‪:‬‬

‫‪A‬‬

‫‪B‬‬ ‫^‬ ‫^‬ ‫^‬ ‫‪C‬‬ ‫^‬ ‫‪D‬‬ ‫^‬ ‫^‬ ‫^‬ ‫‪E‬‬ ‫^‬ ‫^‬

‫‪F ^ ^ ^ ^ G‬‬ ‫^ ^ ^ ^ ‪^ ^ H‬‬ ‫‪I ^ ^ ^ ^ J‬‬ ‫^ ^ ^ ^ ‪^ ^ K ^ ^ ^ ^ L‬‬

‫‪P‬‬ ‫^‬ ‫^‬ ‫^‬ ‫^‬ ‫‪O‬‬ ‫^‬ ‫^‬ ‫^‬ ‫^ ‪N‬‬ ‫^‬ ‫^‬ ‫^‬ ‫‪M‬‬ ‫^ ^‬ ‫^‬ ‫^‬

‫‪Q‬‬ ‫^‬ ‫^‬ ‫^‬ ‫^‬


‫‪17×4 = 68‬‬
‫‪68-16=52‬‬ ‫تعداد‪ V‬اشاره گرها ‪NULL‬‬
‫‪ :16‬تعداد‪ V‬اشاره گرهاي استفاده شده (تعداد‪ V‬يالها)‬
‫تمرين ‪:‬‬
‫اگر درجه گراف برابر ‪ d‬باشد و ‪ n‬راس داشته باشيم ‪ ،‬آنگاه تعداد‪ V‬اشاره گرهاي ‪ Null‬برابر است با ‪:‬‬
‫‪nd – (n – 1) = (d – 1)n + 1‬‬

‫همانطور كه مشاهده مي شود و تعداد‪ V‬اشاره گرهاي ‪ NULL‬در روش قبل بس‪VV‬يار زي‪V‬اد اس‪V‬ت ب‪VV‬ه همين‬
‫خاطر از روش ديگري استفاده مي كنيم كه در آن تعداد اش‪VV‬اره گره‪VV‬اي ‪ NULL‬ك‪VV‬اهش ياب‪VV‬د‪ ،‬اين روش جدي‪VV‬د‬
‫روش فرزند چپ ـ هم نياي راست ناميده مي ش‪V‬ود‪ .‬در اين روش ه‪VV‬ر گ‪VV‬ره ح‪VV‬داكثر ب‪V‬ا دو گ‪VV‬ره در س‪V‬طح بع‪VV‬د‬
‫مجاور است كه اين گره ها يكي فرزند چپ گره است و ديگري هم نياي راست گره است ‪.‬‬

‫گره‬ ‫فرزند چپ‬ ‫هم‌نياي‌راست‬

‫عمق درخت افزايش يافته و برابر ‪ 7‬است و تعداد‪ V‬اشاره گرهاي ‪ NULL‬كاهش يافته ‪.‬‬

‫‪1‬‬ ‫‪A‬‬

‫‪37‬‬
‫‪2‬‬ ‫‪B‬‬

‫‪3‬‬ ‫‪F‬‬
‫‪C‬‬
‫‪4‬‬
‫‪G‬‬ ‫‪D‬‬
‫‪5‬‬ ‫‪P‬‬ ‫‪H‬‬ ‫‪J‬‬ ‫‪E‬‬

‫‪6‬‬ ‫‪O‬‬
‫‪I‬‬ ‫‪N‬‬ ‫‪K‬‬
‫‪7‬‬ ‫‪Q‬‬
‫‪M‬‬ ‫‪L‬‬

‫اشاره گرهاي ‪NULL –16=18 2 × 17‬‬


‫اگر ‪ n‬رأس داشته باشيم در روش فرزند چپ ـ هم نياي راست كالً ‪ n+1‬اشاره گر پوچ خواهيم داشت‬

‫تمرين ‪ :‬چگونه مي توان از گرافي كه به صورت فرزند چپ ـ هم نياي راست نمايش داده شده است به گراف‬
‫اصلي رسيد ؟‬

‫درخت هاي دودويي( ‪)Binary Tree‬‬


‫در روش فرزند چپ ـ هم نياي راست به درخ‪V‬تي رس‪V‬يديم ك‪V‬ه در آن ه‪V‬ر گ‪V‬ره ح‪V‬داكثر ‪ 2‬فرزن‪V‬د دارد ‪ ،‬چ‪V‬نين‬
‫درخت هايي درخت دو دويي نام دارند ‪ ،‬اين درخت ها در علوم مختلف بسيار پركار بودند‪ V‬در واقع هر جا از‬
‫منطق و ارزشي استفاده ك‪VV‬نيم مي ت‪VV‬وان درخت دو دويي را ب‪VV‬ه ك‪VV‬ار ب‪VV‬رد ‪ .‬در ك‪VV‬امپيوتر ن‪VV‬يز چ‪V‬ون ك‪VV‬ه مبن‪VV‬اي‬
‫محاسبات مبناي ‪ 2‬است اين درخت ها كاربرد دارند ‪.‬‬
‫نمايش درخت هاي دودويي‬
‫از آنجايي كه درخت هاي دو دويي نسبت به درخت هاي عادي منظم تر هستند ‪ ،‬مي توانيم آن ها را در آراي‪V‬ه‬
‫نيز نمايش دهيم‪ ،‬ابتدا بايد بدانيم هر درخت دودويي به چند خانه آرايه نياز دارد ‪.‬‬
‫تعريف درخت دودويي پر يا كامل درخت دو دويي را كه در آن هر گره اي (به جز برگه‪VV‬ا) دو فرزن‪VV‬د داش‪VV‬ته‬
‫باشد درخت دو دويي پر مي ناميم‪.‬‬

‫مثالً درخت زير يك درخت دودويي پر به عمق ‪ 4‬است ‪.‬‬

‫‪1‬‬
‫‪2‬‬
‫‪3‬‬
‫‪4‬‬

‫كامل يا پر‬

‫درخت هاي پر داراي خواص زير هستند ‪:‬‬


‫خاصيت اول ‪ :‬تعداد‪ V‬گره ها در سطح ‪ K‬ام برابر ‪ 2K-1‬است ‪.‬‬
‫‪ .2‬اگر عمق درخت ‪ d‬باشد تعداد‪ V‬كل گره هاي درخت دودويي پر ‪ 2d -1‬است‪.‬‬

‫‪2  2 1  2 2   2 d 1  2 d  1‬‬

‫‪38‬‬
‫با استفاده از اين خواص براي نمايش يك درخت دودويي به عمق ‪ d‬از آرايه اي به طول ‪ 2d -1‬اس‪VV‬تفاده مي‬
‫كنيم ‪ ،‬ريشه را در خانه اول آرايه قرار مي دهيم و به صورت بازگش‪VV‬تي فرزن‪VV‬د چپ خان‪VV‬ه ‪i‬ام را در خان‪VV‬ه (‬
‫‪ )2i‬قرار مي دهيم و فرزند راست خانه ‪i‬ام را در خانه ‪ 2i+1‬قرار مي دهيم ‪.‬‬

‫درخت دودويي زير را در يك آرايه نمايش مي دهيم ‪.‬‬

‫‪ d = 5  2 d -1=31‬نياز است‪31 .‬آرايه اي به طول‬


‫‪A‬‬

‫‪B‬‬
‫‪C‬‬
‫‪D‬‬
‫‪F‬‬ ‫‪E‬‬
‫‪G‬‬
‫‪I‬‬
‫‪J‬‬ ‫‪H‬‬

‫‪i‬‬
‫[ است ‪.‬‬ ‫نكته پدر گره خانه ‪ i‬ام در خانه ]‬
‫‪2‬‬
‫‪1‬‬ ‫‪2‬‬ ‫‪3‬‬ ‫‪4‬‬ ‫‪5‬‬ ‫‪6‬‬ ‫‪7‬‬ ‫‪8‬‬ ‫‪9 10 `1‬‬ ‫‪`2 `3 `4 `5 `6 `7 `8 `9‬‬
‫‪A‬‬ ‫‪B C‬‬ ‫‪D E‬‬ ‫‪F‬‬ ‫‪G‬‬ ‫‪H‬‬
‫‪`20 ``1 ``2 ``3 ``4 ``5 ``6 ``7 ``8 ``9 ``30 ```1‬‬
‫‪I‬‬ ‫‪J‬‬

‫پيمايش درخت هاي دودويي‬


‫درخت‌هاي دودويي را به ‪ 2‬صورت عمده مي توان پيمايش كرد يكي پيم‪VV‬ايش س‪V‬طحي و ديگ‪V‬ري پيم‪V‬ايش‬
‫عمقي ‪ ،‬در اين قسمت پيمايش هاي عمقي را در نظر مي گ‪VV‬يريم ‪ ،‬ش‪VV‬كل كلي ه‪V‬ر درخت دودويي ب‪VV‬ه ص‪V‬ورت‬
‫زير مي باشد ‪.‬‬
‫‪N‬‬

‫‪L‬‬ ‫‪R‬‬

‫اين سه گره را به ‪( !3‬سه فاكتوريل) حالت پيمايش (بازيابي) كرد ‪ ،‬اما قرارداد مي كنيم كه فرزند چپ‬
‫در اين صورت مقدم بر فرزند راست باشد ‪ ،‬دراين صورت ‪ 3‬حالت پيم‪VV‬ايش خ‪VV‬واهيم داش‪VV‬ت ‪ :‬در ح‪VV‬الت اول‬
‫ابتدا گره بازيابي مي شود سپس فرزندان چپ و راست( ‪ )NLR‬اين حالت پيمايش را ح‪VV‬الت پيش ترتي‪VV‬بي ((‬
‫‪ Preorder‬مي ناميم ‪.‬‬
‫اگر گره ‪ n‬در ميان فرزندان چپ و راست پيمايش شود( ‪ )LNR‬آن گاه پيم‪VV‬ايش مي‪VV‬ان ترتي‪VV‬بي( ‪)In order‬‬
‫(‬ ‫خواهيم داشت و در صورتي كه گره ‪ n‬پس از فرزندانش بازيابي ش‪V‬ود( ‪ )LRN‬پيم‪V‬ايش پس ترتي‪V‬بي‬
‫‪ )order Post‬خ‪VV‬واهيم داش‪VV‬ت ‪ ،‬در اين ح‪VV‬الت هيچ گ‪VV‬ره اي بازي‪VV‬ابي نمي ش‪VV‬ود مگ‪VV‬ر آنك‪VV‬ه تم‪VV‬ام فرزن‪VV‬دانش‬
‫بازيابي شده باشند به همين جهت ريشه آخرين گره اي است كه بازيابي مي شود ‪.‬‬
‫(در بعضي كتابها به جاي ‪ N ، D‬مي باشد)‬

‫مثال ‪ :‬پيمايش درخت زير را بنويسيد‪. V‬‬


‫‪A‬‬

‫‪B‬‬
‫‪C‬‬

‫‪39‬‬
‫‪D‬‬
‫‪F‬‬ ‫‪E‬‬
‫‪G‬‬
‫‪I‬‬
‫‪J‬‬ ‫‪H‬‬

‫ابتدافرزندان چپ بازيابي مي شوند و بعد فرزندان راست ‪.‬‬

‫پيمايش هاي عمقي‬


‫‪NLR: A,B,D,F,I,G,J,C,E,H‬‬

‫‪LNR: B,I,F,D,G,J,A,E,H,C‬‬

‫‪LRN: I,F,J,G,D,B,H,E,C,A‬‬
‫كاربرد درخت هاي دودويي‬
‫همانطور كه گفت‪V‬ه ش‪V‬د درخت ه‪V‬اي دودويي بس‪V‬يار پركاربردن‪V‬د‪ ، V‬يكي از كاربرده‪V‬اي آنه‪V‬ا در تب‪V‬ديل عب‪V‬ارات‬
‫رياضي است ‪ ،‬اغلب اعمال رياضي ‪ ،‬اعمال دوتايي هستند يعني ي‪VV‬ك عملگ‪VV‬ر روي دو عملون‪VV‬د اث‪VV‬ر مي كن‪VV‬د ‪،‬‬
‫يكي عملوند چپ و ديگري عملوند راست ‪ .‬بنابراين متناظر هر عبارت رياضي مي توانيم يك درخت دودويي‬
‫داشته باشيم ‪ .‬مثالً درخت متناظر با عبارت ‪ A+B‬به صورت زير نمايش داده مي شود ‪:‬‬

‫‪+‬‬

‫‪A‬‬ ‫‪B‬‬

‫)) دورعملگر خط مي كشيم))‬


‫عملگر را در ريشه قرار مي دهيم و عملوندهاي چپ و راست را جاي فرزندان قرار مي دهيم ‪ ،‬عبارات‬
‫پيچيده تر را نيز مي توان متناظر با يك درخت دودويي گرفت ‪ ،‬به اين نكته اساسي توجه داريم ك‪VV‬ه ه‪V‬ر عملي‬
‫كه اولويت باالتري داشته باشد سطح باالتري دارد ‪ ،‬يعني از ريشه دورتر است و عملگر ب‪VV‬ا كم‪VV‬ترين اول‪VV‬ويت‬
‫در ريشه قرار مي گيرد ‪.‬‬
‫مث‪pp‬ال ‪ :‬درخت متن‪VV‬اظر ب‪VV‬ا عب‪VV‬ارت زي‪VV‬ر را رس‪VV‬م كني‪VV‬د‪.‬‬
‫‪T2‬‬
‫‪A+B*(C+D/E)/F‬‬
‫‪T3‬‬ ‫‪T1‬‬
‫‪T4‬‬
‫‪T5‬‬

‫پيمايش ‪ Inorder‬يک درخت دودوئي‬


‫)‪void inorder (tree_pointer ptr‬‬
‫‪/* inorder tree traversal */‬‬
‫{‬
‫{ )‪if (ptr‬‬
‫; )‪inorder (ptr -> left _child‬‬
‫; )‪printf ("%d" ,ptr -> data‬‬
‫; )‪inorder (ptr -> right_child‬‬

‫‪40‬‬
}
}

‫ يک درخت دودوئي‬preorder ‫پيمايش‬


void preorder (tree_pointer ptr)
/* preorder tree traversal */
{
if (ptr) {
printf ("%d" , ptr -> data) ;
preorder (ptr -> left_child) ;
preorder (ptr -> right_child) ;
}
}
‫ غير بازگشتي‬inorder ‫پيمايش‬
void iter_inorder (tree_pointer node)
{
int top = -1 ; /* initialize stack */
tree_pointer stack [MAX_STACK_SIZE] ;
for ( ; ; ) {
for ( ; node ; node = node -> left_child)
add (&top , node) ; /* add to stack /*
node = delete (&top) ; /* delete from stack */
if (!node) breake ; /* empty stack */
printf ("%d" ,node -> data) ;
node = node -> right_child ;
}
}
‫ يک درخت دودوئي‬postorder ‫پيمايش‬
void postorder (tree_pointer ptr)
/* postorder tree traversal */
{
if (ptr) {
postorder (ptr -> left_child) ;
postorder (ptr -> right_child) ;
printf ("%d" , ptr -> ->data) ;
}
}
. ‫ فرزند راست است‬، ‫)است و در اعمال يكتايي فرزندش‬Not A (‫) و‬A-( ‫اعمال يكتايي‬
-A A- , not A
not

41
‫روشهاي مرتب سازي ‪:‬‬

‫كاربرد درخت هاي دودويي در مرتب سازي‬


‫يكي از روش هاي مرتب سازي روش مرتب س‪V‬ازي درخت جس‪V‬تجوي دودويي (‪ )BST‬مي باش‪V‬د اين‬
‫روش جزو روشهاي پويا ( ‪ )Dynamic‬است يعني حتي اگر تعداد داده هايي كه مي خواهيم مرتب كنيم از‬
‫ابتدا مشخص نباشد باز هم مي توانيم از اين روش اس‪VV‬تفاده ك‪VV‬نيم ‪ ،‬در اين روش اولين داده را در ريش‪VV‬ه ق‪VV‬رار‬
‫مي دهيم سپس به صورت بازگشتي در مورد داده هاي ديگ‪VV‬ر اگ‪VV‬ر از مق‪VV‬دار گ‪VV‬ره ج‪VV‬اري كوچك‪VV‬تر بودن‪VV‬د ب‪VV‬ه‬
‫سمت چپ گره مي رويم و اگر مقدار داده جديد بزرگتر از گره جاري بود به س‪VV‬مت راس‪VV‬ت آن مي رويم ‪ ،‬در‬
‫نهايت يك درخت دودويي ايجاد مي شود كه با پيمايش ‪ Inorder‬آن داده ها ب‪VV‬ه ص‪VV‬ورت ص‪VV‬عودي م‪VV‬رتب مي‬
‫شوند ‪.‬‬
‫مثال ‪ :‬داده هاي زير را به روش مرتب سازي ‪ BST‬مرتب كنيد‪. V‬‬
‫‪37,24,62,18,25,16,58,39,25‬‬
‫‪37‬‬

‫‪2‬‬
‫‪4‬‬ ‫‪62‬‬

‫‪1‬‬ ‫‪2‬‬
‫‪8‬‬ ‫‪5‬‬ ‫‪5‬‬
‫‪8‬‬
‫‪1‬‬ ‫‪2‬‬
‫‪6‬‬ ‫‪5‬‬ ‫‪39‬‬

‫‪Inorder [ LNR] : 16 , 18 , 24 , 25 , 25 , 37 , 39 , 58 , 62‬‬

‫درج عنصري به داخل درخت دودوئي‬


‫)‪void insert_node (tree_pointer *node ,int num‬‬
‫‪/* if num is in the tree pointed at by node do nothing ; otherwise add a new‬‬
‫‪node with data = num */‬‬
‫{‬
‫; )‪tree_pointer ptr ,temp = modified_search (*node , num‬‬
‫{ ))‪if (temp | | ! (*node‬‬
‫‪/* num is not in the tree */‬‬
‫; ))‪ptr = (tree_pointer) malloc (sizeof (node‬‬
‫{ ))‪if (IS_FULL(ptr‬‬
‫; )"‪fprintf (stderr ,"the memory is full \n‬‬
‫; )‪exit (l‬‬
‫}‬
‫; ‪ptr -> data = num‬‬
‫; ‪ptr -> left_child = ptr -> right_child = NULL‬‬
‫‪if (*node) /* insert as child of temp */‬‬
‫; ‪if (num < temp -> data) temp -> left_child = ptr‬‬
‫; ‪else temp -> right_child = ptr‬‬
‫; ‪else *node = ptr‬‬
‫}‬
‫}‬
‫زمان اجراي مرتب سازي ‪ BST ( n log n2 ) O‬مي باشد ‪.‬‬

‫‪42‬‬
‫‪1‬‬
‫نكته ‪ :‬زمان اجراي مرتب سازي جبابي ) ‪O ( n 2‬‬
‫‪2‬‬
‫‪ n = 2 20‬اگر ‪ :‬مرتب سازي حبابي‬ ‫‪= 500×9 10‬زمان اجرا‬
‫‪ n = 2 20‬اگر ‪ :‬مرتب سازي كومه اي‬ ‫‪= O(220 × )20‬زمان اجرا‬

‫براي درج عنصر در يک درخت جستجوي دودويي به راحتي مي توانيم جاي گره جديد را تعيين کنيم ‪ .‬براي‬
‫اين منظور از ريشه شروع مي کنيم و اگر گره جديد داراي مقداري از ريشه کمتر بود ‪ ،‬در سمت چپ و در‬
‫غير اين صورت به سمت راست مي رويم ‪ .‬اين کار را به شکل بازگشتي تکرار مي کنيم تا محل گره جديد‬
‫مشخص شود ‪.‬‬
‫براي حذف يک گره از درخت ‪ ، BST‬اگر آن گره برگ باشد ( فرزند نداشته باشد ) کافيست اشاره گر والد‬
‫آن را برابر ‪ Null‬قرار دهيم ‪ .‬اما اگر گره اي که مي خواهيم حذف شود ‪ ،‬داراي فرزند باشد دو حالت پيش‬
‫رو داريم ‪ .‬اگر گره اي که مي خواهيم حذف کنيم فقط يک فرزند داشته باشد عمالً فرزند را به جاي والد مي‬
‫نشانيم ‪ ،‬اما اگر گره اي که مي خواهد حذف شود ‪ ،‬دو فرزند داشته باشد مي توانيم بزرگترين عنصر‬
‫( بزرگترين در‬ ‫زيردرخت چپ آن يا کوچکترين عنصر زيردرخت راست آن را جايگزين کنيم ‪.‬‬
‫سمت چپ – کوچکترين در سمت راست )‬
‫مثال ‪ :‬در درخت ‪ BST‬زير مثالً اگر بخواهيم ‪ 72‬را حذف کنيم مي توانيم ‪( 44‬بزرگترين در زير درخت‬
‫سمت چپ ) يا ‪ ( 80‬کوچکترين در زيردرخت سمت راست ) را به جاي ‪ 72‬قرار دهيم ‪.‬‬

‫‪32‬‬

‫‪25‬‬ ‫‪72‬‬

‫‪13‬‬ ‫‪29‬‬ ‫‪39‬‬ ‫‪80‬‬

‫‪26‬‬ ‫‪31 37‬‬ ‫‪44‬‬

‫تذکر مهم ‪ :‬هنگام حذف گره از ‪ BST‬توجه داريم که اگر گره جايگزين گره حذف شده فرزند داشته باشد بايد‬
‫فرزندان گره جايگزين را به والد قبلي گره جايگزين مرتبط کنيم ‪.‬‬

‫مثال ‪ :‬در درخت زير اگر بخواهيم ‪ 72‬را حذف کنيم ‪ 44 ،‬جايگزين آن مي شود و ‪ 41‬فرزند راست وي‬
‫خواهد شد ‪.‬‬
‫‪32‬‬

‫‪25‬‬ ‫‪72‬‬

‫‪13‬‬ ‫‪29‬‬ ‫‪39‬‬ ‫‪80‬‬

‫‪26‬‬ ‫‪31 37‬‬ ‫‪44‬‬

‫‪41‬‬
‫درخت حاصل را در شکل زير مي توانيد مشاهده فرماييد ‪:‬‬
‫‪32‬‬

‫‪25‬‬ ‫‪44‬‬

‫‪13‬‬ ‫‪29‬‬ ‫‪39‬‬ ‫‪80‬‬

‫‪26‬‬ ‫‪31 37‬‬ ‫‪41‬‬

‫مرتب سازي ادغامي (‪)Merge Sort‬‬

‫‪43‬‬
‫اساس كار اين روش ادغام آرايه هاي مرتب در يكديگر است بدين صورت كه در تكرار اول هر دو عدد‬
‫كنار هم را به ترتيب صعودي مرتب مي كنيم تا در واقع آرايه هاي مرتب به طول ‪ 2‬بدست آيد در تك‪VV‬راردوم‬
‫آرايه هاي مرتب به طول ‪ 2‬را كه كنار هم هستند در هم ادغام مي كنيم تا آرايه هاي مرتب به طول ‪ 4‬بدس‪VV‬ت‬
‫آيد‪ ،‬در تكرارسوم آرايه هاي چهارتايي را ادغام مي كنيم ت‪VV‬ا م‪VV‬رتب ‪ 8‬ت‪VV‬ايي بدس‪VV‬ت آي‪VV‬د اين ك‪VV‬ار را ادام‪VV‬ه مي‬
‫دهيم تا كل آرايه مرتب شود ‪.‬‬

‫مثال ‪:‬‬

‫‪41 , 29 , 53 , 16 , 19 , 32 , 17 , 43 , 65 , 14 , 18 , 32 , 19‬‬

‫‪29 , 41 , 16 , 53 , 19 , 32 , 17 , 43 , 14 , 65 , 18 , 32 , 19‬‬

‫‪16 , 29 , 41 , 53 , 17 , 19 , 32 , 43 , 14 , 18, 32 , 65 , 19‬‬

‫‪16 , 17 , 19 , 29 , 32 , 41 , 43 , 53, 14 , 18 , 19 , 32 , 65‬‬

‫‪14 , 16 , 17 , 18 , 19 , 19 , 29 , 32 , 32 , 41 , 43 , 53 , 65‬‬

‫به عنوان تمرين ثابت كنيد‬


‫‪n‬‬
‫‪ O gol‬است‪.‬‬
‫‪n‬‬
‫)‬ ‫‪2‬‬ ‫زمان اجراي مرتب سازي ادغامي (‬

‫مزيت اين روش‬


‫مزيت اين روش نسبت به ساير روش هاي مرتب سازي اين است كه الزم نيست همزمان تمام داده ها در‬
‫حافظه اصلي موجود باشند يعني مي توان با استفاده از حافظه كمكي (مثال ديسك سخت ‪ )hard disk‬قسمت‬
‫هايي را كه مي خواهيم در هم ادغام شود همانجا يا حتي در حافظه اصلي ادغام كنيم‪.‬‬
‫مرتب سازي انتخابي ( ‪: )Selection Sort‬‬
‫در روش مرتب سازي حبابي ‪ ) ) Bubble‬ممکن است در هر تکرار ‪ ،‬تعداد زيادي از عناصر با هم جابجا‬
‫شوند ‪ .‬براي رفع اين مشکل مي توانيم از مرتب سازي انتخابي استفاده کنيم ‪ .‬در هر مرحله انديس‬
‫بزرگترين عنصر مشخص مي شود ‪ ،‬سپس با آخرين عنصر زير آرايه اي که مي خواهيم مرتب‬
‫شود جابجا مي شود ‪.‬‬
‫)‪For ( i = n -1 ; i >0 ; i--‬‬
‫{‬
‫; ] ‪Max = a [ 0‬‬
‫)‪For ( j = 1 ; j <= i ; j++‬‬
‫{‬
‫)‪if ( a [ j] > max‬‬
‫{‬
‫]‪Max = a [ j‬‬
‫; ‪Maxindex = j‬‬
‫}‬
‫}‬
‫; ]‪Temp = a [ i‬‬
‫; ]‪a [ i] = a [ maxindex‬‬
‫; ‪a [ maxindex] = temp‬‬
‫}‬
‫روش مرتب سازي درجي ( ‪: ) Insertion Sort‬‬
‫در اين روش در تکرار ‪ i‬ام يک عنصر جديد در يک آرايه مرتب ‪ ،‬عنصري درج مي شود ‪ .‬پس از‬
‫‪ n-1‬مرحله آرايه ‪n‬عنصري مرتب شده است ‪.‬‬

‫‪44‬‬
‫نکته ‪ :‬اگر ‪ data‬به شکل مرتب شده ذخ‪VV‬يره ش‪VV‬ده باش‪VV‬ند ‪ ،‬م‪VV‬رتب س‪VV‬ازي درجي از دو روش ‪ Selection‬و‬
‫‪ Bubble‬بهتر است ‪.‬‬

‫‪20‬‬ ‫‪30‬‬ ‫‪40‬‬ ‫‪50‬‬ ‫‪60‬‬

‫‪Bubble‬‬ ‫‪10 = 1 + 2 + 3 + 4‬‬


‫‪Selection‬‬ ‫‪10 = 1 + 2 + 3 + 4‬‬
‫‪Insertion‬‬ ‫‪4=1+1+1+1‬‬

‫روش مرتب سازي کومه اي ( ‪: ) Heap Sort‬‬


‫هرگاه در يک درخت کامل دودوديي تا قبل از سطح پاياني درخت کامل باشد و در سطح پاياني برگها از چپ‬
‫به راست در نظر گرفته شده باشند ‪،‬آنگاه يک درخت شبه کامل يا کومه خواهيم داشت ‪.‬‬

‫کومه است‬

‫کومه نيست‬
‫در اينجا دو مفهوم ‪ Max Heap‬و ‪ Min Heap‬مطرح مي باشند که در پايين به آنها اشاره شده است‪.‬‬
‫‪ : Min Heap‬کومه اي را که در آن هيچ گره اي از فرزندانش بزرگتر نباشد را ‪ Min Heap‬مي ناميم ‪.‬‬
‫‪ : Max Heap‬يک درخت دودويي شبه کامل است که در آن هيچ گره اي از فرزندانش کوچکتر نباشد ‪.‬‬
‫‪3‬‬
‫‪0‬‬

‫‪2‬‬ ‫‪1‬‬
‫‪5‬‬ ‫‪4‬‬

‫‪2‬‬ ‫‪1‬‬
‫‪3‬‬ ‫‪9‬‬
‫درج عنصر در ‪ : Max Heap‬اگر بخواهيم يک عنصر جديد را به يک ‪ Max Heap‬اضافه کنيم ‪ ،‬اوالً آنرا‬
‫به موقعيت مجاز اضافه مي کنيم تا کومه بودن از دست نرود ‪.‬‬
‫مثالً اگر بخواهيم عدد ‪ 22‬را به ‪ Max Heap‬باال اضافه کنيم به صورت زير عمل مي کنيم ‪:‬‬
‫‪3‬‬
‫‪0‬‬

‫‪2‬‬ ‫‪1‬‬
‫‪5‬‬ ‫‪4‬‬

‫‪2‬‬
‫سپس با ريشه خود يعني‪ 14 19‬جابجا مي ‪23‬شود ‪.‬‬
‫‪2‬‬ ‫ابتدا ‪ 22‬از سمت چپ ‪ ،‬به پايين ترين سطح اضافه شده و‬
‫‪3‬‬
‫‪0‬‬

‫‪45‬‬
‫‪2‬‬ ‫‪2‬‬
‫‪5‬‬ ‫‪2‬‬

‫‪2‬‬ ‫‪1‬‬ ‫‪1‬‬


‫‪3‬‬ ‫‪9‬‬ ‫‪4‬‬
‫تذکر ‪ :‬در مثال قبل اگر مي خواستيم عدد ‪ 32‬را اضافه ک‪VV‬نيم ‪ ،‬متوالي‪V‬ا ً ب‪VV‬ا مق‪VV‬ادير وال‪VV‬د تع‪VV‬ويض مي ش‪VV‬د و در‬
‫نهايت در ريشه قرار مي گرفت ‪.‬‬
‫حذف عنصر از ‪ : Max Heap‬همواره عمل حذف از ريشه انج‪VV‬ام مي ش‪VV‬ود ‪ .‬پس از آنک‪VV‬ه عنص‪VV‬ر ريش‪VV‬ه را‬
‫برداشتيم ‪ ،‬آخرين گره ‪ ( Max Heap‬سمت راست ترين گره سطح آخر ) جايگزين ريشه مي شود ‪ .‬س‪VV‬پس‬
‫به صورت بازگشتي هر کدام از فرزندان که از والد بزرگتر بودند جايگزين والد مي ش‪VV‬وند ‪ .‬اين عم‪VV‬ل آنق‪VV‬در‬
‫ادامه مي يابد تا شرط ‪ Max Heap‬برقرار شود ‪ .‬توجه به اين نکته ضروري است که هميشه عدد از ريشه‬
‫بايستي حذف کنيم و حذف به غير از ريشه مجاز نمي باشد ‪.‬‬
‫مثال ‪ :‬در ‪ Max Heap‬باال يک عنصر را حذف نماييد ‪.‬‬
‫مراحل خذف را مي توانيد در پايين مشاهده فرماييد ‪:‬‬
‫‪1‬‬
‫‪4‬‬

‫‪2‬‬ ‫‪2‬‬
‫‪5‬‬ ‫‪2‬‬

‫‪2‬‬ ‫‪1‬‬
‫‪3‬‬ ‫‪9‬‬

‫‪2‬‬
‫‪5‬‬

‫‪1‬‬ ‫‪2‬‬
‫‪4‬‬ ‫‪2‬‬

‫‪2‬‬ ‫‪1‬‬
‫‪3‬‬ ‫‪9‬‬ ‫‪2‬‬
‫‪5‬‬

‫‪2‬‬ ‫‪2‬‬
‫‪3‬‬ ‫‪2‬‬

‫‪1‬‬ ‫‪1‬‬
‫‪4‬‬ ‫‪9‬‬
‫از آنج‪VV‬ا ک‪VV‬ه در ‪ Max Heap‬هم‪VV‬واره بزرگ‪VV‬ترين عنص‪VV‬ر در ريش‪VV‬ه ق‪VV‬رار دارد ‪ ،‬اگ‪VV‬ر تم‪VV‬ام عناص‪VV‬ر ‪Max‬‬
‫‪ Heap‬را متواليا ً از ريشه خارج کنيم ‪ ،‬در نهايت اعداد به صورت مرتب شده باقي مي مانند ‪.‬‬
‫‪7‬‬ ‫‪8‬‬ ‫‪8‬‬ ‫‪8‬‬ ‫‪8‬‬
‫‪9‬‬ ‫‪4‬‬ ‫اي ‪ Sort‬کنيد ‪.‬‬ ‫دهيد سپس به صورت کومه ‪4‬‬ ‫‪4‬‬
‫مثال ‪ :‬کومه اعداد زير را تشکيل‬
‫‪4‬‬
‫‪45 – 32 7– 15 - 25 - 84 - 79‬‬
‫‪8‬‬ ‫‪7‬‬ ‫‪2‬‬ ‫‪7‬‬ ‫‪2‬‬ ‫‪7‬‬ ‫‪2‬‬
‫‪4‬‬ ‫‪9‬‬ ‫‪9‬‬ ‫‪5‬‬ ‫‪9‬‬ ‫‪9‬‬ ‫‪5‬‬
‫‪5‬‬
‫‪1‬‬ ‫‪1‬‬ ‫‪3‬‬
‫‪5‬‬ ‫‪5‬‬ ‫‪2‬‬
‫‪8‬‬ ‫‪8‬‬
‫‪4‬‬ ‫‪4‬‬
‫‪7‬‬ ‫‪2‬‬ ‫‪7‬‬ ‫‪4‬‬
‫‪9‬‬ ‫‪5‬‬ ‫‪9‬‬ ‫‪5‬‬
‫‪1‬‬ ‫‪3‬‬ ‫‪4‬‬ ‫‪1‬‬ ‫‪3‬‬ ‫‪2‬‬
‫‪5‬‬ ‫‪2‬‬ ‫‪5‬‬ ‫‪5‬‬ ‫‪2‬‬ ‫‪5‬‬

‫‪2‬حذف‬ ‫‪7‬‬ ‫‪2‬‬ ‫حذف ‪79‬‬


‫‪5‬‬ ‫‪9‬‬ ‫‪5‬‬ ‫‪84‬‬
‫‪7‬‬ ‫‪4‬‬ ‫‪3‬‬ ‫‪4‬‬ ‫‪3‬‬ ‫‪4‬‬
‫‪9‬‬ ‫‪5‬‬ ‫‪2‬‬ ‫‪5‬‬ ‫‪2‬‬ ‫‪5‬‬
‫‪8‬‬ ‫‪2‬‬ ‫‪8‬‬ ‫‪1‬‬ ‫‪7‬‬ ‫‪8‬‬
‫‪1‬‬ ‫‪3‬‬ ‫‪4‬‬ ‫‪1‬‬ ‫‪5‬‬ ‫‪4‬‬ ‫‪5‬‬ ‫‪9‬‬ ‫‪4‬‬
‫‪5‬‬ ‫‪2‬‬ ‫‪5‬‬

‫‪4‬‬ ‫‪1‬‬ ‫‪3‬‬


‫‪5‬‬ ‫‪5‬‬ ‫‪2‬‬

‫‪46‬‬
‫حذف ‪45‬‬ ‫حذف ‪32‬‬
‫‪3‬‬ ‫‪2‬‬ ‫‪3‬‬ ‫‪2‬‬ ‫‪1‬‬ ‫‪2‬‬
‫‪2‬‬ ‫‪7‬‬ ‫‪8‬‬ ‫‪5‬‬ ‫‪4‬‬ ‫‪2‬‬ ‫‪7‬‬ ‫‪5‬‬ ‫‪4‬‬ ‫‪5‬‬ ‫‪5‬‬
‫‪8‬‬ ‫‪7‬‬ ‫‪8‬‬
‫‪1‬‬ ‫‪9‬‬ ‫‪4‬‬ ‫‪5‬‬ ‫‪9‬‬ ‫‪4‬‬ ‫‪5‬‬ ‫‪9‬‬ ‫‪4‬‬
‫‪5‬‬

‫‪ 2‬حذ‬ ‫‪1‬‬
‫‪5‬‬ ‫‪5‬‬ ‫ف ‪25‬‬
‫‪1‬‬ ‫‪3‬‬ ‫‪2‬‬ ‫‪3‬‬
‫‪5‬‬ ‫‪2‬‬ ‫‪5‬‬ ‫‪2‬‬
‫‪7‬‬ ‫‪8‬‬ ‫‪4‬‬ ‫‪7‬‬ ‫‪8‬‬
‫‪4‬‬ ‫‪9‬‬ ‫‪4‬‬ ‫‪5‬‬ ‫‪9‬‬ ‫‪4‬‬
‫‪5‬‬

‫جواب ‪84 – 79 – 45 - 32 – 25 - 15 :‬‬

‫روش مرتب سازي سريع (‪)Quick Sort‬‬


‫در اين روش يك عنصر از آرايه را به عنوان عنصر لوال يا پاشنه گردي ( ‪ )Pivot‬در نظر مي گيريم‬
‫و مكان واقعي آن را در آرايه مشخص مي كنيم بدين‪ V‬صورت كه با متغيري به اس‪VV‬م ‪i‬از ابت‪VV‬داي آراي‪VV‬ه ش‪VV‬روع‬
‫مي كنيم و پيش مي رويم تا عنصر بزرگتر از ‪ pivot‬پيدا كنيم به همين ترتيب از انتهاي آرايه با يك متغير به‬
‫نام ‪ j‬خانه خانه عقب برمي گرديم تا عنصر كوچكتر از ‪ pivot‬پيدا كنيم ‪ .‬اگر ‪ i‬از ‪ j‬كوچكتر باشد ج‪VV‬اي خان‪VV‬ه‬
‫هاي ‪i‬ام و ‪ j‬ام را عوض مي كنيم( ‪ ) i < j‬اين كار را ادامه مي دهيم تا ‪ i‬از ‪ j‬بزرگتر شود ‪ . ) ) i > j‬در اين‬
‫صورت ‪ i‬از ‪ j‬رد شده و بايستي حتم‪V‬ا ً ج‪V‬اي ‪ Pivot‬را ب‪V‬ا خان‪V‬ه ‪ j‬ام ع‪V‬وض مي ك‪V‬نيم ‪ .‬پس از آنك‪V‬ه مك‪V‬ان‬
‫واقعي ‪ pivot‬مشخص شد به صورت بازگشتي ابتدا به سراغ زير آرايه سمت چپ ‪ pivot‬مي رويم و س‪VV‬پس‬
‫زير آرايه سمت راست ‪ . pivot‬عمليات را آنقدر ادامه مي دهيم تا كل آرايه مرتب شود ‪ .‬در اينج‪VV‬ا ‪ pivot‬را‬
‫اولين خانه آرايه اي كه مي خواهيم مرتب شود در نظر مي گيريم ‪.‬‬
‫‪ pivot‬جابه جا مي شود)‬ ‫( ‪ i‬از ‪ j‬گذشته با‬
‫‪i‬‬ ‫‪j‬‬ ‫‪i‬‬ ‫‪j‬‬
‫‪37‬‬ ‫‪24 62 18 25 16 58 39 22‬‬ ‫‪m ntovip‬‬
‫‪16‬‬ ‫‪25‬‬ ‫‪37‬‬ ‫‪5‬‬ ‫‪1 9 73‬‬
‫‪62‬‬
‫‪j‬‬ ‫‪I‬‬
‫‪16‬‬ ‫‪24 25 18 25 37 58 39 62‬‬ ‫‪m ntovip‬‬
‫‪16‬‬ ‫‪1 5 61‬‬
‫‪i j i j‬‬
‫‪16 24 25 18 25 37 58 39 62‬‬ ‫‪m ntovip‬‬
‫‪18 18 25‬‬ ‫‪2 5 42‬‬
‫‪24‬‬
‫‪j‬‬ ‫‪j i‬‬ ‫‪i‬‬
‫‪16 18 24 25 25 37 58 39 62‬‬ ‫‪m ntovip‬‬
‫‪25‬‬ ‫‪4 5 52‬‬
‫‪j I‬‬

‫‪47‬‬
‫‪16‬‬ ‫‪18‬‬ ‫‪24‬‬ ‫‪25‬‬ ‫‪25‬‬ ‫‪37‬‬ ‫‪58‬‬ ‫‪39‬‬ ‫‪62‬‬ ‫‪m‬‬ ‫‪ntovip‬‬
‫‪39‬‬ ‫‪58‬‬ ‫‪7‬‬ ‫‪9 85‬‬

‫مثال ‪:‬‬
‫‪25 , 16 , 19 , 32 , 14 , 27 , 15‬‬

‫پروژه‬

‫هدف پروژه‪:‬‬
‫برنامه اي بنويسيد‪ V‬که يک عبارت ‪ infix‬شامل عملگرهاي زير که در آن هر عملوندي فقط يک ک‪VV‬اراکتر از‬
‫حروف انگليسي مي باشد و حداکثر تا ‪ 3‬سطح پرانتز تو در ت‪V‬و از ورودي بگ‪V‬يرد و آن را ب‪V‬ه ‪ Prefix‬تب‪V‬ديل‬
‫کند ‪.‬‬
‫براي جمع‬ ‫**‬ ‫توان‬
‫‪+‬‬
‫براي تفريق‬ ‫پرانتز بسته (‬
‫‪-‬‬
‫براي ضرب‬ ‫پرانتز باز )‬
‫*‬
‫براي تقسيم‬ ‫(‪ )~ =shift + 1‬منفي يكتايي ~‬
‫‪/‬‬

‫‪48‬‬

You might also like