83
1

Algorithms Data Structures 1

Embed Size (px)

Citation preview

Page 1: Algorithms Data Structures 1

–1–

Page 2: Algorithms Data Structures 1

قسم الخوارزميات Recursive Algorithms............... 2 -الخوارزميات العودية .1 Backtracking Algorithms ....... 20 -الخوارزميات التراجعية .2 Complexity ........................................ 33 -التعقيد الزمني .3

قسم بنى المعطيات

39 ................................................... بنى المعطيات الخطية .1 Linked Lists ..................... 39 -القوائم المترابطة .1.1 Stack ......................................... 48 - المكدسات .1.2 Queue ........................................... 54 -األرتال .1.3

60................................................ ية بنى معطيات غير خط .2 Trees .......................................... 60 -األشجار .2.1

Binary Trees ........... 60 -األشجار الثنائية .2.1.1 Generalized Trees ..74 - األشجار المعممة .2.1.2

Graph................................... ..........77 -البيان .2.2

Page 3: Algorithms Data Structures 1

–1–الخوارزميات و بنى المعطيات

1 آلية الهندسة المعلوماتية - جامعة البعث

Recursive Algorithms - خوارزميات العودية ال

أي ( و بالتالي يتم استدعاء هذا التابع بشكل مكرر ). recursive call( أنه عودي عندما يستدعي نفسه ) إجراء / تابع( جزئي برنامج عن نقول

) .يتم تنفيذ نفس التعليمات بشكل مكرر ...خاصة في مسائل الذآاء الصنعي و مسائل الترتيب , هوم العودية بدًال من حلقات تكراريةمن المفيد في بعض المسائل أن نستخدم مف

.نالحظ أن تكرار االستدعاء العودي ال نهائي لذلك يجب بالضرورة وضع شرط توقف إلنهاء التكرار :فائدة الخوارزميات العودية

و من ثم تعود خطوة . الة إلى حاالت أبسط على التتالي حتى أن تصل إلى حالة بدائية عندما نتعامل مع مسائل معقدة تقوم العودية بتقسيم هذه الح .خطوة و تعوض القيم الناتجة إلى أن تصل إلى الحالة األصلية فنحصل على الناتج النهائي

:السلبياتر تابع جديد يتم حجز متحوالته المحلية و ألن آل استدعاء ُيعتب( االستدعاءات العودية تسبب ضياعًا في الوقت و تستهلك ذاآرة إضافية -1

) .Stack Overflow= مما يؤدي في األخير إلى الطفحان , وسطاءه من جديد في المكدس ...Cobol , Fortran, لغة اآللة : ال تقبل بعض اللغات البرمجية التعريف العودي للتوابع و منها مثًال -2

.منتهيًا و صغيرًا ) أي عدد تكرار االستدعاءات العودية لنفس التابع ( يجب أن يكون عمق العودية :نتيجة

. أحيانًا فإن اللجوء إلى العودية ليس هو الحل األمثل بل ُيفضل عليه استخدام الخوارزميات التكرارية :مالحظة

:أنواع الخوارزميات العودية :حيث يبين الجدول التالي الفرق بينهما , مباشرة يمكن أن تكون التوابع ذات عودية مباشرة أو ذات عودية غير

التوابع ذات العودية المباشرة التوابع ذات العودية غير المباشرة

هي توابع تحوي استدعاًء لتوابع أخرى و التي بدورها تستدعي إذا آان لدينا التابع : مثال . التابع األب

:مثال . هي توابع تحوي استدعاًء صريحًا لنفسها

void B(void) { ………. A( ); ………. } int A(void) { ………. B( ) ; // indirect recursive call ………. }

int A(void) { ………. A( ); // direct recursive call ………. }

: أمثلة لبرامج عودية

: Fact –حساب العاملي لعدد

!)1()2(.......12: من المعروف أن قانون العاملي ُيحسب آالتالي ⋅⋅⋅−⋅−⋅= nnnn !)1!(: و لكن يمكن آتابته بشكل آخر −⋅= nnn

)!2()1( −⋅− nn )!3()2( −⋅− nn

...... ........ )!0(1⋅

علمًا أن الصفر , يتناقص في آل مرة حتى أن يصل إلى الصفر وnإذًا تتكرر عملية حساب العاملي لعدد ما و حيث أن هذا العدد بدأ من القيمة نصل إلى لذلك يمكن هنا تطبيق مفهوم العودية ألننا نكرر عمليات حساب العاملي ألعداد متناقصة حتى أن. أصغر قيمة مقبولة لحساب العاملي لها

.الحالة البدائية ) :تكرارية و عودية ( لنكتب تابع حساب العملي لعدد بطرقتين

Page 4: Algorithms Data Structures 1

–1–الخوارزميات و بنى المعطيات

2 آلية الهندسة المعلوماتية - جامعة البعث

حساب العاملي لعدد تكراريًا حساب العاملي لعدد عوديًا

long fact(int n) { if ((n==1)||(n==0)) return 1; else return n*fact(n-1); }

long fact(int n) { long f=1; if ((n==1)||(n==0)) return 1; else { for (int i=1;i<=n;i++) f*=i; return f; } }

: Fibonacci - ما حساب قيمة متتالية فيبوناتشي عند عدد

Fn = Fn-1 + Fn-2 ; n ≤ (F0 = 0 , F1 = 1 ) 2 : إن الشكل العام لمتتالية فيبوناتشي هو

:و بالتالي لدينا مثًال

هذا يعني أنه لدينا تكرار , ى القيم المسبقة بينما من أجل أي عدد آخر ال يمكن حساب القيمة إال باالعتماد عل ) 1 و 0( إذًا لدينا حالتين بدائيتين ) .1 و 0أي ( حساب تابع فيبوناتشي و لكن في آل مرة ألعداد أصغر حتى أن نصل إلى أبسط قيم ممكنة

:و يكتب التابع العودي آما يلي int fib(int n) { if (n==0) return 0; else if (n==1) return 1; else return fib(n-1)+ fib(n-2); }

:Towers of Hanoi -مسألة أبراج هانوي :و المطلوب. و لكل قرص ثقب بحيث يمكن إدخاله إلى عامود . قرصًا من أقطار مختلفة nليكن لدينا

: لشروط التالية باد مع التقييA علمًا بأنها آانت متوضعة على شكل برج هرمي على عامود Cبناء برج هرمي من هذه األقراص على عامود . ُيسمح في آل خطوة بنقل قرص واحد فقط من عامود آلخر -

.ُيمنع وضع قرص أآبر على قرص أصغر - . مرحليًا Bيمكن استخدام العامود المساعد -

).أي معرفة نقل أي قرص و إلى أي عامود على التتالي , آتنفيذ ُيطلب فقط طباعة مراحل النقل ( : لدينا n = 2فمثًال من أجل

F0 F1 F2 F3 F4 F5 F6 F7 …….. 0 1 1 2 3 5 8 13 ……..

A B C

A B C

A CB

A B C

1:

2:

3:

4:

Page 5: Algorithms Data Structures 1

–1–الخوارزميات و بنى المعطيات

3 آلية الهندسة المعلوماتية - جامعة البعث

#include <iostream.h> الحل: int n; void hanoi(int n, char A, char B, char C); void main() { do { cout<<"Enter n= "; cin>>n; } while (n<=0); hanoi(n,'A','B','C'); } /***************************************************************************************/ void hanoi(int n, char A, char B, char C) { if (n==1) cout<<A<<" --> "<<C<<endl; else { hanoi(n-1,A,C,B); cout<<A<<" --> "<<C<<endl; hanoi(n-1,B,A,C); } }

) :من أجل قرص أو قرصين أو ثالثة أقراص ( حيث يعطي تنفيذ البرنامج السابق النتائج التالية n = 1 n = 2 n = 3

A C A B A C B C

A C A B C B A C B A B C A C

:تحويل التعابير الرياضية من ُمصدرة إلى ُملحقة في األسلوب ) . Postfix(و الكتابة الُملحقة ) Prefix(الكتابة الُمصدرة : بة التعابير الرياضية بال أقواس باستخدام أسلوبين مختلفين نستطيع آتا

بينما في األسلوب الُملحق تتبع آل عملية عواملها . أو متحوالتها مباشرة ) Operands(مباشرة عواملها ) Operator(الُمصدر تسبق آل عملية .اشرة مب

:أمثلة

آما نفترض , لنفترض للتسهيل عدم وجود ثوابت في التعابير الرياضية . رمجيًا هي باستعمال العودية إن أفضل طريقة لتعريف هذين األسلوبين ب

.أيضًا أن جميع العمليات ثنائية :المخطط األولي للخوارزمية العودية التي تقوم بعملية التحويل من تعبير ُمصدر إلى تعبير ُملحق هو آالتالي

).تعبيران متكافئان في هذه الحالة ( فال نقوم بأي شيء , إذا آان التعبير متحوًال وحيدًا • . opأول عملية حسابية في التعبير المصدر و لنسميها تحديد • .post1للتعبير الُمصدر و تحويله إلى ُملحق و تسميته opnd1إيجاد المعامل األول • .post2 و تسميته للتعبير الُمصدر و تحويله إلى ُملحق opnd2إيجاد المعامل الثاني • .بالترتيب و وضع الناتج في التعبير الُملحق opnd1 , opnd2 , opدمج التعابير الجزئية •

( Infix ) نظامي ( Prefix ) مصدر ( Postfix ) ملحق A+B +AB AB+ A+B*C +A*BC ABC*+ A*(B+C) *A+BC ABC+* A*B+C +*ABC AB*C+ A+B*C+D-E*F -++A*BCD*EF ABC*+D+EF*- (A+B)*(C+D-E)*F **+AB-+CDEF AB+CD+E-*F*

Page 6: Algorithms Data Structures 1

–1–الخوارزميات و بنى المعطيات

4 آلية الهندسة المعلوماتية - جامعة البعث

:لنحدد أوًال بنى المعطيات المستخدمة

const int strsize = 80; struct string { char ch[strSize]; int length; };

. تمثل الطول الجاري للسلسلة length هي سلسلة المحارف نفسها و ch أن string حيث نالحظ في تعريف سلسلة المحارف :نحتاج أيضًا إلى تعريف اإلجرائيتين المساعدتين التاليتين

" xy"و " abc" من أجل concatفمثًال االستدعاء . c في السلسة b و a التي تقوم بدمج السلسلتين concat(a,b)اإلجرائية - .”abcxy“ السلسلة cسيضع في

في i اعتبارًا من الموقع S1 من j جميع األحرف التي عددها S2 التي تضع في السلسلة الجزئية S2= substr(S1, i , j)اإلجرائية -S1 ) أي نسخ جزء من السلسلةS1 إلى السلسلة S2 .( فمثًال االستدعاءS2= substr(“Welcome”,4,2) سيضع في S2 السلسلة

“om”. و هي أيضًا بدورها ستعتمد على خوارزمية عودية أخرى اسمها , convertأما بالنسبة للخوارزمية العودية إلجراء عملية التحويل سنسميها

find أي عدد المحارف التي تؤلف المعامل ( و التي تحسب طول معامل. ( :الحل

#include <iostream.h> #include <string.h> // --> strlen(const char *s) #include <ctype.h> // --> isalpha(int c) const int strSize=80; struct string { char ch[strSize]; int length; }; string prefix , postfix; // prefix = input , postfix = output char pr[strSize]; // users first input (we convert it to string) int i; string concat(string s1,string s2); // merge two strings string substr(string s1,int i,int j); // copy part from s1 to a new string string convert(string prefix); // convert prefix into postfix int find(string s,int position); // returns the length of an operand /***************************************************************************************/ void main() { cout<<"Enter a mathimatical sentence in prefix_case :\n"; cin.getline(pr,strSize,'\n'); // reads text with white spaces prefix.length=strlen(pr); for (i=0;i<prefix.length;i++) prefix.ch[i]=pr[i]; postfix=convert(prefix); cout<<"Postfix = "; for (i=0;i<postfix.length;i++) cout<<postfix.ch[i]; } /***************************************************************************************/ string concat(string s1,string s2) { string s3; s3.length = s1.length + s2.length; for (i=0;i<s1.length;i++) s3.ch[i]=s1.ch[i]; int j=s1.length-1; for (i=0;i<s2.length;i++) { j++; s3.ch[j]=s2.ch[i]; } return s3; }

Page 7: Algorithms Data Structures 1

–1–الخوارزميات و بنى المعطيات

5 آلية الهندسة المعلوماتية - جامعة البعث

string substr(string s1,int i,int j) { string s2; s2.length=j; int m=0; for (int k=i;k<i+j;k++) { s2.ch[m]=s1.ch[k]; m++; } return s2; } /***************************************************************************************/ string convert(string prefix) { string postfix; char op; // op = operator string opnd1,opnd2,temp; // opnd1= first operand , opnd2= second operand string post1,post2,opstr; // post1= opnd1 after converting , // post2= opnd2 after converting , opstr= op as string int m,n; // m = length of opnd1 , n = length of opnd2 if (prefix.length==1) if (isalpha(prefix.ch[0])) postfix=prefix; else { cout<<"Illegal prefix string !\n"; postfix.length=0; } else { op=prefix.ch[0]; m=find(prefix,1); n=find(prefix,1+m); if (((op!='+')&&(op!='-')&&(op!='*')&&(op!='/'))|| (m==0)||(n==0)||(m+n+1!=prefix.length)) { cout<<"Illegal prefix string !\n"; postfix.length=0; } else { opnd1=substr(prefix,1,m); opnd2=substr(prefix,1+m,n); post1=convert(opnd1); post2=convert(opnd2); temp=concat(post1,post2); opstr.length=1; opstr.ch[0]=op; postfix=concat(temp,opstr); } } return postfix; } /***************************************************************************************/ int find(string s,int position) { if (position>=s.length) return 0; else { char first; int m,n; first=s.ch[position]; if (isalpha(first)) return 1; else { m=find(s,position+1); n=find(s,position+1+m); if ((m==0)||(n==0)) return 0; else return m+n+1; } } }

Page 8: Algorithms Data Structures 1

–1–الخوارزميات و بنى المعطيات

6 آلية الهندسة المعلوماتية - جامعة البعث

:Merge Sort -مسألة الفرز بالدمج

Merge(و نريد ترتيب هذه العناصر ضمن الجدول بطريقة الفرز بالدمج , عناصره من األعداد الصحيحة غير المرتبة , tليكن لدينا الجدول Sort .(ثم نقوم بدمجهما في جدول مرتب , دة و نرتب آل جدول جزئي على ح, نقسم الجدول إلى جدولين جزئيين : و تتلخص هذه الطريقة بما يلينتابع هذه العملية وصوًال إلى جداول جزئية مؤلفة من . عملية ترتيب آل جدول جزئي هي تطبيق لنفس الطريقة لكن عند مستوى أقل . واحد

.ثم نقوم بدمج آل جدولين مع المقارنة حسب الترتيب, عنصر واحد فقط . نحن إذًا أمام مسألة عودية

:فإن خطوات خوارزمية الفرز بالدمج آالتالي , أعداد صحيحة غير مرتبة 6ذنا آمثال جدول مؤلف من لو أخ [ 9 7 3 0 6 1 ] [ 9 7 3 ] [ 0 6 1 ] [ 9 7 ] [ 3 ] [ 0 6 ] [1 ] [ 9 ] [ 7 ] [ 3 ] [ 0 ] [ 6 ] [1 ] [ 7 9 ] [ 3 ] [ 0 6 ] [ 1] [ 3 7 9 ] [ 0 1 6 ] [ 0 1 3 6 7 9 ]

:هما , لى إجراءين لحل المسألة سوف نعتمد عvoid merge(int low,int mid,int high,tableType t); // مرتبين في جدول مرتب وحيدنلدمج جدولين جزئيي void mergeSort(int low,int high,tableType t); // إجراء عودي يقوم بتجزئة جدول و ترتيب آل جدول جزئي على

ن المرتبينحدا و ثم يطلب دمج الجدولين الجزئيي ) : هما أدلة بداية و نهاية الجدولين الجزئيينhigh و lowحيث أن ( يكون على الشكل التالي mergeSortمخطط خوارزمية الـ

:طالما شرط التوقف غير محقق .mid و وضع القيمة المقابلة لهذا الدليل في المتحول tحساب دليل منتصف الجدول -1 . بطريقة الفرز بالدمج t[low .. mid]ترتيب الجدول الجزئي -2 . بطريقة الفرز بالدمج t[mid+1 .. high]ترتيب الجدول الجزئي -3 .t[low .. high]دمج الجدولين الجزئيين المرتبين في جدول وحيد مرتب -4 .1+ي دليل نهاية الجدول األول بمعنى أن دليل بداية الجدول الجزئي الثاني يساو, نفترض أن الجدولين الجزئيين متجاورين: مالحظة

.t لتخزين العناصر قبل نقلها إلى الجدول aux و سوف نستخدم جدوًال مساعدًا :الحل

#include <iostream.h> const int n=100; typedef int tableType[n]; tableType t,aux; // t= unsorted table , aux= auxiliary table (temporary) int m; // dimension of table void merge(int low,int mid,int high,tableType t); void mergeSort(int low,int high,tableType t); // recursive algorithm /***************************************************************************************/ void main() { do { cout<<"Enter dimension of table , dim = "; cin>>m; } while (m<=0); for (int i=0;i<m;i++) { cout<<"t["<<i<<"]= "; cin>>t[i]; } mergeSort(0,m-1,t); for(i=0;i<m;i++) cout<<t[i]<<" "; } /***************************************************************************************/ void merge(int low,int mid,int high,tableType t) { int i=low, j=mid+1; //i=index in first half of t , j=index in second half of t int k=low; // k=index in aux while ((i<=mid)&&(j<=high)) { if (t[i]<t[j])

Page 9: Algorithms Data Structures 1

–1–الخوارزميات و بنى المعطيات

7 آلية الهندسة المعلوماتية - جامعة البعث

{ aux[k]=t[i]; k++; i++; } else if (t[i]>t[j]) { aux[k]=t[j]; k++; j++; } else // repition of same number { aux[k]=t[i]; // or: aux[k]=t[j] aux[k+1]=t[i]; k+=2; i++; j++; } } while (i<=mid) { aux[k]=t[i]; k++; i++; } while (j<=high) { aux[k]=t[j]; k++; j++; } i=low; while (i<=high) { t[i]=aux[i]; i++; } } /***************************************************************************************/ void mergeSort(int low,int high,tableType t) { if (low!=high) { int mid=(low+high)/2; mergeSort(low,mid,t); mergeSort(mid+1,high,t); merge(low,mid,high,t); } }

Page 10: Algorithms Data Structures 1

–1–الخوارزميات و بنى المعطيات

8 آلية الهندسة المعلوماتية - جامعة البعث

:Hilbert -منحنيات هيلبرت

.حيث أنها عبارة عن ترآيب عدة خطوط منكسرة تتبع منهجًا في الرسم, إن منحنيات هيلبرت مثال عن الزخرفة المتناسقة

)H5 إلى H1منحنيات هيلبرت من (

و يتألف آل من الثالث األولى منها من خط منكسر من , نجد بعد دراسة الشكل السابق جيدًا أنه مؤلف من خمسة أشكال متوضعة فوق بعضها H2 و H1خطوط هيلبرت من المستويات .( H3 و H2 و H1حيث نرمز لهذه الخطوط بالرموز , إحدى األشكال الثالثة الموضحة آالتالي

)H3و

و متوافقة من حيث , التي تعد أصغر حجمًا بمرتين Hi من ترآيب أربعة أشكال من المستوى Hi+1نالحظ أنه يمكن الحصول على المستوى H1 المستوى يمكن اعتبار أن. و تتصل مع بعضها بثالثة قطع مستقيمة , و توجه هذه األشكال األربعة إلى جميع االتجاهات المختلفة , الشكل

.أربعة نقاط تم وصلها بواسطة ثالثة خطوط = فارغة H0مؤلف من أربعة أشكال

H1

H2

H3

Page 11: Algorithms Data Structures 1

–1–الخوارزميات و بنى المعطيات

9 آلية الهندسة المعلوماتية - جامعة البعث

آترآيب ألربعة إجرائيات تقوم آل Hiفإننا نستطيع التعبير عن إجرائية رسم , متصلة Hi-1 يتألف من أربعة منحنيات Hiبما أن آل منحني

و , و لنرمز بأسهم إلى عمليات رسم الوصالتA,B,C,Dلنرمز إلى هذه اإلجرائيات األربعة بـ . ناسبين باالتجاه و القياس المHi-1منها برسم :بالتالي نستطيع التعبير عن المخطط العودي لهذه اإلجرائيات آما يلي

A : D A A B B : C B B A C : B C C D D : A D D C

.X0Y طول القطعة المستخدمة في رسم الخط المنكسر و أن جملة االحداثيات هي h البرنامج حيث أن لنكتب ) Borland Turbo C++ under Dosحيث يمكن تطبيق البرنامج في( :الحل

:مالحظات .(x,y)ة يرسم خط مستقيم بدءًا من الموقع الحالي لمؤشر الكتابة و حتى النقطlineto(x,y) التابع -

- initgraph من أجل تهيئة الشاشة إلظهار الرسم البياني. - setcolor لتغيير لون خط الرسم عندما تكون الشاشة في وضع Graphmode بينماTextcolor تسنخدم في الوضع Textmode.

#include <graphics.h> #include <conio.h> // --> getch() const int n=5,h0=512; int h,x,y,x0,y0; void A(int i); void B(int i); void C(int i); void D(int i); /***************************************/ void main() { int gdriver = DETECT, gmode; initgraph(&gdriver, &gmode, ""); int i=0; h=h0; x0=h/2; y0=x0; do { i++; h/=2; setcolor(i); x0=x0+(h/2); y0=y0-(h/2); moveto(x0,y0); x=x0; y=y0; A(i); getch(); } while (i<n); closegraph(); } /***************************************/ void A(int i) { if (i>0) { D(i-1); x-=h; lineto(x,y); A(i-1); y+=h; lineto(x,y); A(i-1); x+=h; lineto(x,y);

B(i-1); } } /***************************************/ void B(int i) { if (i>0) { C(i-1); y-=h; lineto(x,y); B(i-1); x+=h; lineto(x,y); B(i-1); y+=h; lineto(x,y); A(i-1); } } /***************************************/ void C(int i) { if (i>0) { B(i-1); x+=h; lineto(x,y); C(i-1); y-=h; lineto(x,y); C(i-1); x-=h; lineto(x,y); D(i-1); } } /***************************************/ void D(int i) { if (i>0) { A(i-1); y+=h; lineto(x,y); D(i-1); x-=h; lineto(x,y); D(i-1); y-=h; lineto(x,y); C(i-1); } }

Page 12: Algorithms Data Structures 1

–1–الخوارزميات و بنى المعطيات

10 آلية الهندسة المعلوماتية - جامعة البعث

:Sierpinsky -منحنيات سيربنسكي

:فمثًال لدينا ! لكنها أآثر تعقيدًا و أناقة , منحنيات سيربنسكي تشبه من حيث الترآيب منحنيات هلبرت

S1 - S3حنيات سيربنسكي من منS1 - S4 منحنيات سيربنسكي من

S1منحني سيربنسكي من المستوى S1 - S2 منحنيا سيربنسكي من

, لذلك يجب اعتماد مخطط عودي لخوارزمية الرسم , آون منحنيات سيربنسكي منحنيات مغلقة S1 باالعتماد على S2نالحظ أنه ال يمكن رسم .بحيث نحصل على منحنيات مفتوحة يؤدي وصلها إلى الحصول على الرسم المطلوب

المنحنيات ي إلى هذه تجمعها أربع قطع مستقيمة ال تنتمA,B,C,D هو ترآيب ألربع إجرائيات nسنعتبر أن منحني سيربنسكي من الدرجة . 90oإن المنحنيات األربعة متماثلة و ينتج آل منها من اآلخر بدوران قدره . و يعطي المنحني المطلوب

:A اعتمدنا على القطع األربعة التالية مع الوصل بينها بقطع مستقيمة مائلة و ذلك بدئًا من عند رسم S1فمثًال أثناء رسم

:هو ) مهما آان المستوى ( األساسي لرسم منحني سيربنسكي فالمخطط S : A B C D

A

B

C

D

Page 13: Algorithms Data Structures 1

–1–الخوارزميات و بنى المعطيات

11 آلية الهندسة المعلوماتية - جامعة البعث

: من المستوى الثانيA يجب االعتمد على القطع األربعة التالية مع الوصل بينها بقطع مستقيمة مائلة و ذلك بدئًا من عند رسم S2أما لرسم

: من المستوى الثالثA يجب االعتمد على القطع األربعة التالية مع الوصل بينها بقطع مستقيمة مائلة و ذلك بدئًا من عند رسم S3أما لرسم

. هو عبارة عن أربعة نقاط تم الوصل بينها بقطع وصل S0حيث أن منحني سيربنسكي من الدرجة صفر أي : التي تقوم برسم المنحنيات الجزئية فهو A,B,C,Dالمخطط العودي لإلجرائيات األربعة أما

A : A B D A B : B C A B C : C D B C D : D A C D

.حيث يرمز السهم العريض إلى قطعة مستقيمة مضاعفة الطول

:ردناها لرسم منحنيات هيلبرت نكتب البرنامج الالزم لرسم منحنيات سيربنسكي بإتباع نفس الخطوات التي أو )Borland Turbo C++ under Dosحيث يمكن تطبيق البرنامج في ( :الحل

#include <graphics.h> #include <conio.h> const int n=4,h0=256; int i,h,x,y,x0,y0; void A(int i); void B(int i); void C(int i); void D(int i); /***************************************************************************************/ void main() { int gdriver = DETECT, gmode; initgraph(&gdriver, &gmode, "");

A B C D

A

. . . . . . . . . . . . . .

Page 14: Algorithms Data Structures 1

–1–الخوارزميات و بنى المعطيات

12 آلية الهندسة المعلوماتية - جامعة البعث

i=0; h=h0/4; x0=2*h; y0=h; do { i++; x0-=h; h/=2; y0-=h; x=x0; y=y0; moveto(x0,y0); setcolor(i); A(i); x+=h; y+=h; lineto(x,y); B(i); x-=h; y+=h; lineto(x,y); C(i); x-=h; y-=h; lineto(x,y); D(i); x+=h; y-=h; lineto(x,y); getch(); } while (i<n); closegraph(); } /***************************************************************************************/ void A(int i) { if (i>0) { A(i-1); x+=h; y+=h; lineto(x,y); B(i-1); x+=2*h; lineto(x,y); D(i-1); x+=h; y-=h; lineto(x,y); A(i-1); } } /***************************************************************************************/ void B(int i) { if (i>0) { B(i-1); x-=h; y+=h; lineto(x,y); C(i-1); y+=2*h; lineto(x,y); A(i-1); x+=h; y+=h; lineto(x,y); B(i-1); } } /***************************************************************************************/ void C(int i) { if (i>0) { C(i-1); x-=h; y-=h; lineto(x,y); D(i-1); x-=2*h; lineto(x,y); B(i-1); x-=h; y+=h; lineto(x,y); C(i-1); } } /***************************************************************************************/ void D(int i) { if (i>0)

Page 15: Algorithms Data Structures 1

–1–الخوارزميات و بنى المعطيات

13 آلية الهندسة المعلوماتية - جامعة البعث

{ D(i-1); x+=h; y-=h; lineto(x,y); A(i-1); y-=2*h; lineto(x,y); C(i-1); x-=h; y-=h; lineto(x,y); D(i-1); } }

:تمرين

a(n x n) من مصفوفة مربعة x لعنصر minor الـحيث أن, Minorsحساب معين مصفوفة مربعة عوديًا باستخدام طريقة النشر و حساب الـ ). n-1 x n-1أي نحصل على مصفوفة ذات أبعاد ( x بعد حذف آل من السطر و العمود اللذين يحتويان aهو المصفوفة الجزئية الناتجة من

: عوديًا آما يليn مربعة من الدرجة a لمصفوفة (Determinant)نعرف معين

∑ (minor(a[i,j])): و إال det(a) = a[i,j]: أحادية فإن a(1x1)نت إذا آا−

=

+ ××−=1

0det],[)1()det(

n

i

ji jiaa

. عمود تم تثبيته jحيث :الحل

#include <iostream.h> const int m=5; struct matrix{ // definition of quadratic matrix int n; // n= number of lines ( = number of columns ) int val[m][m]; }; matrix a; int i,j;

int det(matrix a); matrix minor(matrix a,int i,int j); /***************************************************************************************/ void main() { cout<<"Enter number of lines(=columns)= "; cin>>a.n; for (i=0;i<a.n;i++) for (j=0;j<a.n;j++) { cout<<"a["<<i<<"]["<<j<<"]="; cin>>a.val[i][j]; } cout<<"Det(a)= "<<det(a); } /***************************************************************************************/ int det(matrix a) { if (a.n==1) return a.val[0][0]; else { matrix mat; int i,j=0,d=0; // j= the fixed column , d= det of a for (i=0;i<a.n;i++) { mat=minor(a,i,j); if (((i+j)%2)!=0) // (i+j) odd number d-=a.val[i][j]*det(mat); else

Page 16: Algorithms Data Structures 1

–1–الخوارزميات و بنى المعطيات

14 آلية الهندسة المعلوماتية - جامعة البعث

d+=a.val[i][j]*det(mat); } return d; } } /***************************************************************************************/ matrix minor(matrix a,int i,int j) { int ii,jj,t=-1,k; // t=line of new matrix , k=column of new matrix matrix mat; mat.n=a.n-1; for (ii=0;ii<a.n;ii++) if (ii!=i) { t++; k=-1; for (jj=0;jj<a.n;jj++) if (jj!=j) { k++; mat.val[t][k]=a.val[ii][jj]; } } return mat; }

Page 17: Algorithms Data Structures 1

–1–الخوارزميات و بنى المعطيات

15 آلية الهندسة المعلوماتية - جامعة البعث

تحويل الخوارزميات العودية إلى خوارزميات تكرارية

:طريقة حذف االستدعاء العودي المتطرف -1

أي ال يوجد أي تعليمة أخرى بعد تنفيذ االستدعاء ضمن نص , نقول عن استدعاء عودي أنه متطرفًا إذا آان هذا االستدعاء ينهي تنفيذ اإلجرائية ). لعودي ضمن اإلجرائية بغط النظر عن موضع االستدعاء ا( اإلجرائية

فيصبح الشكل while أو حلقة تكرارية مثل goto يمكن تحويله إلى خوارزمية تكرارية باالستعانة بتعليمة متطرفًافي حالة آون االستدعاء العودي :العام للتحويل آالمخطط التالي

void p( X … , Y … ) void p( X … , Y … ) { . { start: . . . if (condition) Y=… . else X = E ; p( E , Y ); goto start; . . . . { استدعاء متطرف {

.رف متطp( E , Y )و االستدعاء العودي , قائمة من متحوالت الخرج Y, قائمة من متحوالت الدخل Xحيث :الطريقة العامة لتحويل اإلجرائيات العودية إلى إجرائيات تكرارية -2

. ألنها تعتمد على استخدام المكدسات , Stackسوف نؤجل هذه الطريقة حاليًا إلى أن نصل بدراستنا إلى مفهوم المكدس

:أمثلة على طريقة حذف االستدعاء العودي المتطرف :ي لعدد صحيح حساب العامل ) :1(مثال

استخدام حلقة while استخدام goto label الخوارزمية العودية long fact(int n) { if ((n==1)||(n==0)) return 1; else return n* fact(n-1); } استدعاء متطرف

long fact(int n) { long f=1; Start: if ((n==1)||(n==0)) return f; else { f*=n; n--; goto Start; } }

Long fact(int n) { long f=1; while (n!=0) { f*=n; n--; } return f; }

: إيجاد القاسم المشترك األآبر لعددين صحيحين) :2(مثال

حلقةاستخدام while استخدام goto label الخوارزمية العوديةint gcd(int x,int y) { if (y==0) return x; else return gcd(y,x%y); } استدعاء متطرف

int gcd(int x,int y) { int h; Start: if (y==0) return x; else { h=x; x=y; y=h%y; goto Start; } }

int gcd(int x,int y) { int h; while (y!=0) { h=x; x=y; y=h%y; } return x; }

Page 18: Algorithms Data Structures 1

–1–الخوارزميات و بنى المعطيات

16 آلية الهندسة المعلوماتية - جامعة البعث

: حساب رفع قوة لعدد صحيح) :3(مثال

استخدام حلقة while استخدام goto label الخوارزمية العوديةint power(int x,int n) { if (n==0) return 1; else if (n==1) return x; else return x* power1(x,n-1); } استدعاء متطرف

int power(int x,int n) { int p=1; Start: if (n==0) return p; else { p*=x; n--; goto Start; } }

int power(int x,int n) { int p=1; while (n!=0) { p*=x; n--; } return p; }

:مسألة أبراج هانوي ) :4(مثال

ديةعو الميةرزخوا

ال

void Hanoi(int n,char a,char b,char c) { if (n==1) cout<<a<<" --> "<<c<<endl; else { Hanoi(n-1,a,c,b); cout<<a<<" --> "<<c<<endl; Hanoi(n-1,b,a,c); استدعاء متطرف } }

goto

labe

l

void Hanoi(int n,char a,char b,char c) { char h; Start: if (n==1) cout<<a<<" --> "<<c<<endl; else { Hanoi(n-1,a,c,b); cout<<a<<" --> "<<c<<endl; n--; h=a; a=b; b=h; goto Start; } }

While

void Hanoi(int n,char a,char b,char c) { char h; while (n!=1) { Hanoi(n-1,a,c,b); cout<<a<<" --> "<<c<<endl; n--; h=a; a=b; b=h; } cout<<a<<" --> "<<c<<endl; }

Page 19: Algorithms Data Structures 1

–1–الخوارزميات و بنى المعطيات

17 آلية الهندسة المعلوماتية - جامعة البعث

:إيجاد جداء عددين صحيحين ) :5(مثال

استخدام حلقة while استخدام goto label الخوارزمية العوديةint multi(int x,int y) { if (y==0) return 0; if (y==1) return x; else return x + multi(x,y-1); }

استدعاء متطرف

int multi(int x,int y) { int m=x; if (y==0) return 0; else Start: if (y==1) return m; else { m+=x; y--; goto Start; }}

int multi(int x,int y) { int m=x; while (y!=1) { m+=x; y--; } return m; }

:t ضمن قائمة مرتبة xعن عنصر ) المجاالت بطريقة تنصيف( خوارزمية البحث الثنائي ) :6(مثال

ديةعو الميةرزخوا

ال

char binS(int x,array t,int low,int high) { int mid; c='n'; // no , x not found if (low<=high) { mid=(low+high)/2; if (x==t[mid]) c='y'; // yes , x found else if (x<t[mid]) return binS(x,t,low,mid-1); else return binS(x,t,mid+1,high); } return c; }

goto

labe

l

char binS(int x,array t,int low,int high) { int mid; c='n'; // no , x not found Start: if (low<=high) { mid=(low+high)/2; if (x==t[mid]) c='y'; // yes , x found else if (x<t[mid]) { high=mid-1; goto Start; } else { low=mid+1; goto Start; } } return c; }

Page 20: Algorithms Data Structures 1

–1–الخوارزميات و بنى المعطيات

18 آلية الهندسة المعلوماتية - جامعة البعث

While

char binS(int x,array t,int low,int high) { int mid; char c='n'; // no , x not found while ((low<=high)&&(c=='n')) { mid=(low+high)/2; if (x==t[mid]) c='y'; // yes , x found else if (x<t[mid]) high=mid-1; else low=mid+1; } return c; }

Page 21: Algorithms Data Structures 1

–1–الخوارزميات و بنى المعطيات

19 آلية الهندسة المعلوماتية - جامعة البعث

Backtracking Algorithms - خوارزميات التراجعية ال

.في حل المسائل ) Try-and-Error" (التجريب و الخطأ"الخوارزميات التراجعية هي خوارزميات عودية تعتمد طريقة ندرس ثم , المتاحة للخطوة التالية تفي آل خطوة نحدد اإلمكانيا, تتلخص هذه الطريقة ببناء الحل النهائي للمسألة عن طريق مجموعة من الخطوات

عندما يتأآد لنا أن . و نتابع الخوارزمية اعتمادًا على هذه الخطوة , و نسجلها على أنها الخطوة التالية في الحل النهائي , هذه اإلمكانيات بأن ننتقي أحدها سجل أخطاء يفيد في تجنب الوقوع في تشبه هذه العملية بناء. نعدل عن هذه الخطوة , أو يؤدي إلى طريق مسدود , اختيارنا ال يقود إلى الحل النهائي

.الخطأ مرتين بل تم وضع , أي دون تحديد لغة برمجية معينة , pseudocodeحيث آتب بـلغة الخوارزميات ( إن المخطط العام للخوارزميات التراجعية آالتالي

) :الشكل العام للخوارزمية مع الشرح باللغة اإلنكليزية و دون تفاصيل دقيقة void try() { initialize selection of candidates; do { select next candidate; if (acceptable) { record it; if (solution incomplete) { try next step; if (not successful) cancel recording; } } } while (not successful)and(remains of candidates); }

void try() { ; هتيئة اإلمكانيات املمكن ترشيحها do { ; اختيار املرشح التايل if (مقبول) { ; تسجيل اخلطوة احلالية if (احلل غري مكتمل) { ; حاول اخلطوة التالية if (غري ناجحة) ; إلغاء تسجيل آخر خطوة } } }while احلل غري مكتمل( )and )وجود مرشحني أخرى( ; }

فة من خالل عرض حلول سنتداول هذا المخطط في األمثلة التالية لنبين استخداماته المختل. تختلف تفصيالت هذا المخطط باختالف المسألة المطروحة

.بعض أهم المسائل الشهيرة

:Knightstour -مسألة جولة حصان الشطرنج 10: حيث <X0,Y0>نضع حصانًا في موقع معين , مربعًا n×nلدينا رقعة شطرنج فيها 0 −≤≤ nX 10 و 0 −≤≤ nY و علينا إيجاد

. بحيث يحدث المرور بكل مربع مرة واحدة فقطn2 - 1أي أن نوجد متتالية من الحرآات عددها) إذا آان ذلك ممكنًا (ة طريقة لتغطية الرقعو لدينا مجموعة من اإلمكانيات التي يجب أن , سنفترض في آل مرحلة أننا قمنا بعدد من الحرآات : لحل المسألة سنهتم فقط بحرآة الحصان التالية

" .أتؤدي إلى حل أم إلى طريق مسدود؟"نجرب إحدى هذه الحرآات و نناقش , مرحلة لدينا عدد من الحرآات الممكنة في آل . نجربها :يمكن التعبير عن ذلك بالخوارزمية العودية المبسطة التالية و المستوحاة من المخطط الخوارزمي التراجعي العام

void try next move() { initialize selection of moves; do { select next candidate from list of next moves; if (acceptable) { record move; if (board not full) { try next move; if (not successful) erase previous recording; } } } while (board not full)and(there are more candidates yet); }

Page 22: Algorithms Data Structures 1

–1–الخوارزميات و بنى المعطيات

20 آلية الهندسة المعلوماتية - جامعة البعث

X

3

1

2

4

5

6 7

8

: نعرفها بالشكل hنمثل الرقعة بمصفوفة مربعة . لتفصيل الخوارزمية سنحدد بنى المعطيات المستخدمة و معامالت اإلجرائية

const int n=5; int h[n][n];

)X,Y( عندما ال يحدث المرور في المربع h[X,Y] = 0 -: حيث نعتبر - h[X,Y] = i في المربع عندما يحدث المرور)X,Y ( في الخطوةi

:معامالت الخوارزمية )X,Y: (الموقع الذي نريد تطبيق الخوارزمية فيه • i: رقم الخطوة • نجاح أو فشل: يعطي نتيجة المناقشة qمتحول خرج •

i < n2: بالشكل ) board not full" (الرقعة ليست ممتلئة: "بناًء على ذلك يمكن تبسيط العبارة " (مقبول"فإن العبارة ) Lحسب طريقة حرآة الحصان المعروفة على الشكل ( لتمثيل إحدى المواقع الممكنة u , vإذا استعملنا متحولين موضعيين

acceptable ( 0: يمكن التعبير عنها بالشكل ≤ v ≤ n-1 and 0 ≤ u ≤ n-1 and h[u,v] = 0.

نعلم من قواعد لعبة الشطرنج أن . >X,Y< األخيرة من تبسيط الخوارزمية هي تحديد الحرآات الممكنة التي يمكن إجراؤها من موقع معين المرحلة : الحصان يستطيع في الحالة العامة االنتقال إلى ثمانية مواقع يبينها الشكل التالي

افة فروق إلى إحداثيات موقع يمكن الحصول على إحداثيات هذه المواقع الجديدة بإض : يعرفان بالشكل b و aالحصان و نخزن هذه الفروق في جدولين

int a[8] , b[8]; عند استدعاء اإلجرائية . لترقيم إمكانيات االنتقال التالي kآما نستطيع استخدام عداد

نسند القيمة واحد و , اللذين يمثالن الموقع االبتدائي للحصان >X,Y<نحدد المعاملين .h[X,Y]للموقع

.h[0,0]حيث يبدأ الحصان من الموقع , البرنامج التالي يعطي الحل الكامل لمسألة جولة الحصان على رقعة الشطرنج #include <iostream.h> #include <iomanip.h> // --> setw() const int n=5; // number of lines/columns int i,j; char q='n'; // no , the solution is incomplete int a[8],b[8]; int h[n][n]={0}; void try1(int i,int x,int y,char &q); /******************************************************************************************/ void main() { a[0]=2; b[0]=1; a[1]=1; b[1]=2; a[2]=-1; b[2]=2; a[3]=-2; b[3]=1; a[4]=-2; b[4]=-1; a[5]=-1; b[5]=-2; a[6]=1; b[6]=-2; a[7]=2; b[7]=-1; h[0][0]=1; // first step (i=1) is fixed

Page 23: Algorithms Data Structures 1

–1–الخوارزميات و بنى المعطيات

21 آلية الهندسة المعلوماتية - جامعة البعث

try1(2,0,0,q); if (q=='y') for (i=0;i<n;i++) { for (j=0;j<n;j++) cout<<setw(5)<<h[i][j]; cout<<endl; } else cout<<"No solution !\n"; } /******************************************************************************************/ void try1(int i,int x,int y,char &q) { int u,v,k=-1; do { k++; u=x+a[k]; v=y+b[k]; if ((u>=0)&&(u<n)&&(v>=0)&&(v<n)&&(h[u][v]==0)) { h[u][v]=i; if (i<n*n) { try1(i+1,u,v,q); if (q=='n') h[u][v]=0; } else q='y'; // yes , the solution is complete } } while ((q=='n')&&(k<7)); } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

:EightQueens -مسألة الوزراء الثمانية

بحسب المخطط العام للخوارزميات . بحيث ال يكون فيها أي واحد مهددًا لآلخر , طرنج الغرض من هذه المسألة هو توزيع ثمانية وزراء على رقعة ش :التراجعية فإن شكل اإلجرائية هو

void try(int i) { initialize selection of positions for i-th queen; do { make next selection; if (safe) { setqueen; if (i<7) { try (i+1); if (not successful) remove queen; } } } while (not successful)and(there are more positions yet); }

Page 24: Algorithms Data Structures 1

–1–الخوارزميات و بنى المعطيات

22 آلية الهندسة المعلوماتية - جامعة البعث

Q

8 9 10 11 12 13 14

0 1 2 3 4 5 6 7

11

14 13 12

10 9 8 7

0 1 2 3 4 5 6

أو السطر دلم من قواعد الشطرنج أنه يمكن للوزير أن يهدد جميع المربعات الموجودة في العامونع

و تؤدي , لذا يجب وضع وزير واحد في آل عامود . آما يبين ذلك الشكل المجاور , أو القطر نفسه .iم إلى تحديد رقم السطر الذي سيوضع فيه ضمن العامود رقiعملية تحديد موقع الوزير رقم

بحيث ُتحدد بنية , لحل هذه المسألة على الرقعة ال بد من مناقشة عميقة لبنية المعطيات المستخدمة في البداية يمكن . تساعد في إجراء االختبارات الالزمة عند تقرير وضع الوزير في مربع معين

رات صعبة لنعرف لكن هذا التمثيل سيؤدي إلى اختبا, تعريف رقعة الشطرنج بأنها مصفوفة مربعة .أم ال ) غير مهددًا(أيكون مربع ما آمنًا

و أن نعرف أيحوي سطر معين أو قطر , إن ما يهمنا هو موقع آل وزير ضمن العامود الموافق :لذا سنستخدم بنى المعطيات التالية . معين وزيرًا أم ال

int x[8]; // i x[i] قمتحوي رقم السطر الذي يوضع فيه الوزير رchar a[8]; // ال يحوي أي وزير j ’a[j]==’y تعني أن السطر char b[15]; // ال يحوي أي وزير j ’b[j]==’y تعني أن القطر المباشر رقمchar c[15]; // ال يحوي أي وزير j ’c[j]==’y تعني أن القطر المتعامد رقم

: التالي طريقة ترقيم أقطار رقعة الشطرنج يبين الشكل

فنالحظ أن, بعد تحديد بنى المعطيات المستخدمة نستطيع تفصيل الخوارزمية

).عددها ثمانية ( i هي آل مربعات العامود رقم i المواقع الممكنة للوزير رقم في آل مرة يكون في البداية صفرًا و يزدادj الختبار هذه المواقع نستعمل عدادًا

.7 واحدًا حتى يصل إلى القيمة

: تنفيذ التعليمات التالية j في السطر iتكافئ عملية وضع الوزير رقم

x[i]=j; a[j]=‘n’; b[7+i-j]=‘n’; c[i+j]=‘n’;

: تنفيذ التعليمات التالية j من السطر iو تكافئ عملية رفع الوزير رقم a[j]=‘y’; b[7+i-j]=‘y’; c[i+j]=‘y’;

((’c[i+j]==’y)&&(’b[7+i-j]==’y)&&(’a[j]==’y)): بالشكل ) safe" (أمان"و يمكن التعبير عن القضية

x = [ 0 , 4 , 7 , 5 , 2 , 6 , 1 , 3 ]: يعطي البرنامج التالي الحل للمسألة الممثل بالشكل

X

X

X

X

X

X

X

X

إحدى حلول مسألة الوزراء الثمانية

Page 25: Algorithms Data Structures 1

–1–الخوارزميات و بنى المعطيات

23 آلية الهندسة المعلوماتية - جامعة البعث

:الحل

#include <iostream.h> #include <iomanip.h> int i; char q='n'; // no , there is no solution char a[8]; // lines char b[15]; // direct diagonals char c[15]; // indirect diagonals int x[8]; // solution = lines void try1(int i,char &q); void print(); /******************************************************************************************/ void main() { for (i=0;i<8;i++) a[i]='y'; // all lines are safe for (i=0;i<15;i++) b[i]='y'; // all direct diagonals are safe for (i=0;i<15;i++) c[i]='y'; // all indirect diagonals are safe try1(0,q); if (q=='y') print(); else cout<<"No solution !\n"; } /******************************************************************************************/ void try1(int i,char &q) { int j=-1; do { j++; q='n'; if ((a[j]=='y')&&(b[7+i-j]=='y')&&(c[i+j]=='y')) { x[i]=j; a[j]='n'; b[7+i-j]='n'; c[i+j]='n'; if (i<7) { try1(i+1,q); if (q=='n') { a[j]='y'; b[7+i-j]='y'; c[i+j]='y'; } } else q='y'; } } while ((q=='n')&&(j<7)); } /******************************************************************************************/ void print() { for (int k=0;k<8;k++) cout<<setw(5)<<x[k]; cout<<endl; }

Page 26: Algorithms Data Structures 1

–1–الخوارزميات و بنى المعطيات

24 آلية الهندسة المعلوماتية - جامعة البعث

. ع الحلول لمسألة معينةبحيث نوجد جمي, نستطيع االستفادة من خوارزمية حل مسألة الوزراء الثمانية في تعميم المخطط العام للخوارزميات التراجعية

.األخرىو إنما نسجل هذا الحل و نتابع تجريب اإلمكانيات , و لتحقيق ذلك يجب عدم إيقاف تجريب اإلمكانيات المتاحة عند الوصول إلى حل :يصبح مخطط الخوارزميات التراجعية التي توجد جميع الحلول آالتالي

void try(int i) { for (int k=0;k<m-1;k++) { select k-th candidate; if (acceptable) { record it; if (i<n) try(i+1); else print solution; } } }

: الثمانية تصبح إجرائية البحث عن الحلول آالتالي في حالة مسألة الوزراء

void try2(int i) { for (int j=0;j<8;j++) { if ((a[j]=='y')&&(b[7+i-j]=='y')&&(c[i+j]=='y')) { x[i]=j; a[j]='n'; b[7+i-j]='n'; c[i+j]='n'; if (i<7) try2(i+1); else print(); a[j]='y'; b[7+i-j]='y'; c[i+j]='y'; } } }

) .ال ينتج أحدها عن اآلخر بتدوير الرقعة أو بالتناظر( حًال مستقًال 12من بين هذه الحلول يوجد , حل 92بهذا نستطيع إيجاد آافة الحلول و عددها

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Page 27: Algorithms Data Structures 1

–1–الخوارزميات و بنى المعطيات

25 آلية الهندسة المعلوماتية - جامعة البعث

:Optimal Selection -مسألة الخيار األمثل

درسنا في . يأتي هذا المثال ليبين آيف يمكن أن نستخدم المخطط العام للخوارزميات التراجعية في مقارنة الحلول التي يمكن إيجادها لمسألة معينة

ثم عممنا , أو في مسألة الوزراء الثمانية, آما فعلنا في مسألة جولة حصان الشطرنج, يمكن استخدام هذا المخطط إليجاد حل واحدالمثالين السابقين آيف ًا لكننا سنحتفظ بحل واحد يكون أمثليًا اعتماد, في هذه الفقرة سنتبع الطريقة نفسها . هذا المخطط لنستطيع إيجاد جميع الحلول لمسألة الوزراء الثمانية

.على معايير تسمح بمقارنة الحلول الممكنة إذا افترضنا أننا . إليجاد الحل األمثل لمسألة معينة يجب إيجاد جميع الحلول الممكنة بحيث نحتفظ دومًا بحل واحد ُيعتبر أمثليًا بحسب معيار معين

مكن الحصول على الحل األمثل بتعديل المخطط العام عندئذ ي, ) إحدى الحلولS( حيث F(S)نستطيع مقارنة الحلول بواسطة تابع موجب :للخوارزميات التراجعية التي توجد جميع الحلول بحيث نستبدل عملية إظهار الحل بالتعليمات التالية

if ( F(Solution)>F(Optimal) ) Optimal=Solution;

. Optimalو بذلك نحتفظ في آل لحظة بأفضل حل أمكن الحصول عليه في المتحول

تجري عملية بناء الخيارات الممثلة للحلول . سنختار مثاًال لمسألة الحل األمثل مسألة هامة تتلخص بإيجاد االختيار األمثل من مجموعة عناصر معطاةصر إلى االختيار أو نناقش في حالة آل عنصر فائدة ضم هذا العن. عن طريق مناقشة آل عنصر من عناصر المجموعة األساسية, المقبولة بالتدريج

.ثم ننتقل إلى العنصر التالي عوديًا, عدم فائدته

أو نستبعد هذا العنصر و نتابع بناء , إما أن نضم هذا العنصر إلى الخيار اآلني الذي نحن بصدد بنائه: عند فحص فائدة عنصر معين نستنتج أحد أمرين :و هذا مما يجعل خوارزمية الحل تأخذ الشكل التالي , دة و يجب مناقشة هذين االحتمالين آل على ح. اختيارنا دونه

void try(int i) { if (inclusion is acceptable) { include i-th object; if (i<n) try(i+1); else check optimality; erase i-th object; } if (exclusion is acceptable) // إذا آان االستبعاد مقبوًال if (i<n) try(i+1); else check optimality; }

ر القبول في الحد لذلك يجب أن نستفيد من معايي) عنصرnعدد أجزاء مجموعة مؤلفة من ( اختيارًا ممكنًا 2nتبين دراسة هذه الخوارزمية أن هناك

.سنوضح طريقة تقليص هذا العدد في ضوء مثال محدد . آثيرًا من هذا العدد

بحيث Aو لنفترض أننا نريد بناء مجموعة جزئية من , V و قيمة W مجموعة من األشياء لكل منها وزن A = { a1 , a2 , ... , an }لتكن و يقوم بإعداد , تصادف هذه المسألة أي مسافر يستعيد للسفر بالطائرة. و مجموع أسعارها أعظميًا , يكون مجموع أوزان عناصرها أقل من حد معين

.و عليه اختيار مجموعة صغيرة من األشياء ال يتجاوز وزنها العام الوزن المسموح به في المطار , حقيبته :يبين الجدول التالي وزن آل منها و قيمته , تحوي المجموعة فيها أربعة عناصر, لتوضيح مبدأ العمل نأخذ حالة بسيطة

a4 a3 a2 a1 العنصر ) W (الوزن 10 11 15 17 ) V (القيمة 18 20 25 17

يمكن تمثيل تنفيذ خوارزمية البحث . آغ و تكون قيمتها أعظمية30و نريد اختيار مجموعة جزئية من هذه العناصر بحيث ال يزيد وزنها الكلي عن

الفرع اليساري يعني . ( تمثل آل عقدة داخلية في هذه الشجرة عملية مناقشة ضم أو استبعاد عنصر, تيار بالشجرة المبينة بالشكل التالي عن أفضل اخ

Page 28: Algorithms Data Structures 1

–1–الخوارزميات و بنى المعطيات

26 آلية الهندسة المعلوماتية - جامعة البعث

من ). 16عددها ( Aو تمثل األوراق الخيارات الناتجة أو المجموعات الجزئية للمجموعة ). ضم العنصر و الفرع اليميني يعني استبعاد العنصرأما بقية الحلول فيجب حساب قيمة . ألنها ال تحقق شرط الوزنS13 , S9 , S5 , S3 , S2 , S1دراسة هذه الحلول يتبين أنه يجب استبعاد الحلول

.45و يعطي القيمة , هو أفضل حل S10و من الواضح من أن الحل , آل منها

S1={a1,a2,a3,a4}; S2={a1,a2,a3}; S3={a1,a2,a4}; S4={a1,a2}; S5={a1,a3,a4}; S6={a1,a3}; S7={a1,a4}; S8={a1}; S9={a2,a3,a4}; S10={a2,a3}; S11={a2,a4}; S12={a2}; S13={a3,a4}; S14={a3}; S15={a4}; S16={ };

:سوف نستخدم لحل المسألة المتحوالت التالية

limW : الوزن األقصى لـn ثابت ( = عنصر( totV : السعر الكلي لـn ثابت ( = عنصر(

s : صف يجمع عناصر االختيار اآلني opts : صف يعبر عن االختيار األمثل الذي حصلنا عليه حتى اللحظة الحالية

maxV : مجموع أسعار عناصر االختيار األمثلopts av : السعر العام لالختيارsالذي حصلنا عليه حتى اللحظة الحالية

tw : الوزن العام لالختيارsالذي حصلنا عليه حتى اللحظة الحالية

:دم ضمه الذي نحن بصدد بنائه أو عsلنحدد طريقة لتقرير ضم عنصر إلى الصف فكلما نريد ضم عنصر " . 0"و نعطي لها قيم بدائية , مؤلف من أعداد صحيحة عددها نفس عدد العناصر الكلي s لنمثل العناصر المنضمة بصف

ففي آل ". 0"أما في حال عدم ضم العنصر يبقى عنصر الصف المقابل له ". 1" القيمة s[i] أي s نعطي للعنصر المقابل له في الصف iترتيبه ). n-1 إلى 0حيث أن العناصر مرقمة من ( أم ال sخطوة نمشيها سنناقش ضم عنصر واحد إلى الصف

هو مجموع قيم العناصر المنضمة إضافة إلى قيم العناصر التي لم نناقش بعد av و أن s الوزن الكلي للعناصر المنضمة في الصف twلنفترض

: رقم العنصر الذي نعالجه حاليًا نجد iو بفرض . ضمها إلى الصف : i = 0في البداية

tw = 0; av = ∑−

=

1

0].[

n

ivia

: يكون i = n-1و عندما تصبح

tw ≤ limW; av = ∑=1][

].[is

via

tw + a[i].w ≤ limW: بالقضية " الضم مقبول"عندئذ يمكن التعبير عن الشرط av - a[i].v > maxV: بالقضية " االستبعاد مقبول"و يمكن التعبير عن الشرط

a1

a2

a3

a4

S15 S16S14 S13S12S11S1 S2 S3 S4 S5 S6 S7 S8 S9 S10

Page 29: Algorithms Data Structures 1

–1–الخوارزميات و بنى المعطيات

27 آلية الهندسة المعلوماتية - جامعة البعث

. و التي يمكن ضمها مستقبًال يمكن أن يتجاوز أفضل قيمة وصلنا إليها حتى اآلن sي يكافئ القول إن مجموع قيم العناصر الموجودة حاليًا في و الذ

.فإنه من المؤآد أن الحل الناتج أفضل من آخر حل أمكن الحصول عليه , و يكون االستبعاد مقبوًال i = n-1عندما تكون

100 و 10حيث أعطينا األوزان العظمى قيمًا بين , عنصر 12الي يعطي الحل الكامل لهذه المسألة حيث يبين الجدول التالي حالة انضمام البرنامج الت .آيلوغرامًا

#include <iostream.h> #include <iomanip.h> // --> setw() const n=12; struct objects { int v,w; // v=value , w=weight }; int i; objects a[n]; int limW,totV=0,maxV; int w1,w2,w3; int s[n]={0},opts[n]={0}; // if (s[i]==1) object i selected , if (s[i]==0) not selected void try1(int i,int tw,int av); /******************************************************************************************/ void main() { for (i=0;i<n;i++) { cout<<"Enter weight,value ("<<i<<") = "; cin>>a[i].w>>a[i].v; totV+=a[i].v; } cout<<"Enter w1,w2,w3 = "; cin>>w1>>w2>>w3; cout<<"Weight "; for (i=0;i<n;i++) cout<<setw(4)<<a[i].w; cout<<endl; cout<<"Value "; for (i=0;i<n;i++) cout<<setw(4)<<a[i].v; cout<<endl; do { limW=w1; maxV=0; try1(0,0,totV); cout<<setw(6)<<limW; for (i=0;i<n;i++) if (opts[i]==1) cout<<setw(4)<<"*"; else cout<<setw(4)<<" "; cout<<endl; w1+=w2; } while (w1<=w3); } /******************************************************************************************/ void try1(int i,int tw,int av) { int av1; if (tw+a[i].w<=limW) { s[i]=1; if (i<n-1) try1(i+1,tw+a[i].w,av);

Page 30: Algorithms Data Structures 1

–1–الخوارزميات و بنى المعطيات

28 آلية الهندسة المعلوماتية - جامعة البعث

else if (av>maxV) { maxV=av; for (int j=0;j<n;j++) opts[j]=s[j]; } s[i]=0; } av1=av-a[i].v; if (av1>maxV) if (i<n-1) try1(i+1,tw,av1); else { maxV=av1; for (int j=0;j<n;j++) opts[j]=s[j]; } }

:يكون تنفيذ البرنامج آالجدول التالي

الوزن 10 11 12 13 14 15 16 17 18 19 20 21 القيمة 15 18 15 17 21 20 19 21 23 24 24 25 * 10 * 20 * * 30 * * * 40 * * * * 50 * * * * * 60 * * * * * 70 * * * * * * 80 * * * * * * 90 * * * * * * * 100

Page 31: Algorithms Data Structures 1

–1–الخوارزميات و بنى المعطيات

29 آلية الهندسة المعلوماتية - جامعة البعث

:مترين

األصفار تمثل حيث أن الواحدات تمثل جدران المتاهة و, يمثل الشكل التالي متاهة من و بالتالي يمكن االنتقال ضمن المتاهة. الممرات الممكن سلوكها عبر المتاهة

.موضع آخر يوجد فيه صفراً موضع إلى الجدار األيمن من أجل إيجاد المخرج من هذه المتاهة نضع يدنا اليمنى على

و نستمر , و نقوم بالسير قدماً دون أن نرفع يدنا فوق األصفار Startعند المدخل :و المطلوب . Goalبالمشي حتى أن نصل إلى المخرج

التي تقوم بإيجاد الطريق try1لتراجعية اكتب برنامجاً يعتمد على الخوارزمية ا طباعة الشكل حيث يجب في نهاية البرنامج, الواصل ما بين المدخل و المخرج

وضع رقم الخطوة السابق نفسه لكن مكان األصفار الواقعة على الطريق يجب ثم عمم المسألة إليجاد جميع الحلول و ثم الحل ( .لمعرفة تسلسل الخطوات الحالية

) .ألمثل فقط ا :الحل

#include <iostream.h> #include <conio.h> const int n=10; // number of lines/columns int h[n][n]={{0,0,0,0,0,0,0,0,0,0},{0,0,0,0,1,0,0,0,0,0},{0,0,1,0,1,0,1,1,0,0}, {0,1,1,0,1,0,0,1,0,0},{0,0,0,0,0,1,0,1,0,1},{1,1,1,0,1,1,0,1,0,1}, {1,0,1,0,1,1,0,1,0,1},{1,0,1,0,0,0,0,1,0,1},{1,0,0,0,1,1,1,1,0,1}, {1,1,1,1,1,1,1,1,1,1}}; int optS[n][n]; // optimal solution int a[4],b[4]; int i,j,Xn,Yn,minL=0; // minL = length of optimal solution (=shortest way) char q='n',c; // no , the solution is incomplete void try1(int i,int x,int y,char &q); // one solution void try2(int i,int x,int y); // all solutions void try3(int i,int x,int y); // optimal solution void print(int h[n][n]); /******************************************************************************************/ void main() { a[0]=-1; b[0]=0; a[1]=0; b[1]=1; a[2]=1; b[2]=0; a[3]=0; b[3]=-1; cout<<"Enter Xo = "; cin>>i; cout<<"Enter yo = "; cin>>j; h[i][j]=2; cout<<"Enter X-Goal = "; cin>>Xn; cout<<"Enter y-Goal = "; cin>>Yn; cout<<"One Solution --> Press 1\n"; cout<<"All Solutions --> Press 2\n"; cout<<"Optimal Solution --> Press 3\n"; c=getch(); if (c=='1') { try1(3,i,j,q); if (q=='y') print(h); else cout<<"No solution";

0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 1 0 1 1 0 0 0 1 1 0 1 0 0 1 0 0 0 0 0 0 0 1 0 1 0 1 1 1 1 0 1 1 0 1 0 1 1 0 1 0 1 1 0 1 0 1 1 0 1 0 0 0 0 1 0 1 1 0 0 0 1 1 1 1 0 1 1 1 1 1 1 1 1 1 1 1

Start

Goal

Page 32: Algorithms Data Structures 1

–1–الخوارزميات و بنى المعطيات

30 آلية الهندسة المعلوماتية - جامعة البعث

} else if (c=='2') try2(3,i,j); else { try3(3,i,j); print(optS); } getch(); } /******************************************************************************************/ void try1(int i,int x,int y,char &q) { int u,v,k=-1; do{ ++k; u=x+a[k]; v=y+b[k]; if ((u>=0)&&(u<n)&&(v>=0)&&(v<n)&&(h[u][v]==0)) { h[u][v]=i; if ((u==Xn)&&(v==Yn)) q='y'; else { try1(i+1,u,v,q); if (q=='n') h[u][v]=0; } } } while ((q=='n')&&(k<3)); } /******************************************************************************************/ void try2(int i,int x,int y) { int u,v,k=-1; do{ ++k; u=x+a[k]; v=y+b[k]; if ((u>=0)&&(u<n)&&(v>=0)&&(v<n)&&(h[u][v]==0)) { h[u][v]=i; if ((u==Xn)&&(v==Yn)) { print(h); getch(); } else try2(i+1,u,v); h[u][v]=0; } } while (k<3); } /******************************************************************************************/ void try3(int i,int x,int y) { int u,v,k=-1; do{ ++k; u=x+a[k]; v=y+b[k];

Page 33: Algorithms Data Structures 1

–1–الخوارزميات و بنى المعطيات

31 آلية الهندسة المعلوماتية - جامعة البعث

if ((u>=0)&&(u<n)&&(v>=0)&&(v<n)&&(h[u][v]==0)) { h[u][v]=i; if ((u==Xn)&&(v==Yn)) { if ((minL==0)||(i<minL)) { minL=i; for (int w=0;w<n;w++) for (int t=0;t<n;t++) optS[w][t]=h[w][t]; } } else try3(i+1,u,v); h[u][v]=0; } } while (k<3); } /******************************************************************************************/ void print(int h[n][n]) { for (int i=0;i<n;i++) { for (int j=0;j<n;j++) cout<<h[i][j]<<" "; cout<<endl; } }

_________________________________________________________________________________________

: عن الخوارزميات التراجعيةتمرين لإلطالع

:The stable marriage problem - مسألة الزواج المستقر

:و المطلوب . nو بعدد أساسي واحد و يساوي , B و Aلتكن لدينا المجموعتان غير المتقاطعتان

Aa بحيث يكون < a , b > و من الشكل n : 1إيجاد مجموعة أزواج مرتبة من المجموعة Bb و ∋ و يحققان بعض الشروط , ∋ stableو الذي يدعى قاعدة الزواج المستقر , و سوف تتعرف في الفقرة التالية على أحدها , توجد معايير مختلفة الختيار هذه األزواج . رىاألخ

marriage rule. اصفات التي و لنفرض أن كل شخص من كلتا المجموعتين قد وضع ترتيباً محدداً بالمو, مجموعة آنسات Aو , مجموعة شباب Bلنفرض أن

و اآلنسة a بحيث يكون الرجل < a ,b > زوجاً من الثنائيات nفإذا أمكن اختيار . يرغب بأن تتحقق لدى قرينه الممكن الزواج منه b و في حال عدم. عندئذ تعد مجموعة القران تلك غير مستقرة , و يرغب كل منهما في أن يكون قرين اآلخر , غير متزوجين من بعضهما

.وجود هذه األزواج تدعى المجموعة مستقرة ( كعملية اختيار طالب كلية , والتي يتعلق فيها التوزيع ببعض األفكار و اآلراء , تعد هذه المسألة حالة نوعية للكثير من المسائل المشابهة

.أو غيرها من المسائل المشابهة , أو عملية فرز عناصر فرقة عسكرية , ) المفاضلة و لكن نالحظ أن عملية وضع قائمة رغبات من كال الطرفين ال تتغير و ال تتعلق بمعيار , اختيار الشريك الزوجي مثال ذو حدس شخصي إن مثال

و , و لكن قد تشوه الواقع , تؤدي إلى تبسيط المسألة , و بحيث يتم البحث عن بديل في حال إخفاق أحد الطرفين , < a , b >إنشاء الزوج .ية تجريد تدعى عمل

في زوج إلى أن تنتهي B و Aنجرب و بالتتالي توحيد عنصرين من المجموعتين : يمكن البحث عن حلول لهذه المسألة على الشكل التالي .لنحاول إيجاد جميع التوزيعات المستقرة التي تمكننا بسهولة من العثور على الحل . عناصر المجموعتين

Page 34: Algorithms Data Structures 1

–1–الخوارزميات و بنى المعطيات

32 آلية الهندسة المعلوماتية - جامعة البعث

COMPLEXITY –تعقيد الخوارزميات

).أي لتحديد الخوارزمية األسهل(يلزم حساب تعقيد الخوارزميات للتمييز بين خوارزميات مختلفة حيث جميعها تحل نفس المشكلة

.باإلضافة إلى ذلك فإن حساب درجة التعقيد هام جدًا لقياس زمن تنفيذ برنامج ما :ت المهمة التالية ال بد من ذآر المالحظا, قبل أن نبدأ بدراسة تعقيد الخوارزميات

:بعض المفاهيم الرياضية الالزمة لمقارنة الخوارزميات -

: إذا آان f(n) = O(g(n)) أو f = O(g) و نرمز إلى ذلك بـ g إنه ٌمسيطر عليه من قبل f نقول عن التابع

f(n) = O(g(n)) ⇔ ∃ c,N | n > N ⇒ f(n) ≤ c g(n) :1-مثال

f(n) = n g(n) = 3n n < c(3n) ⇒ c >

31 ⇒ { f(n) = O(g(n)) ; c >

31 }

:2-مثالf(n) = 5n3 = O(n3) ; f(n) = n2 + n = O(n2) ; 6n2 + 3n = O(n2) ; c=7 , n=3

: للمقارنة نعتمد على الحقائق التالية O(1) ≤ O(log n) ≤ O(nk) ≤ O(n) ≤ O(n log n) ≤ O(nc) ≤ O(cn) ≤ O(n!) ;(0≤k≤1≤c)

2

)1(...321 +=++++

nnn ; 2

)1(....32 qnnnqqqq +=++++

q

qqqqn

n

−−

=++++ −

11....1 12 ;

11.....1

132

−−

=++++++

qqqqqq

nn

:مالحظات

c*O(g) = O(g) : الضرب بثابت -

O(g1) + O(g2) = O(Max { g1 , g2 }): جمع و ضرب التوابع -

O(g1) * O(g2) = O( g1 * g2 ): جمع و ضرب التوابع -

O(g1) + O(g2) = O(Max { g1 , g2 }): جمع و ضرب التوابع -

:درجة تعقيد خوارزمية

.ية لحل هذه المسألة درجة تعقيد مسألة هي درجة تعقيد أفضل خوارزم : حساب زمن تنفيذ خوارزمية -

:يتعلق زمن تنفيذ برنامج ما بالعوامل التالية المعطيات الحالية للبرنامج -1 )تميز النوعية حسب اللغة المستخدمة (compiler البرنامج المولد من قبل المترجم codeنوعية -2 نوعية و جودة المكتبات المستخدمة -3 سرعة الخوارزمية -4 ودة البرنامج المكتوب من قبل المبرمجج -5

Page 35: Algorithms Data Structures 1

–1–الخوارزميات و بنى المعطيات

33 آلية الهندسة المعلوماتية - جامعة البعث

:لحساب زمن التنفيذ يجب تحديد أمرين و هما

فمثًال: معطيات المسألة ) أو طول أو حجم(التوصيف الكمي للمسألة أي ُبعد **)1 عدد العناصر الالزم ترتيبها = sort ُبعد مسألة ترتيب عناصر

درجة آثير الحدود = ُبعد مسألة معالجة آثير حدود عدد الرؤوس أو عدد األضالع = graph ُبعد مسألة بيان

m x n أو m+n أو max(m,n)مثًال = (m x n) ُبعد مسألة مصفوفات من المرتبة :فمثًال) البسيطة أمام العمليات التي هي أآثر آلفةحيث نهمل العمليات( تحديد العمليات األساسية التي سوف تأخذ بعين االعتبار **)2

بالنسبة لعدد من العمليات المتتالية فإن زمن الحساب يجمع جمعًا • T(c) + Max(T(a),T(b))فإن الزمن يحسب بالعالقة ;if (c) a; else bبالنسبة لعمليات الشرطية من الشكل • n x m زمن تنفيذ ما داخل الحلقة فيكون زمن التنفيذ هو mر مرة على األآثر و باعتبا nبالنسبة لحلقة تنفذ • بالنسبة لطلب برنامج جزئي غير عودي تحسب درجة تعقيد اإلجرائية باستخدام نفس القواعد •فمثًال في خوارزمية حساب العاملي لعدد صحيح موجب , بالنسبة لبرنامج جزئي عودي نستخدم عالقته العودية لحساب درجة التعقيد •

:عتبر أن عملية الضرب هي العملية األساسية و بالتالي نالحظنT(0) = 0 T(n) = 1 + T(n-1) ; n >= 1 => T(n) = n الحل هو

:قياس درجة التعقيدر في قائمة عناصرها فمثًال يوجد فرق بين مسألة البحث عن عنص) أي حسب حجمها و محتوياتها ( يتعلق زمن خوارزمية بالمعطيات التي تعالجها

....أعداد صحيحة و قائمة أخرى عناصرها سجالت أو حتى قوائم مترابطة :نميز بين ما يلي n معطيات المسألة ذات الحجم Dnبفرض

:A التعقيد الزمني في أحسن األحوال للخوارزمية -1MinA(n) = Min { CostA(d) ; d ∈ Dn } ; هو آلفة الزمن الالزم cost حيث

: A التعقيد الزمني في أسوأ األحوال للخوارزمية -2MaxA(n) = Max { CostA(d) ; d ∈ Dn }

: A التعقيد الزمني الوسطي للخوارزمية -3AverageA(n) = ∑

⋅nDd

A dCostdP )()(

.dن تكون معطيات الخوارزمية هي احتمال أpحيث .عنصرًا nضمن قائمة تحوي x حساب التعقيد الزمني الوسطي لمسألة البحث التسلسلي عن العنصر :مثال

. A لنسمي خوارزمية البحث :الحل MaxA(n) = n : من الواضح أن أسوأ الحاالت الممكنة هي وجود العنصر المطلوب في نهاية القائمة و بالتالي

MinA(n) = 1: بينما أحسن حالة هي آون العنصر المطلوب هو أول عنصر في القائمة أي نقوم بعملية مقارنة واحدة فقط : أما لحساب التعقيد الزمني الوسطي نحدد ما يلي

في القائمة و لنفرض أنه إذا x هو احتمال وجود qئمة و يمكن ال نفرض أن يمكن أن يكون موجودًا في القا xمع األخذ بعين االعتبار أن العنصر و التي n إلى مجموعة آل القوائم التي طولها Dn,i نرمز بـ i ≤ n-1 ≥ 0فمن أجل . في القائمة فإن المواضع آلها متساوية االحتمالxوجد

:و بالتالي . xيظهر فيها P(Dn,-1) = 1 – q => Cost(Dn,-1) = n P(Dn,i) = q / n => Cost(Dn,i) = i+1

AverageA(n) = nqnqnqnnnqnqi

nq n

i⋅−+

+=⋅−+

+=⋅−++∑

=

)1(2

)1()1(2

)1()1()1(1

0

: و بالتالي q=1 موجود في القائمة فإن xفإذا آنا نعلم سلفًا أن 2

)1()( +=

nnAverageA

Page 36: Algorithms Data Structures 1

–1–الخوارزميات و بنى المعطيات

34 آلية الهندسة المعلوماتية - جامعة البعث

: فإن q=1/2 في القائمة xو إذا آان احتمال وجود 4

13)( +=

nnAverageA

:أمثلة ) :insert( حساب درجة التعقيد لخوارزمية اإلدخال لترتيب صف *)1مثال

Cost(n) = )(2222

)1(.......321 222

nOnnnnnn =≈+=+

=++++

.نهمل الثوابت في درجة التعقيد :مالحظة

) :Bubble Sort(حساب درجة التعقيد لخوارزمية الفرز بالفقاعات *)2مثال عملية i نجري iفي المرور . مرورًا في الحلقة الخارجيةn-1هناك , )واحدة داخل األخرى( و يحتوي البرنامج على حلقتين nُبعد المسألة هو

: تبديل مواقع و لذالك عمليةiمقارنة و

Cost(n) = )()1(2

)1(22 21

1nOnnnni

n

i=−=

−=∑

=

:(Binary Search) حساب درجة التعقيد لخوارزمية البحث الثنائي عن عنصر في قائمة *)3مثال تعيد تقسيم تعتمد الخوارزمية على حساب منتصف المجموعة و اختبار وجود العنصر في المنتصف أو في القسم األيسر أو في القسم األيمن ثم

:مقارنة و إعادة تقسيم : إذًا في آل مرحلة ينقص عدد العناصر إلى النصف و نقوم بعمليتين . حتى نصل إلى الجواب.... المجموعة المتبقية T(1) = 1

T(n) = 1 + T(2n )

T(n) = 1 + 1 + T(4n )

T(n) = 2 + T(4n )

T(n) = 2 + 1 + T(8n )

T(n) = 3 + T( 32n )

………………………..

T(n) = k + T( k

n2

)

kn : بفرض 2= => k = log n

T(n) = log n + T(nn )

T(n) = log n + T(1) T(n) = log n + 1 T(n) = O(log n)

quick sortبينما بالنسبة للترتيب فإن خوارزمية الترتيب السريع . خوارزمية البحث الثنائي هي أسرع خوارزمية بحث:مالحظة .Cost(n) = n log(n) هي األسرع حيث

: P and (Non Polynomial) NP ( Polynomial ) المسائل -

. إذا آانت درجة تعقيدها ذات درجة آثير حدود )P = polynomial( فعالةنقول عن خوارزمية أنها .أي أسية , إذا آانت درجة تعقيدها ليست بدرجة آثير حدود ) NP = non polynomial ( غير فعالةو نقول عن خوارزمية أنها

هي مسائل صعبة و غير قابلة للمعالجة إال في حالة NP هي مسائل سهلة و قابلة للمعالجة بينما المسائل التي تنتمي إلى Pلتي تنتمي إلى إن المسائل ا .معطيات ذات حجم محدود

Page 37: Algorithms Data Structures 1

–1–الخوارزميات و بنى المعطيات

35 آلية الهندسة المعلوماتية - جامعة البعث

:NP أو Pيبين الشكل التالي أمثلة على درجات تعقيد مختلفة مع انتمائهم إلى

:تعقيدأمثلة على حساب ال :احسب درجة تعقيد الخوارزمية العودية لحساب العاملي لعدد صحيح موجب

T(0) = 0 نعتبر أن عملية الضرب هي العملية األساسية و بالتالي : T(n) = 1 + T(n-1) = 2 + T(n-2) = 3 + T(n-3) …………………. = k + T(n-k) ; n - k = 0 ⇒ k = n ⇒ = n + T(0) = n + 0 T(n) = O(n)

:احسب درجة تعقيد الخوارزمية العودية لحساب عدد مرفوع إلى قوة T(0) = 0 ر أن عملية الضرب هي العملية األساسية و بالتالي نعتب : T(n) = 1 + T(n-1) = 2 + T(n-2) = 3 + T(n-3) …………………. = k + T(n-k) ; n - k = 0 ⇒ k = n ⇒ = n + T(0) = n + 0 T(n) = O(n)

:سب درجة تعقيد الخوارزمية العودية لحساب ناتج ضرب عددين صحيحين اح T(0) = 0 نعتبر أن عملية الجمع هي العملية األساسية و بالتالي : T(n) = 1 + T(n-1) = 2 + T(n-2) …………………. = k + T(n-k) ; n - k = 0 ⇒ k = n ⇒ = n + 0 T(n) = O(n)

) :Bubblesort(احسب درجة تعقيد خوارزمية الفرز بالفقاعات : و بالتالي ) حيث أن الخوارزمية تكرارية(نعتبر أن عملية المقارنة هي العملية األساسية T(n) = (n-1) + (n-2) + ….. + 2 + 1

= 2

)1( −nn

T(n) = O(n2)

O(1) ثابتlog(n)nn log(n)n2

Hash التقطيع ائيالبحث الثن

fact (Quicksort) الترتيب

..., الترتيب باإلدخال , آثير حدود , ضرب مصفوفات

P

أسي

.

.

. NP

Page 38: Algorithms Data Structures 1

–1–الخوارزميات و بنى المعطيات

36 آلية الهندسة المعلوماتية - جامعة البعث

) :Insertsort(احسب درجة تعقيد خوارزمية الفرز باإلدخال

:تعتمد على الفكرة التالية ) Insertsort(خوارزمية الترتيب باإلدخال , ) أي األول ( و نحاول حشر العنصر الثاني بين العناصر ما قبله , تبر العنصر األول مرتبًانع حيث, نبدأ من عند العنصر الثاني وصل إلى أول نمجرد ما , اآلن نبدأ من عند العنصر الثالث و نحاول حشره ما بين العنصرين المرتبين ما قبله . فإذا آان األول أآبر نبدل

. إلى العنصر األخير ... الخامس , و هكذا نكرر نفس الخطوات من عند العنصر الرابع . ب صحيحًا ألن أصبح الترتي, نتوقف , عنصر أصغر : إذًا . مرة n-1و في المرة األخيرة , .... , في المرة الثالثة ثالثة مرات , في المرة الثانية مرتين , ففي أول مرة نقارن مرة واحدة فقط

: و بالتالي ) حيث أن الخوارزمية تكرارية(أن عملية المقارنة هي العملية األساسية نعتبر T(n) = 1 + 2 + 3 + …… + (n-1)

= 2

)1( −nn = O(n2)

) :Quicksort(احسب درجة تعقيد خوارزمية الفرز السريع ) :تشبه خوارزمية الدمج ( تعتمد على الفكرة التالية ) Quicksort(سريع خوارزمية الترتيب ال

األول نضع فيه جميع العناصر : عنصر و نجزئ عناصر الصف إلى صفين جزئيين n نبحث عن القيمة الوسطية ما بين الـ عقيد نفترض أن تقريبًا نصف العناصر أصغر و فلحساب الت. الوسطى و الثاني نضع فيه جميع العناصر األآبر ة األصغر من القيم

... اآلن نعيد نفس الخطوات على الصفوف الجزئية . أصغر أم أآبر : إذًا من أجل آل عنصر لدينا مقارنتين . النصف الثاني أآبر ه دومًا لدينا القيم األصغر علمًا أن, دون مقارنة ( اآلن ندمج آل صفين معًا . حتى أن نحصل على صفوف مؤلفة من عنصر وحيد

: و بالتالي ) حيث أن الخوارزمية عودية(نعتبر أن عملية المقارنة هي العملية األساسية :إذًا ) . على اليسار و القيم األآبر على اليمين T(1) = 1

T(n) = n + n + 2 T(2n )

= 2 n + 2 T(2n )

= 4n + 4 T(4n )

= 6n + 8 T(8n ) ………………….

= 2kn + k2 T( k

n2

) ; k

n2

= 1 ⇒ k = log(n) ⇒

= 2 n log(n) + n T(n) = O(nlog(n))

) :Hanoi(احسب درجة تعقيد خوارزمية هانوي : هي العملية األساسية و بالتالي ) طباعة(= نعتبر أن عملية النقل

T(1) = 1 T(n) = 1 + 2 T(n-1) = 1 + 2 + 4 T(n-2) = 1 + 2 + 4 + 8 T(n-3) = 1 + 2 + 4 + 8 + 16 T(n-4) …………………………

= 21

21−

− k

+ k2 T(n-k) ; n - k = 1 ⇒ k = n - 1 ⇒

= 21

21 1

−− −n

+ 12 −n T(1)

= 12 −n - 1 + 12 −n = 2 12 −⋅ n - 1 = n2 - 1 T(n) = O( n2 ) ⇒ NP الخوارزمية غير فعالة

Page 39: Algorithms Data Structures 1

–1–الخوارزميات و بنى المعطيات

37 آلية الهندسة المعلوماتية - جامعة البعث

) :Fibonacci(احسب درجة تعقيد خوارزمية فيبوناتشي

: و بالتالي ) حيث أن الخوارزمية عودية(نعتبر أن عملية الجمع هي العملية األساسية T(0) = 0 T(1) = 0 T(n) = 1 + T(n-1) + T(n-2) = 1 + 2 + T(n-2) + 2T(n-3) + T(n-4) = 1 + 2 + 4 + T(n-3) + 3T(n-4) + 3T(n-5) + T(n-6) = 1 + 2 + 4 + 8 + T(n-4) + 4T(n-5) + 6T(n-6) + 4T(n-7) + T(n-8) = 1 + 2 + 4 + 8 + 16 T(n-4) (وسطيًا)

= 21

21−

− k

+ k2 T(n-k) ; n - k = 0 ⇒ k = n ⇒

= n2 -1 + 02 ⋅n T(n) = O( n2 ) ⇒ NP الخوارزمية غير فعالة

)لإلطالع : ( ات زمن تنفيذ خوارزمية بداللة التعقيد و حجم المعطي

حجم المعطيات التعقيد 10 100 1.000 10.000 100.000 1.000.000

10 -6 s 10 -6 s 10 -6 s 10 -6 s 10 -6 s 10 -6 s 1 19.93 ns 16.61 ns 13.29 ns 9.97 ns 6.64 ns 3.32 ns log 2 n 1000 ms 100 ms 10 ms 1 ms 0.1 ms 0.01 ms N 19931.57 ms 1660.96 ms 132.88 ms 9.97 ms 0.66 ms 0.03 ms n log n11.57 d 2.78 h 100.00 s 1.00 s 0.01 s 0.0001 ms N2

31710 y 31.71 y 11.57 d 1000.00 s 1.00 s 0.001 ms N3

∞ ∞ ∞ 1 x 10 295 y 4.02 x 10 16 y 1.02 s 2n

( ns = nano second , ms = milli second , s = second , min = minute , h = hour , d = day , y = year )

)لإلطالع : ( حجم المعطيات التي يمكن معالجتها بداللة التعقيد الزمني و زمن التنفيذ

زمن التنفيذ1 y 1 h 1 min 1 s التعقيد

∞ ∞ ∞ ∞ 1 ∞ ∞ ∞ ∞ log 2 n 86 x 10 9 36 x 10 8 6 x 10 7 10 6 N 97 x 10 8 13 x 10 7 28 x 10 5 63 x 10 3 n log n 26 x 10 4 60 x 10 3 7.7 x 10 3 10 3 n2

4400 1500 360 100 n3

36 31 25 19 2n

. حاسوب و يجب عدم توظيفها لحل المسائل باستعمال ال, من دراسة الجدولين السابقين يتبين أن بعض الخوارزميات ال تصلح

Page 40: Algorithms Data Structures 1

–1–الخوارزميات و بنى المعطيات

38 آلية الهندسة المعلوماتية - جامعة البعث

Advanced Data Structures -بنى معطيات متقدمة

:سوف نتعرف في الدروس القادمة على أهم بنى معطيات متقدمة و التي هي : بنى المعطيات الخطية -

Arraysاألشعة • Linked Listsالسالسل الخطية • Stacksالمكدسات • Queuesاألرتال •

Treesة البنى الشجري - Graphsالبيانات -

:بنى المعطيات الخطية

من أهم بنى المعطيات . ألنها تسمح بتنظيم المعطيات التي نريد معالجتها تنظيمًا تسلسليًا , ُتعد البنى الخطية أآثر البنى استعماًال لتنظيم المعطيات :الخطية لدينا

Arrays - األشعة

.ادي البعد حيث نذآر إنه يمكن الوصول إلى أي عنصر من شعاع وصوًال مباشرًا من المعروف أن الشعاع صف أح Lists Linked - الخطية السالسل

قراءة , إيجاد طول السلسلة : حيث يمكننا في الحالتين تطبيق العمليات التالية عليها . يمكن تمثيل السالسل الخطية إما باستخدام األشعة أو بالمؤشرات .حشر عنصر و حذف عنصر , بحث عن عنصر , ) تصاعديًا و تنازليًا ( ة السلسل

: تمثيل السالسل الخطية باستخدام األشعة -1

:مثال. حقل طول السلسلة و حقل صف عناصر السلسلة : و يتم ذلك بتعريف سجل مؤلف من حقلين const lmax=100; struct listType { int length; elem val[lmax]; // elem = أي نمط معطيات معروف };

:سلبيات تمثيل السالسل باستخدام األشعة لذلك يجب أخذ هذه الفكرة بعين االعتبار أثناء تعريف السلسلة و . فال يمكن إضافة عناصر أآثر من طول السلسلة , إن الطول األعظم للسلسلة محدود .باإلضافة إلى ذلك فأن عمليات الحشر و الحذف تسبب عددًا آبيرًا من اإلزاحات في الذاآرة . حجز طول زائد حتى ال يحدث خطأ

فارغةL.length=0 ⇔ L :مالحظات L.val[i] = العنصر ذا الرقمi من السلسلة L

من السلسلة الخطيةk في الموقع xإضافة عنصر سلة الخطية في السلk من الموقع xحذف عنصر listType delet(listType L,int k) { if ((k<L.length)&&(k>=0)) { for (int i=k;i<L.length-1;i++) L.val[i]=L.val[i+1]; --L.length; } return L; }

listType insert(listType L,elem x,int k) { if ((L.length<lmax)&&(k<=L.length)) { for (int i=L.length-1;i>=k;i--) L.val[i+1]=L.val[i]; L.val[k]=x; ++L.length; } return L; }

Page 41: Algorithms Data Structures 1

–1–الخوارزميات و بنى المعطيات

39 آلية الهندسة المعلوماتية - جامعة البعث

: تمثيل السالسل الخطية باستخدام المؤشرات -2

و لكن , سنكتفي بالكالم عنها , نة الدراسية األولى و باإلضافة إلى المراجعة في بداية السنة الثانية بما أننا درسنا هذا الموضوع بشكل معمق في الس :و هو , يوجد مفهوم جديد يجب التعرف عليه

:السالسل الدائرية و نحدد السلسلة بمؤشر إلى . لسلة نجعل هذا المؤشر يؤشر إلى أول عنصر في السnilبدًال من أن يأخذ المؤشر في آخر عنصر في السلسلة القيمة

:آما في الشكل التالي , آخر عنصر فيها

:السالسل مضاعفة االرتباط .آما أننا نجعل مؤشر العنصر األول أن يؤشر إلى آخر عنصر , نجعل فيها مؤشر العنصر األخير أن يؤشر إلى أول عنصر

Pascal Triangle -مثلث باسكال : تمرين

) :6= حيث عدد األسطر هنا ( ُيمثل مثلث باسكال بالشكل التالي

:و المطلوب واحدة فقط باستخدام قائمة مترابطة n حتى السطر 1نريد حساب و طباعة مثلث باسكال من السطر

ابطة تحوي فقط فإن القائمة المترiبعد حساب السطر ) . نمثل فيها العناصر المختلفة عن الواحد فقط ( يعتمد علىiمن الطبيعي أن حساب عناصر السطر ) . المختلفة عن الواحد ( iعناصر السطر t[i,j] = t[i-1,j] + t[i-1,j-1]: وفق القاعدة المعروفة i - 1عناصر السطر

.t من المثلث i هو موقع العنصر في السطر jحيث .سبة لتمثيل عناصر مثلث باسكال حدد بنى معطيات منا -1 قبل i - 1الحظ أن نفس القائمة تحوي عناصر السطر السابق ( و تخزينها في القائمة المترابطة iاآتب إجرائية تقوم بحساب عناصر السطر -2

) .استدعاء هذه اإلجرائية ) .آما في الشكل ( مي سطرًا من مثلث باسكال وفق الشكل النظاnاآتب إجرائية تقوم بطباعة أول -3

:الحل#include <iostream.h> #include <conio.h> struct str{ int val; str *prev,*next; }; str *pfirst=0,*plast=0; str s; int n; void init(); void print(); /******************************************************************************************/ void main() {

e1 e2 e3 eNplast

plaste1 e2 e3 eN

1 1 1 1 2 1 1 3 3 1 1 4 6 4 1 1 5 10 10 5 1

Page 42: Algorithms Data Structures 1

–1–الخوارزميات و بنى المعطيات

40 آلية الهندسة المعلوماتية - جامعة البعث

cout<<"Enter n = "; cin>>n; cout<<"\n\n"; if (n==1) cout<<"1 \n"; else if (n==2) { cout<<"1 \n"; cout<<"1 1 \n"; } else { cout<<"1 \n"; cout<<"1 1 \n"; for (int i=3;i<=n;i++) { init(); print(); } } getch(); } /******************************************************************************************/ void init() { if (plast==0) { s.next=0; s.prev=0; s.val=2; plast=new str(s); pfirst=plast; } else { s.next=0; s.prev=plast; s.val=1; plast->next=new str(s); plast=plast->next; str *p=plast; while (p!=pfirst) { p->val += (p->prev)->val; p=p->prev; } p->val += 1; } } /******************************************************************************************/ void print() { str *p=pfirst; cout<<"1 "; while (p!=0) { cout<<p->val<<" "; p=p->next; } cout<<"1"<<endl;

Page 43: Algorithms Data Structures 1

–1–الخوارزميات و بنى المعطيات

41 آلية الهندسة المعلوماتية - جامعة البعث

}

Page 44: Algorithms Data Structures 1

–1–الخوارزميات و بنى المعطيات

42 آلية الهندسة المعلوماتية - جامعة البعث

Thesaurus - ) مترادفات قاموس ( مكنز بناء مسألة

بحيث تكون , حيث أنه يحوي مجموعة من الكلمات مع مترادفاتها, ) Thesaurus –قاموس مترادفات ( استخدم السالسل الخطية لبناء مكنز آل مؤشر يؤشر إلى . مؤشرات مرقم حسب األحرف األبجديةلتحقيق ذلك نفترض أنه لدينا شعاع من ال. الكلمات و المترادفات مرتبة أبجديًا

آل آلمة بدورها تحوي مؤشرًا آخر إلى سلسلة خطية تحوي مترادفات هذه الكلمة . سلسلة خطية من الكلمات التي تبدأ بنفس الحرف األبجدي حذف آلمة -3 إضافة مرادف لكلمة موجودة -2 إضافة آلمة -1: و المطلوب آتابة الخوارزميات التالية. مرتبة أبجديًا آما يوضح الشكل

طباعة محتويات المكنز-8 طباعة مترادفات آلمة معينة -7 البحث عن مرادف -6 البحث عن آلمة -5 حذف مرادف -4

:الحل :لدينا " string.h"من أهم التوابع التي سوف نستخدمها من الملف

strcpy(char s1[],char s2[]) : محتوى السلسلة الثانية إلى األولى) نسخ ( الذي يقوم بإسناد stricmp(char s1[],char s2[]): فهو يمكن أن يعيد ثالثة , أيهما األصغر حسب األحرف األبجدية , الذي يقارن ما بين سلسلتين

if (s1<s2) || “>0” if (s1>s2) || “==0” (if s1==s2) ”0>“: حاالت strlwr(char s[]) :لتحويل جميع أحرف السلسلة إلى أحرف صغيرة

:بالشكل التالي , حتى نستفيد منهما في بقية اإلجرائيات , سوف نعرف على توابع البحث بشكل مناسب

char searchWord(words* pfirst,char word[],words* &pw1,words* &pw2); ( األول يرجع عنوان الكلمة في حال تم إيجادها: و مؤشرين , و الكلمة المطلوبة , هو مؤشر بداية السلسلة المقابلة للكلمة الذي pfirstحيث نمرر

)نستفيد منه في الحذف ( أما المؤشر الثاني يرجع العنوان ما قبل الكلمة المطلوبة , ) نستفيد منه في الحشر و الحذف و طباعة المترادفات char searchSyn(synonym* pfirst,char syn[],synonym* &ps1,synonym* &ps2);

األول يرجع عنوان المرادف في حال تم : و مؤشرين , و المرادف المطلوب , الذي هو مؤشر بداية السلسلة المقابلة للمرادف pfirstحيث نمرر )نستفيد منه في الحذف ( ان ما قبل المرادف المطلوب أما المؤشر الثاني يرجع العنو, ) نستفيد منه في الحشر و الحذف ( إيجاده

يجب أن نتأآد من عدم وجودها, قبل أن نحشر آلمة جديدة -مثًال : اآلن ممكن أن نستفيد من هذين التابعين قبل أن نحشر مرادف لكلمة يجب أن نتأآد من وجود الكلمة و عدم وجود المرادف - ...هكذا , أآد من وجودهما قبل حذف آلمة أو مرادف يجب أن نت -

#include <iostream.h> #include <conio.h> // -> clrscr() , getch() , getche() #include <string.h> // -> strlen() , strcpy(destination,source)=copy string , // -> stricmp(s1,s2) , strlwr(string) const L=30; // L= maxlength of a word or a synonym const n=26; // there are 26 alphabetic letters ( in English ) struct synonym { // = muradef char syn[L]; synonym* next; }; struct words { char word[L]; words* next; synonym* down; }; typedef words* dictionary[n]; dictionary d; words *pw1,*pw2; synonym *ps1,*ps2; char c; // = choice of user

'a'

'b' 'c'

'z'

مرادف

آلمة‘f’ fast

quick

rapid

speedy

:مثًال

Page 45: Algorithms Data Structures 1

–1–الخوارزميات و بنى المعطيات

43 آلية الهندسة المعلوماتية - جامعة البعث

char menu(); char searchWord(words* pfirst,char word[],words* &pw1,words* &pw2); // pw1=address // of word , pw2=address of previous word char searchSyn(synonym* pfirst,char syn[],synonym* &ps1,synonym* &ps2); // ps1=address of synonym , ps2=address of previous synonym void insertWord(words* pw1,words* &pw2,char word[]); void insertSyn(synonym* ps1,synonym* &ps2,char syn[]); void deleteWord(words* pw1,words* &pw2,char word[]); void deleteSyn(synonym* ps1,synonym* &ps2,char syn[]); void printSynonyms(synonym *ps); // prints all synonyms of one word void printDictionary(dictionary d); // prints the whole dictionary /***************************************************************************************/ void main() { do { char word[L],syn[L]; c=menu(); switch (c){ case '1':{ cout<<"Enter new word = "; cin>>word; strlwr(word); if (searchWord(d[int(word[0])-97],word,pw1,pw2)=='y') // ASCII : 'a' - 'z' ( 97 - 122 ) cout<<"The word \""<<word<<"\" does already exist ! \n"; else insertWord(pw1,pw2,word); break; } case '2':{ cout<<"Enter basic word of synonym = "; cin>>word; strlwr(word); cout<<"Enter synonym of "<<word<<" = "; cin>>syn; strlwr(syn); if (searchWord(d[int(word[0])-97],word,pw1,pw2)=='n') cout<<"Sorry , the word \""<<word<<"\" doesn't exist ! \n"; else { char v= searchSyn(pw1->down,syn,ps1,ps2); if ((pw1->down!=0)&&(v=='y')) cout<<"The synonym \""<<syn<<"\" does already exist!\n"; else insertSyn(ps1,ps2,syn); } break; } case '3':{ cout<<"Enter the word you want to delete = "; cin>>word; strlwr(word); if (searchWord(d[int(word[0])-97],word,pw1,pw2)=='n') cout<<"Sorry , the word \""<<word<<"\" does not exist ! \n"; else deleteWord(pw1,pw2,word); break; } case '4':{ cout<<"Enter the word you want to delete its synonym = "; cin>>word; strlwr(word); cout<<"Enter the synonym you want to delete = "; cin>>syn; strlwr(syn); if (searchWord(d[int(word[0])-97],word,pw1,pw2)=='n') cout<<"Sorry , the word \""<<word<<"\" does not exist ! \n"; else if (searchSyn(pw1->down,syn,ps1,ps2)=='n') cout<<"Sorry , the synonym \""<<syn<<"\" does not exist ! \n";

Page 46: Algorithms Data Structures 1

–1–الخوارزميات و بنى المعطيات

44 آلية الهندسة المعلوماتية - جامعة البعث

else deleteSyn(ps1,ps2,syn); break; } case '5':{ cout<<"Enter the word you want to search for = "; cin>>word; strlwr(word); if (searchWord(d[int(word[0])-97],word,pw1,pw2)=='y') cout<<"\""<<word<<"\" is found ! \n"; else cout<<"\""<<word<<"\" is not found ! \n"; break; } case '6':{ cout<<"Enter the basic word of the synonym = "; cin>>word; strlwr(word); cout<<"Enter the synonym you want to search for = "; cin>>syn; strlwr(syn); if (searchWord(d[int(word[0])-97],word,pw1,pw2)=='n') cout<<"Sorry , the word \""<<word<<"\" is not found ! \n"; else if (searchSyn(pw1->down,syn,ps1,ps2)=='y') cout<<"\""<<syn<<"\" is found ! \n"; else cout<<"\""<<syn<<"\" is not found ! \n"; break; } case '7':{ cout<<"Enter the word you want to see its synonyms = "; cin>>word; strlwr(word); if (searchWord(d[int(word[0])-97],word,pw1,pw2)=='y') if (pw1->down==0) cout<<"Sorry , there are no synonyms for this word ! \n"; else printSynonyms(pw1->down); else cout<<"Sorry , this word doesn't exist ! \n"; break; } case '8':{ printDictionary(d); break; } } // end of switch getch(); } while (c!='9'); } /***************************************************************************************/ char menu() { char c; do { clrscr(); cout<<"1= Insert New Word \n"; cout<<"2= Insert New Synonym \n"; cout<<"3= Delete Word \n"; cout<<"4= Delete Synonym \n"; cout<<"5= Search For a Word \n"; cout<<"6= Search For a Synonym \n"; cout<<"7= Print All Synonyms Of a Word \n"; cout<<"8= Print The Whole Dictionary \n"; cout<<"9= Exit \n\n\n"; cout<<"Enter your choice : ";

Page 47: Algorithms Data Structures 1

–1–الخوارزميات و بنى المعطيات

45 آلية الهندسة المعلوماتية - جامعة البعث

c=getche(); // getche() : reads a char and print it on userscreen cout<<"\n\n\n"; } while ((int(c)<49)||(int(c)>57)); // ASCCI : '1' - '9' ( 49 - 57 ) return c; } /***************************************************************************************/ char searchWord(words* pfirst,char word[],words* &pw1,words* &pw2) // pw1=address of word pw2=address of previous word { pw1=pfirst; pw2=pfirst; while ((pw1!=0)&&(stricmp(pw1->word,word)<0)) { pw2=pw1; pw1=pw1->next; } if ((pw1!=0)&&(stricmp(pw1->word,word)==0)) return 'y'; else return 'n'; } /***************************************************************************************/ char searchSyn(synonym* pfirst,char syn[],synonym* &ps1,synonym* &ps2) // ps1=address of synonym , ps2=address of previous synonym { ps1=pfirst; ps2=pfirst; while ((ps1!=0)&&(stricmp(ps1->syn,syn)<0)) { ps2=ps1; ps1=ps1->next; } if ((ps1!=0)&&(strcmp(ps1->syn,syn)==0)) return 'y'; else return 'n'; } /***************************************************************************************/ void insertWord(words* pw1,words* &pw2,char word[]) { words* p=new words(); strcpy(p->word,word); p->next=pw1; p->down=0; if ((pw1==0)&&(pw2==0)) // linked list is empty d[int(word[0])-97]=p; else if (pw1==pw2) // insert at the beginning d[int(word[0])-97]=p; else // insert anywhere else pw2->next=p; } /***************************************************************************************/ void insertSyn(synonym* ps1,synonym* &ps2,char syn[]) { synonym* p=new synonym(); strcpy(p->syn,syn); p->next=ps1; if ((ps1==0)&&(ps2==0)) // there are no synonyms for this word pw1->down=p; else if (ps1==ps2) // insert at the beginning pw1->down=p; else // insert anywhere else ps2->next=p; }

Page 48: Algorithms Data Structures 1

–1–الخوارزميات و بنى المعطيات

46 آلية الهندسة المعلوماتية - جامعة البعث

/***************************************************************************************/ void deleteWord(words* pw1,words* &pw2,char word[]) { synonym *ps=pw1->down,*aux; while (ps!=0) // first: delete all synonyms of this word { aux=ps; ps=ps->next; delete aux; } if (pw1==pw2) // delete first word { d[int(word[0])-97]=pw1->next; delete pw1; } else // delete anywhere else { pw2->next=pw1->next; delete pw1; } } /***************************************************************************************/ void deleteSyn(synonym* ps1,synonym* &ps2,char syn[]) { if (ps1==ps2) // delete first synonym pw1->down=ps1->next; else // delete anywhere else ps2->next=ps1->next; delete ps1; } /***************************************************************************************/ void printSynonyms(synonym *ps) // prints all synonyms of one word { while (ps!=0) { cout<<ps->syn<<" , "; ps=ps->next; } } /***************************************************************************************/ void printDictionary(dictionary d) // prints the whole dictionary { words *pw; synonym *ps; for (int i=0;i<=25;i++) { pw=d[i]; while (pw!=0) { cout<<"\n Word[ "<<pw->word<<" ] = "; ps=pw->down; while (ps!=0) { cout<<ps->syn<<" , "; ps=ps->next; } pw=pw->next; } } }

Page 49: Algorithms Data Structures 1

–1–الخوارزميات و بنى المعطيات

47 آلية الهندسة المعلوماتية - جامعة البعث

Stack - المكدس

الداخل أخيرًا هو الخارج " هو بنية خطية تشبه السلسلة المترابطة حيث يمكن معه إضافة عناصر و إزالتها من قمة المكدس فقط أي حسب المبدأ ) .LIFO = Last in , First out" (أوًال

يحتاج التابع المستدعى أن يعرف آيف يمكن له أن يعود إلى التابع , على سبيل المثال. يمكن استخدام المكدسات ضمن العديد من التطبيقات الهامةة بها يتم تخزين عناوين العودة الخاص, فإذا حدثت عدة استدعاءات لتوابع . لذلك يتم وضع عنوان مكان العودة ضمن مكدس, الذي قام باستدعائه

تساعد المكدسات على التعامل مع التوابع العودية . مما يساعد على عودة آل تابع إلى التابع الذي قام باستدعائهLIFOضمن مكدس حسب المبدأ أجل تحديد طريقة أيضًا يتم استخدام المكدسات مع المترجمات من. و استدعاءاتها بنفس الطريقة التي تتعامل فيها مع التوابع التقليدية غير العودية

.التعامل مع التعابير لحساب قيمتها و توليد لغة اآللة الموافقة لها

:العمليات على المكدسEmptyStack : للتهيئة ( إنشاء مكدس فارغ(

Push : إضافة عنصر إلى المكدس Pop : حذف عنصر من المكدس Top : قراءة العنصر الموجود في قمة المكدس

IsEmpty : اختبار آون المكدس فارغًا CleanUp : تفريغ المكدس

: مكدسًا فإن s بفرض :مالحظات

IsEmpty(s) = false تكون معرفة إذا و فقط إذا آان Top(s) و Pop(s)العمليات -- Pop(Push(s,e)) = s - Top(Push(s,e)) = e - IsEmpty(EmptyStack) = true - IsEmpty(Push(s,e)) = false

باستعمال األشعة و باستعمال المؤشرات:يمكن تمثيل المكدس بطريقتين

:لنقوم بتمثيل مكدسًا بالطريقتين و نضع آل تمثيل مع عملياته في ملف رأسي حتى نستطيع االستفادة منهما في األمثلة اآلتية التمثيل باستعمال المؤشرات ستعمال األشعةالتمثيل با

// save in header file : Stack_A.h #include <iostream.h> const lmax=100; struct stack { int top; int val[lmax]; }; /***************************************/void emptyStack(stack &s) { s.top=-1; } /***************************************/char isEmpty(stack s) { if (s.top==-1) return 'y'; else return 'n'; } /***************************************/

// save in header file : Stack_P.h #include <iostream.h> struct stackElem { int val; stackElem *link; }; typedef stackElem* stack; /***************************************/void emptyStack(stack &s) { s=0; // nil } /***************************************/char isEmpty(stack s) { if (s==0) return 'y'; else return 'n'; } /***************************************/

A F

Push(s,B)

A B

F A

Pop(s)

F

المكدس قمة

eN

eN-1

e1…

head Top

سل( بواسطة مكدس خطيةتمثيل )سلة

Page 50: Algorithms Data Structures 1

–1–الخوارزميات و بنى المعطيات

48 آلية الهندسة المعلوماتية - جامعة البعث

void push(stack &s,int e) { if (s.top==lmax-1) cout<<"Error: Stack is full \n"; else { ++s.top; s.val[s.top]=e; } } /***************************************/void pop(stack &s) { if (isEmpty(s)=='y') cout<<"Error: Stack is empty \n"; else --s.top; } /***************************************/int top(stack s) { if (isEmpty(s)=='y') cout<<"Error: Stack is empty \n"; else return s.val[s.top]; } /***************************************/void cleanUp(stack &s) { if (isEmpty(s)=='y') cout<<"Stack is already cleaned up"; else emptyStack(s); }

void push(stack &s,int e) { stack h=new stackElem(); h->val=e; h->link=s; s=h; } /***************************************/void pop(stack &s) { stack h=s; if (isEmpty(s)=='y') cout<<"Error: Stack is empty \n"; else { s=s->link; delete h; } } /***************************************/int top(stack s) { if (isEmpty(s)=='y') cout<<"Error , Stack is empty \n"; else return s->val; } /***************************************/void cleanUp(stack &s) { if (isEmpty(s)=='y') cout<<"Stack is already cleaned up"; else while (isEmpty(s)=='n') pop(s); }

.ي لعدد صحيح باستخدام مفهوم المكدساتأعد آتابة برنامج حساب العامل : مثال عملي

: نكتب ما يلي Stack_P.hباالعتماد على الوحدة : الحل#include <iostream.h> #include "Stack_P.h" int n; long fact(int n); /***************************************************************************************/ void main() { cout<<"Enter n= "; do { cin>>n; } while (n<0); cout<<n<<"! = "<<fact(n)<<endl; } /***************************************************************************************/ long fact(int n) { stack s; emptyStack(s); long f=1; while (n>0) { push(s,n); --n; }

Page 51: Algorithms Data Structures 1

–1–الخوارزميات و بنى المعطيات

49 آلية الهندسة المعلوماتية - جامعة البعث

while (isEmpty(s)=='n') { f*=top(s); pop(s); } return f; }

أما بالنسبة للمكدسات , إن الفرق ما بين قائمة مترابطة و مكدس هو أنه يمكن إدخال و حذف عنصر في القائمة في أي مكان نريد :مالحظة هامة .فيمكن إدراج العناصر و حذفها من قمة المكدس فقط

:تمرين

.مستخدمًا مفهوم المكدسات ) postfix(إلى الشكل الملحق ) Infix(اآتب إجرائية تقوم بطباعة عبارة رياضية بعد تحويلها من الشكل النظامي :الحل

حيث يحوي هذا الملف جميع عمليات المكدس و لكن مع الفرق أن محتوى السجالت من نوع , " Stack_PC.h"لنقوم بإنشاء ملف رأسي جديد :و بالتالي نجد . int بدل عدد صحيح charمحرفي

#include <iostream.h> #include <string.h> #include "Stack_PC.h" char c[25];

void print(char s[]); /***************************************************************************************/ void main() { cout<<"Enter a mathimatical infix sentence : \n"; cin>>c; print(c); } /***************************************************************************************/ void print(char c[]) { stack s; emptyStack(s); for (int i=0;i<strlen(c);i++) { if ((int(c[i])>=48)&&(int(c[i]<=57))) // Ascci : 0 - 9 cout<<c[i]; else if ((c[i]=='+')||(c[i]=='-')||(c[i]=='*')||(c[i]=='/')||(c[i]=='(') ||(c[i]==')')) switch (c[i]) { case '+':case '-': { while ((isEmpty(s)=='n')&&(top(s)!='(')) { cout<<top(s); pop(s); } push(s,c[i]); break; } case '*':case '/': { if ((isEmpty(s)=='n')&&((top(s)=='*')||(top(s)=='/'))) { cout<<top(s); pop(s); } push(s,c[i]); break; } case '(':{ push(s,c[i]);

Page 52: Algorithms Data Structures 1

–1–الخوارزميات و بنى المعطيات

50 آلية الهندسة المعلوماتية - جامعة البعث

break; } case ')':{ while (top(s)!='(') { cout<<top(s); pop(s); } pop(s); // pop '(' break; } } // end of switch } // end of for while (isEmpty(s)=='n') { cout<<top(s); pop(s); } }

:تمرين , / و * , -, : + حيث يمكن للتعبير أن يحوي العمليات الثنائية البسيطة ( اآتب إجرائية لحساب قيمة تعبير رياضي مكتوب بالشكل النظامي

")" .و "(" باإلضافة إلى األقواس :الحل

من charن أجل تخزين األعداد و الثاني عناصره مfloatاألول تكون عناصره من نوع : لننشئ ملفين رأسيين لتمثيل نوعين من المكدسات :حيث يجب مناقشة األولويات بالشكل التالي , أجل تخزين العمليات و األقواس

push: عدد حيث أن العمليات ( pushثم , ")" ) بشرط أن المكدس ليس فارغًا و القمة ليست (نخرج جميع العمليات األولى منها + : , -

) ) ألنها موجودة على اليسار : -, ( + -, + , / , : * األولى هي حيث أن العمليات ( pushثم , ")" ) بشرط أن المكدس ليس فارغًا و القمة ليست (نخرج جميع العمليات األولى منها * : , /

) ألنها موجودة على اليسار / , : * األولى هي : (push ")" . لـ popثم , ")" نخرج جميع العمليات إلى أن نصل إلى أقرب قوس مفتوح مقابل له أي ( :

#include <iostream.h> #include <string.h> // --> strlen() #include "Stack_PF.h" // name of Stack= "stack" , val = float #include "Stack_PC.h" // name of Stack= "Cstack" , val = char char s[25]; float calculate(char s[]); float getNumber(char s[],int &i); // تابع للحصول على عدد مؤلف من عدة أرقام متتالية /***************************************************************************************/ void main() { cout<<"Enter a mathimatical infix sentence : \n"; cin>>s; cout<<s<<" = "<<calculate(s); } /***************************************************************************************/ float calculate(char s[]) { float n1,n2; char op; stack sF; Cstack sC; emptyStack(sF); emptyStack(sC); for (int i=0;i<strlen(s);i++) { if ((int(s[i])>=48)&&(int(s[i]<=57))) // Ascci : 0 - 9 push(sF,getNumber(s,i)); else

Page 53: Algorithms Data Structures 1

–1–الخوارزميات و بنى المعطيات

51 آلية الهندسة المعلوماتية - جامعة البعث

if ((s[i]=='+')||(s[i]=='-')||(s[i]=='*')||(s[i]=='/')||(s[i]=='(')||(s[i]==')')) switch (s[i]){ case '*': case '/':{if ((isEmpty(sC)=='n')&&((top(sC)=='*')||(top(sC)=='/'))) { n1=top(sF); pop(sF); n2=top(sF); pop(sF); op=top(sC); pop(sC); if (op=='*') push(sF,n1*n2); else push(sF,n2/n1); // op == '/' } push(sC,s[i]); break; } case '+': case '-':{while ((isEmpty(sC)=='n')&&(top(sC)!='(')) { n1=top(sF); pop(sF); n2=top(sF); pop(sF); op=top(sC); pop(sC); if (op=='+') push(sF,n1+n2); else if (op=='-') push(sF,n2-n1); else if (op=='*') push(sF,n1*n2); else push(sF,n2/n1); // op == '/' } push(sC,s[i]); break; } case '(':{ push(sC,s[i]); break; } case ')':{ while ((isEmpty(sC)=='n')&&(top(sC)!='(')) { n1=top(sF); pop(sF); n2=top(sF); pop(sF); op=top(sC); pop(sC); if (op=='+') push(sF,n1+n2); else if (op=='-') push(sF,n2-n1); else if (op=='*') push(sF,n1*n2); else push(sF,n2/n1); // op == '/' } pop(sC); // pop '(' break; } } // end of switch } // end of for while (isEmpty(sC)=='n') { n1=top(sF); pop(sF); n2=top(sF); pop(sF); op=top(sC); pop(sC); if (op=='+') push(sF,n1+n2); else if (op=='-') push(sF,n2-n1); else if (op=='*') push(sF,n1*n2); else push(sF,n2/n1); // op == '/' } return top(sF); }

Page 54: Algorithms Data Structures 1

–1–الخوارزميات و بنى المعطيات

52 آلية الهندسة المعلوماتية - جامعة البعث

/***************************************************************************************/ float getNumber(char s[],int &i) { float num=0; while ((int(s[i])>=48)&&(int(s[i])<=57)) { num=num*10+int(s[i])-int('0'); ++i; } --i; return num; }

Page 55: Algorithms Data Structures 1

–1–الخوارزميات و بنى المعطيات

53 آلية الهندسة المعلوماتية - جامعة البعث

Queue - ) االنتظار صف ( الرتل

و يجري الحذف في الجهة المعاآسة , tailو هو بنية خطية تشبه القائمة المترابطة غير أن عمليات اإلضافة تجري في جهة ندعوها ذيل الرتل FIFO = First ) أي " الداخل أوًال هو الخارج أوًال"رتال تعمل وفقًا للمبدأ و بالتالي فإن األ, headالتي نسميها بداية الرتل

in , First Out ) . لذلك يمكنها القيام بخدمة , فمثًال من المعلوم أن معظم الحواسب لها معالج وحيد فقط . يمكن استخدام األرتال ضمن العديد من التطبيقات الهامة

آما يمكن استخدام األرتال إلدارة عمليات . يتم تخزين المعلومات المتعلقة بالمستثمرين اآلخرين ضمن رتل . ر واحد فقط في لحظة معينةمستثم ...الطباعة في حال وجود عدة مستثمرين و طابعة واحدة فقط

:العمليات على الرتل

EmptyQueue : للتهيئة ( إنشاء رتل فارغ( Enqueue : إضافة عنصر إلى الرتل Dequeue : حذف عنصر من الرتل

Top : قراءة العنصر الموجود في بداية الرتل IsEmpty : اختبار آون الرتل فارغًا CleanUp : تفريغ الرتل

:فإن , رتًال q بفرض أن :مالحظات

IsEmpty(q) = false تكون معرفة إذا و فقط إذا آان Top(q) و Dequeue(q)العمليات -- IsEmpty(EmptyQueue) = true - IsEmpty(Enqueue(q,e)) = false

باستعمال األشعة و باستعمال المؤشرات:يمكن تمثيل الرتل بطريقتين .tailؤشر إلى نهايتها مؤشر ذيل الرتل و يfrontيمثل الرتل في سلسلة خطية بحيث يؤشر إلى بدايتها مؤشر بداية الرتل

حتى نستطيع االستفادة منه في مثال برنامج Queue_P.hلنقوم بتمثيل رتًال بطريقة المؤشرات حيث نضع التمثيل مع عملياته ضمن ملف رأسي :Fibonacciحساب الـ

برنامج Fibonacci تمثيل الرتل باستعمال المؤشرات

// save in header file : Queue_P.h #include <iostream.h> struct elem { int val; elem* link; }; struct queue { elem* front; elem* tail; }; /**************************************/ void emptyQueue(queue &q) { q.front=0; q.tail=0; } /**************************************/ char isEmpty(queue q) { if (q.front==0) return 'y'; else return 'n'; }

#include <iostream.h> #include "Queue_P.h" int n; int fib(int n); /**************************************/ void main() { cout<<"Enter n = "; cin>>n; cout<<"Fib("<<n<<")= "<<fib(n); } /**************************************/ int fib(int n) { int f1,f2; queue q; emptyQueue(q); if (n<=1) return n; else { enqueue(q,0);

e1

e2

eN

front Top

rear

خطية( سلسلة بواسطة رتل )تمثيل

A F

Enqueue(q,B)

F A

B F

Dequeue(q)

B

الرتل بداية

الرتل ذيل

Page 56: Algorithms Data Structures 1

–1–الخوارزميات و بنى المعطيات

54 آلية الهندسة المعلوماتية - جامعة البعث

/**************************************/ void enqueue(queue &q,int x) { elem* h=new elem(); h->val=x; h->link=0; if (isEmpty(q)=='y') { q.front=h; q.tail=h; } else { q.tail->link=h; q.tail=h; } } /**************************************/ void dequeue(queue &q) { if (isEmpty(q)=='y') cout<<"Error: Queue is empty \n"; else { elem* h=q.front; if (q.front->link==0) { q.front=0; q.tail=0; } else q.front=q.front->link; delete h; } } /**************************************/ int top(queue q) { if (isEmpty(q)=='y') cout<<"Error: Queue is empty \n"; else return q.front->val; } /**************************************/ void cleanUp(queue &q) { if (isEmpty(q)=='y') cout<<"Error: Queue is already cleaned up \n"; else while (isEmpty(q)=='n') dequeue(q); }

enqueue(q,1); for (int i=2;i<=n+1;i++) { f1=top(q); dequeue(q); f2=top(q); enqueue(q,f1+f2); } return top(q); } }

GCD برنامج إيجاد القاسم المشترك األآبر لعددين #include <iostream.h> #include "Queue_P.h" int x,y; int GCD(int x,int y); /**************************************/ void main() { cout<<"Enter x,y : "; cin>>x>>y; cout<<"GCD of ("<<x<<","<<y<<") = "<<GCD(x,y); } /**************************************/ int GCD(int x,int y) { int f1,f2; queue q; emptyQueue(q); enqueue(q,y); enqueue(q,x); while (top(q)!=0) { f1=top(q); dequeue(q); f2=top(q)%f1; dequeue(q); enqueue(q,f2); enqueue(q,f1); } dequeue(q); return top(q); }

Page 57: Algorithms Data Structures 1

–1–الخوارزميات و بنى المعطيات

55 آلية الهندسة المعلوماتية - جامعة البعث

:تمرين

األول لبيع الخبز و الثاني لبيع , بعد دفع الحساب يتم فصل الزبائن إلى طابورين , يصطف عدد من المواطنين أمام فرن لبيع الخبز و الفطائر و . لكل زبون) عدد الفطائر /عدد األرغفة( و الكمية ) فطائر/خبز(علماً أنه يجب معرفة نوع الطلب , حسب الدورو يتم البيع . الفطائر :المطلوب

) .باستخدام المؤشرات ( اكتب تمثيالً تعبر فيه عما سبق -1 .اكتب خوارزمية تقوم بفصل الطابور الرئيسي إلى طابورين حسب نوع الطلب -2 .اكتب خوارزمية تقوم بحساب الكمية التي باعها صاحب الفرن من الخبز أو الفطائر -3 :الحل

struct node{ char kind; // ‘0’= bread , ‘1’= pie int num; node* next; }; struct Queue{ node *top,*tail; }; /***************************************************************************************/ void sort(Queue q,Queue &qB,Queue &qP) { Queue h; while (isEmpty(q)==’n’) { h=top(q); if (h->kind==’0’) // = bread enqueue(qB,h); else enqueue(qP,h); // = pie dequeue(q); } } /***************************************************************************************/ void amount(Queue q,int &am) { Queue h; while (isEmpty(q)==’n’) { h=top(q); am+=h->num; dequeue(q); } }

:تمرينحتى ... طباعة العقد بدءاً من الجذر ثم تمشيط عقد المستوي األول ثم الثاني أي( اكتب خوارزمية لطباعة شجرة ثنائية على شكل مستويات

) .المستوي األخير :الحل

void print(BTree b) { Queue q; emptyQueue(q); if (b!=0) { enqueue(q,b); while (isEmpty(q)==’n’) { b=Top(q); dequeue(q); cout<<b->val; if (b->l!=0) enqueue(q,b->l); if (b->r!=0) enqueue(q,b->r); } } }

Page 58: Algorithms Data Structures 1

–1–الخوارزميات و بنى المعطيات

56 آلية الهندسة المعلوماتية - جامعة البعث

:تمرين

) .isPerfect( اكتب خوارزمية للتحقق من كون شجرة بحث ثنائي هي كاملة أم ال char isPerfect(BTree b) { Queue q; emptyQueue(q); char c=’n’; if (b!=0) enqueue(q,b); while (isEmpty(q)==’n’) { b=Top(q); dequeue(q); if (b==0) c=’y’; else if (c==’y’) return ‘n’; if (b!=0) { enqueue(q,b->l); enqueue(q,b->r); } } return ‘y’; }

Page 59: Algorithms Data Structures 1

–1–الخوارزميات و بنى المعطيات

57 آلية الهندسة المعلوماتية - جامعة البعث

تحويل الخوارزميات العودية إلى خوارزميات تكرارية

:الطريقة العامة لحذف االستدعاء العودي غير المتطرف -2

.نقول عن استدعاء عودي أنه غير متطرفًا إذا آان يوجد بعد هذا االستدعاء تعليمة واحدة على األقل

آتل من التعليمات و حيث أن هنا ال توجد C و B و A, ليس متطرفًا ( )Pحيث أن االستدعاء العودي (إن الشكل العام للتحويل آالتالي ) :وسطاء تمرير لإلجراء

لذلك يمكن تحديد , فإذًا يتم في آل استدعاء عودي إعادة تنفيذ التعليمات نفسها تمامًا دون أي فرق ) معطيات جديدة(= طالما ال توجد وسطاء تمرير labelو لكن بما أننا نذهب في آل مرة إلى هذا الـ , سب المسألة المطروحة في نقطة معينة تناlabel مقابل آل استدعاء عودي فمن المستحيل

, ) B( تقطع لنا في آل مرة الطريق الواصل إلى تلك التعليمات gotoألن تعليمة ) B (متابعة تنفيذ التعليمات الموجودة ما بعد االستدعاء العودي ( ألول مرة بعد أن نصل إلى شرط التوقف ) B(من الواضح أنه يجب تنفيذ . آخر يعطي مكان هذه التعليمات المقطوعةlabelة لذلك يجب إضاف

لذلك قمنا بإضافة عداد في , يتوقف على عدد االستدعاءات العودية ) B(عدد مرات تنفيذ !!! ) . التي ال تنفذ إال مرة واحدة فقط ) C(أي بعد تنفيذ .فذ بقيمة العداد مرة تن) B(لخوارزمية يقوم بعملية العد و بالتالي فإن بداية ا

طريقة ثانية للحذف حذف االستدعاء العودي الخوارزمية بشكل عودي

void P() { if (condition) { A ; P(); B ; } else C ; }

Void P() { int i=0; Start: if (condition) { A ; ++i; goto Start; L1: B ; --i; } else C ; if (i>0) goto L1; }

void P() { int i=0; while (condition) { A ; ++i; } C; while (i>0) { B ; --i; } }

باإلضافة إلى مكدسًا نضع فيه أرقامًا , و توزيعها بالشكل المناسب labels في حال وجود عدة استدعاءات عودية يمكن استخدام عدة :مالحظة

.و نستعمل هذه القيم في تحديد آخر استدعاء مؤجل , تدل على االستدعاءات العودية فإذا , إن في آل استدعاء عودي يتم تنفيذ التعليمات نفسها و لكن من أجل معطيات مختلفة عندما توجد وسطاء تمرير للتابع العودي ف:مالحظة

يجب علينا حفظ هذه المعطيات قبل تغييرها من أجل إمكانية استرجاعها أثناء , آان لدينا تعليمات ما بعد االستدعاء العودي متعلقة بهذه المعطيات و إنما يمكن استخدام مفهوم , إذًا هنا ال يكفينا عداد يقوم بعد عدد مرات االستدعاءات العودية . أب طريق العودة من استدعاء ابن إلى استدعاء

:إن المثال التالي يبين هذه الفكرة . المكدسات لتخزين المعطيات مؤقتًا فيها

) .معتمدًا مفهوم المكدسات ( اآتب خوارزمية غير عودية لمسألة أبراج هانوي :مثال :الحل

#include <iostream.h> #include "Stack_P.h" // name of Stack = stack , val = int #include "Stack_PC.h" // name of Stack = Cstack , val = char /***************************************************************************************/ void Hanoi(int n,char a,char b,char c) { stack sN; Cstack sA,sB,sC; char aux; emptyStack(sN); emptyStack(sA); emptyStack(sB); emptyStack(sC); start: if (n==1) cout<<a<<" --> "<<c<<endl; else { push(sN,n); push(sA,a); push(sB,b); push(sC,c); --n;

Page 60: Algorithms Data Structures 1

–1–الخوارزميات و بنى المعطيات

58 آلية الهندسة المعلوماتية - جامعة البعث

aux=b; b=c; c=aux; goto start; L: cout<<a<<" --> "<<c<<endl; --n; aux=a; a=b; b=aux; goto start; } if (isEmpty(sN)=='n') { n=top(sN); pop(sN); a=top(sA); pop(sA); b=top(sB); pop(sB); c=top(sC); pop(sC); goto L; } }

:تمرين

.PostOrder اكتب خوارزمية تكرارية لطباعة شجرة ثنائية بالترتيب الملحق :الحل

void printPostOrder(BTree b) { Stack s1,s2,s3; emptyStack(s1); emptyStack(s2); emptyStack(s3); start: if (b!=0) { push(s1,b); push(s3,b); b=b->L; goto start; L1: push(s2,b); b=b->R; goto start; L2: cout<<b->val; } if ((isEmpty(s2)==’n’)&&(top(s2)==(top(s3)) { b=top(s2); pop(s2); pop(s3); goto L2; } if (isEmpty(s1)==’n’) { b=top(s1); pop(s1); goto L1; } }

Page 61: Algorithms Data Structures 1

–1–الخوارزميات و بنى المعطيات

59 آلية الهندسة المعلوماتية - جامعة البعث

:مقدمة

والتي يمكن , ) Non Sequential Structures( أي غير خطية بنى المعطيات غير التسلسليةإن األشجار هي نوع من أنواع :تعريفها كما يلي

).قد توجد عالقة ترتيب جزئي بين عناصر بعض البنى غير التسلسلية ( هي البنى التي ال توجد عالقة ترتيب كلي بين عناصرها ) :Tree( الشجرة تعريف-

(و منظمة تنظيماً هرمياً , links بروابطومرتبطة بعضها ببعض , nodes عقداًهي مجموعة من العناصر نسميها Hierarchical ( ال يحوي حلقاتcycles الجذرأي أنه توجد عقدة مميزة و وحيدة نسميها , مغلقة root , يمكن بواسطتها الوصول إلى

...و من هذه العقد إلى عقد أخرى و هكذا , جموعة من العقد محيث تنظم الملفات في مجلدات , نظراً لكثرة استعمالها في نظم االستثمار خاصة , تعتبر البنى الشجرية من البنى المميزة في مجال المعلوماتية

.يحوي كل منها مجموعة من المجلدات الجزئية و مجموعة من الملفات :مثلة على األشجار أ-

:تمثيل نتيجة دوري كرة القدم باستخدام شجرة ثنائية

:تمثيل عبارة حسابية باستخدام شجرة ثنائية

.Generalized Trees و األشجار المعممة Binary Treesمن أهم أنواع األشجار لدينا األشجار الثنائية

: Trees Binary - الثنائية األشجار

.و هي األشجار التي يكون فيها لكل عقدة ابنان على األكثر

:تعاريف : تحقق أحد الشرطين التاليين Bنسمي شجرة ثنائية كل بنية :1تعريف

B = Ф ) الشجرة فارغة( B = < O,B1,B2 > حيث O عقدة نسميها الجذر .B2 , B1 نسمي . شجرتان ثنائيتان منفصلتانB1لشجرة ا

. الشجرة الجزئية اليمينية B2الجزئية اليسارية و

Tree Structures–البنى الشجرية

الوثبةالكرامة

الحكمةالشرطة

االتحاد جبلة

الكرامة الوثبة

الوثبةالكرامة

الكرامة

5 2 y x

+ -

/ *

+

x z

((2+y)*(x-5))+(z/x)

Page 62: Algorithms Data Structures 1

–1–الخوارزميات و بنى المعطيات

60 آلية الهندسة المعلوماتية - جامعة البعث

:2تعريف

و نقول إنه يوجد اتصال يساري , O االبن األيمن لـ B2و جذر الشجرة الجزئية , O االبن األيسر لـ B1نسمي جذر الشجرة الجزئية

.بين الجذر و االبن األيسر و اتصال يميني بين الجذر و االبن اليميني

:3تعريف

.إذا كان لهما األب نفسه, نقول عن عقدتين أنهما أختان . لَف و حفيد س, أخ , ابن , أب : يمكن أن توجد بين العقد العالقات التالية

. njسلفاً ألب niأو كانت , nj أباً لـ niإذا و فقط إذا كانت , njلعقدة ) Ancestor( أنها سلف niنقول عن عقدة

. njاً البن حفيدniأو كانت , nj ابناً لـ niإذا و فقط إذا كانت , njلعقدة ) Grandchild( أنها حفيد niول عن عقدة نق

:4تعريف

:لكل عقدة في شجرة ثنائية ولدان على األكثر

.أو اختصاراً عقداً , ) Internal Nodes(نسمي العقد التي لها ولد على األقل عقداً داخلية ) .Leafs(أو أوراق , ) External Nodes(نسمي العقد التي ليس لها أوالد عقداً خارجية :5تعريف

.و نسمي فرعاً في الشجرة كل طريق يصل بين الجذر و إحدى األوراق , ضمن شجرة ثنائية كل متتالية من العقد ) Path(نسمي طريقاً

5 2 y x

+ -

/ *

+

x z

O root / جذر

المستوي األول

المستوي الثاني

المستوي الثالث

B1 الشجرة الجزئية اليسارية

|| Oيسر لـ االبن األ

|| يوجد اتصال يساري بين

الجذر و االبن األيسر

B2 الشجرة الجزئية اليمينية

||

Oاالبن األيمن لـ ||

يوجد اتصال يميني بين

الجذر و االبن األيمن )ورقة(عقدة خارجية

External Node (leaf) ليس لها أوالد

)عقدة(عقدة داخلية Internal Node

لها ولد واحد على األقل

n1

n2 n3

n4 األخ

االبن

األب

االبن

الحفيد

Page 63: Algorithms Data Structures 1

–1–الخوارزميات و بنى المعطيات

61 آلية الهندسة المعلوماتية - جامعة البعث

:سات على األشجار الثنائية بعض القيا

: عقدة في هذه الشجرة xشجرة ثنائية و Bبفرض أن

D(B) 1درجة الشجرة D(B) = 2 درجة شجرة ثنائية العدد األعظم ألوالد عقدة

Vol(empty tree) = 0 عدد عقدها Vol( < O,B1,B2 > ) = 1 + Vol(B1) + Vol(B2)

Vol(B) 2حجم الشجرة

عدد االتصاالت في الطريق الواصل بين هذه العقدة و الجذر h(x) = 0 ; x = root

h(x) = 1 + h(y) ; y = father of x h(x) 3ارتفاع عقدة

H(B) 4ارتفاع الشجرة H(B) = max{ h(x) ; x is a node of B }: أطول ارتفاع عقدة في الشجرة

L(B) 5عرض الشجرة العدد األعظم للعقد في مستوي ما

LC(B) = Σ h(x) ; x is a node of B: مجموع ارتفاعات عقدها مسافة التجول ضمن

LC(B)شجرة 6

LCI(B) = Σ h(x) ; x = internal node of B: مجموع ارتفاعات عقدها الداخلية مسافة التجول الداخلي

LCI(B)ضمن شجرة 7

LCE(B) = Σ h(x) ; x = external node of B: مجموع ارتفاعات أوراقها مسافة التجول الخارجي

LCE(B)ضمن شجرة 8

:فنالحظ أن , التالي الشجرة الثنائية المبينة في الشكل B لتكن :مثال

Root(B) = n1 Left Son (n1) = n2 Right Son (n1) = n4 Leafs = { n8 , n10 , n5 , n9 } Internal Nodes = { n1 , n2 , n3 , n4 , n6 , n7 } h(n1) = 0 , h(n2) = h(n4) = 1 , h(n3) = h(n5) = h(n7) = 2 h(n6) = h(n9) = 3 , h(n8) = h(n10) = 4 H(B) = 4 L(B) = 3 LC(B) = 22 LCI(B) = 9 LCE(B) = 13

LC(B) = LCI(B) + LCE(B) نالحظ أن :مالحظة

:بعض األشجار الثنائية الخاصة .لكل عقدة ولد واحد على األكثر ) :Linear( الشجرة الثنائية الخطية -1 عقدة واحدة 0لمستوي في ا ) :Complete( الشجرة الثنائية التامة -2

عقدتان 1 في المستوي

عقد 4 2 في المستوي

عقدةk 2k في المستوي

h : Vol(B) = 1 + 2 + 4 + ..... + 2h = 2h+1 - 1 التي ارتفاعها Bالعقد في الشجرة عدد

.أي أن جميع المستويات مملوءة تماماً بالعقد

n1

n4

n3 n5 n7

n6 n9

n8 n10

n2

Page 64: Algorithms Data Structures 1

–1–الخوارزميات و بنى المعطيات

62 آلية الهندسة المعلوماتية - جامعة البعث

) :Perfect( الشجرة الثنائية الكاملة -3

, ما عدى المستوي األخير الذي يمكن أن يحوي فراغات , جميع المستويات مملوءة تماماً بالعقد

.و في هذه الحالة تكون الفراغات دوماً في جهة اليمين :Binary Search Trees أشجار البحث الثنائي - 4

هي أشجار ال تتضمن قيماً مكررة حيث أن العقد الموجودة على الطرف األيسر ألية شجرة جزئية هي عقد ذات قيم أصغر من قيمة العقدة

توضع القيم : أو بالعكس ( على الطرف األيمن ألية شجرة جزئية تكون قيمها أكبر من قيمة العقدة األب لها و العقد الموجودة , األب لها

) .الصغيرة على الطرف األيمن و القيم الكبيرة على الطرف األيسر

: لنشكل من القيم التالية شجرة بحث ثنائي :1مثال { 47 , 25 , 77 , 11 , 43 , 93 , 65 , 31 , 17 , 7 , 44 , 68 }

: لنشكل من القيم التالية شجرة بحث ثنائي :2مثال { 6 , 4 , 5 , 10 , 2 , 1 , 0 , 11 }

:بعض النظريات الخاصة باألشجار الثنائية

: عندئذ يكون , H و ارتفاعها n شجرة ثنائية حجمها B إذا كانت :1نظرية

.x هو أكبر عدد صحيح أصغر من حيث

. أكبر أو يساوي Hيكون ارتفاعها , ورقة f غير فارغة ذات B كل شجرة ثنائية :نتيجة

: . ورقة يكون f و تحوي nفي كل شجرة ثنائية حجمها :مالحظة

: بالمتراجحة Bيمكن حصر مسافة التجول في . n شجرة ثنائية حجمها B لتكن :2نظرية

.n2تكون في أحسن األحوال من مرتبة و في أسوأ األحوال , n مسافة التجول في شجرة ثنائية حجمها :نتيجة

.: يكون االرتفاع الوسطي لألوراق , ورقة f شجرة ثنائية تحوي B لتكن :3نظرية

44

25 77

11 43 65 93

31

47

7 17 68

⎣ ⎦x⎣ ⎦ 12 −≤≤ nHnLog

⎣ ⎦fLog 2

21+

≤nf

⎣ ⎦ 2)1()(

12

−≤≤∑

=

nnBLCkLogn

knLogn 2⋅

fBPF 2log)( ≥

4 10

2 5 11

6

1

0

Page 65: Algorithms Data Structures 1

–1–الخوارزميات و بنى المعطيات

63 آلية الهندسة المعلوماتية - جامعة البعث

:تمثيل األشجار الثنائية

.إما باستخدام المصفوفات أو باستخدام المؤشرات , يمكن تمثيل األشجار بطريقتين

:كل عقدة تُمثل بسجل من الشكل : تمثيل األشجار الثنائية باستعمال المؤشرات -1

مؤشر إلى الشجرة الجزئية اليساريةLحيث

Rلشجرة الجزئية اليمينية مؤشر إلى ا

) .أي الجذر ( هي عبارة عن مؤشر إلى العقدة األولى bو بالتالي فإن الشجرة

:مثال : تمثيل األشجار الثنائية باستعمال المصفوفات -2

حيث يتم ترقيم العقد , رقم االبن اليميني رقم االبن اليساري و , نعرف مصفوفة فيها ثالثة أعمدة بحيث يحوي كل سطر فيها معلومات العقدة

:كما يلي

و بالتالي نستنتج . هو رقم االبن اليميني 2n+1و , هو رقم االبن اليساري 2nفإن , رقم العقدة nإذا كان : ترقيم العقد ضمن شجرة ثنائية

.m/2 هو العقدة رقم mأن أبا عقدة رقمها

const n=100; struct node { element val; // int , char , float , ... int L,R; }; typedef node BTable[n]; struct TabBTree { int root; BTable tab; }; TabBTree b;

struct node { element val; // int , char , ... node *L,*R; }; typedef node* BTree; BTree b;

a

C

d k L

e m

f G

b

a

b ×

×××

× ×k

C

×L

××me

f

×d

×G×

b

n

2n+12n

Page 66: Algorithms Data Structures 1

–1–الخوارزميات و بنى المعطيات

64 آلية الهندسة المعلوماتية - جامعة البعث

: لنمثل نفس الشجرة السابقة باستخدام المصفوفات :مثال

1 a 2 3 2 b 4 - 3 C 6 7 4 d - 9 5 - - - 6 k - - 7 L 14 - 8 - - - 9 e 18 19 - - - -

14 m - - - - - -

18 f - - 19 G - -

:- Traversalالتجول ضمن شجرة الثنائية

.تهدف عملية التجول إلى المرور بكل عقدة من عقد الشجرة حسب ترتيب معين بهدف إجراء معالجة معينة عليها

:و هي كالتالي , نائية توجد ثالثة طرق للتجول ضمن شجرة ث

ثم الفرع اليساري و ثم الفرع اليميني, يأتي الجذر أوالً : Preorderالتجول حسب الترتيب المصدر -

ثم الجذر و ثم الفرع اليميني , يأتي الفرع اليساري أوالً : Inorderالتجول حسب الترتيب النظامي -

ثم الفرع اليميني و ثم الجذر , الفرع اليساري أوالً يأتي : Postorderالتجول حسب الترتيب الملحق -

:لتكن لدينا الشجرة الثنائية التالية و لنكتب محتويات هذه الشجرة بالطرق الثالثة : مثال

Preorder : { a , b , d , e , f , G , C , k , L , m } Inorder : { d , f , e , G , b , a , k , C , m , L } Postorder : { f , G , e , d , b , k , m , L , C , a }

1root

a

C

d k L

e m

f G

b

Page 67: Algorithms Data Structures 1

–1–الخوارزميات و بنى المعطيات

65 آلية الهندسة المعلوماتية - جامعة البعث

:تمرين

حساب عدد األوراق في شجرة بحث ثنائي) 2حساب عدد العقد الداخلية في شجرة بحث ثنائي ) 1 :اكتب خوارزمية لكل مما يلي

حساب مسافة التجول في شجرة بحث ثنائي) 5ي حساب عرض شجرة بحث ثنائ) 4حساب ارتفاع شجرة بحث ثنائي )3

طباعة عقد شجرة ) 8حساب مسافة التجول الخارجي في شجرة بحث ثنائي ) 7حساب مسافة التجول الداخلي في شجرة بحث ثنائي )6

الترتيب الملحق طباعة عقد شجرة بحث ثنائي ب) 10طباعة عقد شجرة بحث ثنائي بالترتيب المصدر ) 9بحث ثنائي بالترتيب النظامي

طباعة طريق عقدة في شجرة بحث ثنائي ) 13طباعة أوراق شجرة بحث ثنائي فقط ) 12طباعة عقد شجرة بحث ثنائي الداخلية فقط ) 11

التحقق من كون شجرة بحث ) 16التحقق من كون شجرة بحث ثنائي هي تامة ) 15التحقق من كون شجرة بحث ثنائي هي خطية ) 14

املةثنائي هي ك

:الحل#include <iostream.h> #include <conio.h> // --> clrscr() , getch() , getche() #include <ctype.h> // --> toupper() #include <stdlib.h> // --> _exit(0) (= exits the program and closes the window) #include <math.h> // --> pow() #include "Queue_pBTree.h" // for is_perfect const m=100; struct node{ int val; node *l,*r; }; typedef node* BTree; BTree b=0,q=0; int n,i,maxH; int a[m]; // for width char c; // = choice of user char menu(); void insertNode(BTree &b,int n); void print(BTree b); // choices of print void printInfix(BTree b); void printPrefix(BTree b); void printPostfix(BTree b); void printInternal(BTree b); void printLeaf(BTree b); void printPath(BTree b,int n); int internalNum(BTree b); int leafNum(BTree b); void treeHeight(BTree b,int h,int &maxH); void fillLevels(BTree b,int a[],int i); // for width int width(BTree b); int nodeHeight(BTree b,int x); int LC(BTree b,BTree k); int LCI(BTree b,BTree k); int LCE(BTree b,BTree k); char isLinear(BTree b); char isComplete(BTree b); char isPerfect(BTree b); /***************************************************************************************/ void main() { do{ clrscr(); c=menu(); switch (c){ case '1':{cout<<"\n\nEnter the value to insert , val = "; cin>>n; insertNode(b,n);

Page 68: Algorithms Data Structures 1

–1–الخوارزميات و بنى المعطيات

66 آلية الهندسة المعلوماتية - جامعة البعث

break; } case '2':{print(b); break; } case '3':{if ((b==0)||((b->l==0)&&(b->r==0))) cout<<"\n\nThere are no internal nodes ! \n"; else printInternal(b); break; } case '4':{if (b==0) cout<<"\n\nThere are no external nodes ! \n"; else printLeaf(b); break; } case '5':{cout<<"\nEnter the node you want to see its path , n = "; cin>>n; printPath(b,n); break; } case '6':{cout<<"\nThis tree contains "<<internalNum(b)<<" internal nodes\n"; break; } case '7':{n=0; cout<<"\nThis tree contains "<<leafNum(b)<<" leaves !\n"; break; } case '8':{maxH=0; treeHeight(b,0,maxH); cout<<"\nThe height of this tree is H(B)= "<<maxH<<endl; break; } case '9':{cout<<"\nThe width of this tree = "<<width(b); break; } case 'M':{cout<<"\nLC(B) = "<<LC(b,b); break; } case 'I':{cout<<"\nLCI(B) = "<<LCI(b,b); break; } case 'E':{cout<<"\nLCE(B) = "<<LCE(b,b); break; } case 'L':{if (isLinear(b)=='y') cout<<"\nYes , this tree is linear !\n"; else cout<<"\nNo , this tree isn't linear !\n"; break; } case 'C':{if (isComplete(b)=='y') cout<<"\nYes , this tree is complete !\n"; else cout<<"\nNo , this tree isn't complete!\n"; break; } case 'P':{ if (isPerfect(b)=='y') cout<<"\nYes , tree is perfect !\n"; else cout<<"\nNo , this tree isn't perfect !\n"; break; } case '0': _exit(0); } // end of switch getch(); } while (c!=0); } /***************************************************************************************/

Page 69: Algorithms Data Structures 1

–1–الخوارزميات و بنى المعطيات

67 آلية الهندسة المعلوماتية - جامعة البعث

char menu() { char ch; do{ clrscr(); cout<<"0: Exit \n"; cout<<"1: Insert Node \n"; cout<<"2: Print Tree \n"; cout<<"3: Print Internal Nodes \n"; cout<<"4: Print External Nodes (Leafs)\n"; cout<<"5: Print Path Of A Node \n"; cout<<"6: Number Of Internal Nodes \n"; cout<<"7: Number Of External Nodes \n"; cout<<"8: Height Of Tree \n"; cout<<"9: Width Of Tree \n"; cout<<"M: LC Of Tree \n"; cout<<"I: LCI Of Tree \n"; cout<<"E: LCE Of Tree \n"; cout<<"L: Is The Tree Linear ? \n"; cout<<"C: Is The Tree Complete ? \n"; cout<<"P: Is The Tree Perfect ? \n\n"; cout<<"Enter your choice : "; ch=getche(); cout<<endl; ch=toupper(ch); } while (((ch!='M')&&(ch!='I')&&(ch!='E')&&(ch!='L')&&(ch!='C')&&(ch!='P'))&& ((int(ch)<48)||(int(ch)>57))); return ch; } /***************************************************************************************/ void insertNode(BTree &b,int n) { if (b==0) { b=new node; b->val=n; b->l=0; b->r=0; } else if (n<b->val) insertNode(b->l,n); else insertNode(b->r,n); } /***************************************************************************************/ void print(BTree b) { char p; do{ clrscr(); cout<<"1: Print Infix-Traversal \n"; cout<<"2: Print Prefix-Traversal \n"; cout<<"3: Print Postfix-Traversal \n\n\n"; cout<<"Enter your choice : "; p=getche(); cout<<endl; } while ((p!='1')&&(p!='2')&&(p!='3')); if (b==0) cout<<"\n\nThis tree is empty ... , press any key to continue ... \n"; else if (p=='1') printInfix(b); else if (p=='2') printPrefix(b); else printPostfix(b); } /***************************************************************************************/ void printInfix(BTree b) { if (b!=0) { printInfix(b->l); cout<<b->val<<" "; printInfix(b->r); } }

Page 70: Algorithms Data Structures 1

–1–الخوارزميات و بنى المعطيات

68 آلية الهندسة المعلوماتية - جامعة البعث

/***************************************************************************************/ void printPrefix(BTree b) { if (b!=0) { cout<<b->val<<" "; printPrefix(b->l); printPrefix(b->r); } } /***************************************************************************************/ void printPostfix(BTree b) { if (b!=0) { printPostfix(b->l); printPostfix(b->r); cout<<b->val<<" "; } } /***************************************************************************************/ void printInternal(BTree b) { if ((b!=0)&&((b->l!=0)||(b->r!=0))) { cout<<b->val<<" "; if (b->l!=0) printInternal(b->l); if (b->r!=0) printInternal(b->r); } } /***************************************************************************************/ void printLeaf(BTree b) { if (b!=0) { if ((b->l==0)&&(b->r==0)) cout<<b->val<<" "; else { if (b->l!=0) printLeaf(b->l); if (b->r!=0) printLeaf(b->r); } } } /***************************************************************************************/ void printPath(BTree b,int n) { BTree t=b; cout<<"\nPath of "<<n<<" is : "; while ((t!=0)&&(t->val!=n)) { cout<<t->val<<" "; if (n<t->val) t=t->l; else t=t->r; } if (t!=0) cout<<t->val<<endl; else cout<<"The node "<<n<<" doesn’t exist ! \n"; } /***************************************************************************************/ int internalNum(BTree b) { if ((b!=0)&&((b->l!=0)||(b->r!=0))) return 1+internalNum(b->l)+internalNum(b->r); else return 0; }

Page 71: Algorithms Data Structures 1

–1–الخوارزميات و بنى المعطيات

69 آلية الهندسة المعلوماتية - جامعة البعث

/***************************************************************************************/ int leafNum(BTree b) { if (b==0) return 0; else { if ((b->l==0)&&(b->r==0)) return 1; else return leafNum(b->l)+leafNum(b->r); } } /***************************************************************************************/ void treeHeight(BTree b,int h,int &maxH) { if ((b==0)||((b->l==0)&&(b->r==0))) { if (h>maxH) maxH=h; } else { treeHeight(b->l,h+1,maxH); treeHeight(b->r,h+1,maxH); } } /***************************************************************************************/ void fillLevels(BTree b,int a[],int i) { if (b!=0) { ++a[i]; if (b->l!=0) fillLevels(b->l,a,i+1); if (b->r!=0) fillLevels(b->r,a,i+1); } } /***************************************************************************************/ int width(BTree b) { int H=0; treeHeight(b,0,H); for (i=0;i<=H;i++) a[i]=0; fillLevels(b,a,0); int wid=a[0]; for (i=1;i<=H;i++) if (a[i]>wid) wid=a[i]; return wid; } /***************************************************************************************/ int nodeHeight(BTree b,int x) { BTree t=b; int h=0; while ((t!=0)&&(t->val!=x)) { ++h; if (x<t->val) t=t->l; else t=t->r; } if (t!=0) return h; else return 0; } /***************************************************************************************/ int LC(BTree b,BTree k) { if (k!=0) return nodeHeight(b,k->val)+LC(b,k->l)+LC(b,k->r); else return 0; } /***************************************************************************************/ int LCI(BTree b,BTree k) { if ((k!=0)&&((k->l!=0)||(k->r!=0))) return nodeHeight(b,k->val)+LCI(b,k->l)+LCI(b,k->r); else return 0; } /***************************************************************************************/

Page 72: Algorithms Data Structures 1

–1–الخوارزميات و بنى المعطيات

70 آلية الهندسة المعلوماتية - جامعة البعث

int LCE(BTree b,BTree k) { if (k!=0) if ((k->l==0)&&(k->r==0)) return nodeHeight(b,k->val); else return LCE(b,k->l)+LCE(b,k->r); else return 0; } /***************************************************************************************/ char isLinear(BTree b) { if (b==0) return 'y'; else if ((b->l!=0)&&(b->r!=0)) return 'n'; else if (b->l!=0) return isLinear(b->l); else return isLinear(b->r); } /***************************************************************************************/ char isComplete(BTree b) { int H=0; treeHeight(b,0,H); for (i=0;i<=H;i++) a[i]=0; fillLevels(b,a,0); char q='y'; for (i=0;i<=H;i++) if (a[i]!=pow(2,i)) { q='n'; break; } return q; } /***************************************************************************************/ char isPerfect(BTree b) { Queue q; emptyQueue(q); char c=’n’; if (b!=0) enqueue(q,b); while (isEmpty(q)==’n’) { Top(q); dequeue(q); if (b==0) c=’y’; else if (c==’y’) return ‘n’; if (b!=0) { enqueue(q,b->l); enqueue(q,b->r); } } return ‘y’; }

Page 73: Algorithms Data Structures 1

–1–الخوارزميات و بنى المعطيات

71 آلية الهندسة المعلوماتية - جامعة البعث

: تمرين

!) .ليس من الضرورة أن تكون األشجار مرتبة ( اكتب خوارزمية تقوم بالتحقق من كون شجرتين متساويتين أم ال :الحل

char equal(BTree b1,BTree b2) { if ((b1==0)&&(b2==0)) return 'y'; else if (((b1==0)&&(b2!=0))||((b1!=0)&&(b2==0))) return 'n'; else if (b1->val!=b2->val) return 'n'; else { char q; q=equal(b1->l,b2->l); if (q=='y') q=equal(b1->r,b2->r); return q; } }

:تمرين

.اكتب خوارزمية حذف عقدة من شجرة بحث ثنائي

.ء شجرة جديدة بحيث نقوم بنقل جميع عقد الشجرة األصلية ما عدى العقدة المراد حذفها يمكن إنشا:الحلvoid deleteNode(BTree b,int x,BTree &b2) { if (b!=0) { if (b->val!=x) insertNode(b2,b->val); if (b->l!=0) deleteNode(b->l,x,b2); if (b->r!=0) deleteNode(b->r,x,b2); } }

.b إلى القديمة b2و من ثم نقوم بإسناد الشجرة الجديدة

: تمرين

:المطلوب).كما في الشكل التالي (B2 تحوي كامل B1 إذا كانت B1 إنها جزئية من شجرة ثنائية أخرى B2نقول عن شجرة ثنائية

.B1 جزئية من شجرة أخرى B2اكتب إجرائية تتحقق من كون شجرة -1

.B1 في B2اكتب إجرائية تقوم بحساب تكرار وجود -2

:يمكن دمج الطلبين بكتابة الخوارزميتين التاليتين : الحل

char equal(BTree b1,BTree b2) { if (b2==0) return 'y'; else if ((b1==0)&&(b2!=0)) return 'n'; else if ((b1->val!=b2->val)) return 'n'; else { char q=equal(b1->l,b2->l);

3

6 7

B2 1

2 3

4 5 6 7

B1

Page 74: Algorithms Data Structures 1

–1–الخوارزميات و بنى المعطيات

72 آلية الهندسة المعلوماتية - جامعة البعث

if (q=='y') q=equal(b1->r,b2->r); return q; } } /***************************************************************************************/

void frequency(BTree b1,BTree b2,int &n) // عدد تكرار الوجود { if (b1!=0) { if (equal(b1,b2)=='y') ++n; frequency(b1->l,b2,n); frequency(b1->r,b2,n); } } /***************************************************************************************/

:حيث نستدعي في البرنامج الرئيسي كالتالي int n=0; frequency(b1,b2,n); if (n>0) cout<<"b2 is part of b1 "<<n<<" times "; else cout<<"b2 is not part of b1 ";

: تمرين

أو إذا كانتا غير فارغتين و الشجرة الجزئية , إذا كانتا فارغتين معاً ) Mirror Similar(أنهما متشابهتان بالتعاكس نقول عن شجرتين ثنائيتين

اكتب خوارزمية تتحقق من كون ) . كما في الشكل التالي(ليسارية من كلتيهما متشابهة بالتعاكس مع الشجرة الجزئية اليمينية من كلتيهما ا

.متشابهتين بالتعاكس , شجرتين ثنائيتين

:الحلchar isMirror(BTree b1,BTree b2) { if ((b1==0)&&(b2==0)) return 'y'; else if (((b1==0)&&(b2!=0))||((b1!=0)&&(b2==0))) return 'n'; else if (b1->val!=b2->val) return 'n'; else { char q; q=isMirror(b1->l,b2->r); if (q=='y') q=isMirror(b1->r,b2->l); return q; }

}

1

2 3

4 5 6 7

1

3 2

7 6 5 4

Page 75: Algorithms Data Structures 1

–1–الخوارزميات و بنى المعطيات

73 آلية الهندسة المعلوماتية - جامعة البعث

:نعرض منها الطريقتين التاليتين , يمكن تمثيل األشجار المعممة بطرق عدة . دة أبناء لكل عقدةالشجرة المعممة هي شجرة يمكن فيها وجود ع

:تمثيل الشجرة المعممة باستعمال مصفوفة من المؤشرات -1 عن كل التي تصدر) درجة الشجرة(= و يعرف عدد أعظمي للمؤشرات , تحوي العقدة الواحدة مصفوفة من المؤشرات للداللة على األوالد

.ثم إن هذا العدد األعظم لألوالد قد يكون غير كاف في بعض الحاالت, بالطبع نالحظ بأن هذا التمثيل يسبب هدر في الذاكرة المحجوزة. عقدة

:مثال

رة باستعمال يمكن تمثيل الشج , 6هي ) العدد األعظم لألوالد(إذا اعتبرنا أن درجة الشجرة , ) 1(لتكن الشجرة المعممة المبينة في الشكل

) :2(كما في الشكل , مصفوفة من المؤشرات

:حيث يتم هنا تعريف بنية الشجرة المعممة بالشكل التالي const n=6; // n = Degree of GTree struct gnode{ element val; // int , char , float , ... gnode* a[n]; }; typedef gnode* GTree;

:تمثيل الشجرة المعممة باستعمال سالسل من األوالد -2ال يوجد ضياع في الذاكرة , في هذه الحالة . يدل األول على الولد األول و يدل المؤشر الثاني على األخ التالي, تحوي العقدة مؤشرين

. و يمكن تخزين الشجرة مهما كان عدد األوالد , المحجوزة

:المث

Generalized Trees –األشجار المعممة

a

b c d

f g e

)1(

شجرة معممة

a

b d c

f g e

)2(

تمثيل شجرة معممة باستخدام مصفوفة مؤشرات

a

b c d

g f e

Page 76: Algorithms Data Structures 1

–1–الخوارزميات و بنى المعطيات

74 آلية الهندسة المعلوماتية - جامعة البعث

أهي أخ أو : و من أجل ذلك نحتاج إلى حقل إضافي لنحدد العقدة التالية , يمكن تعديل هذه الطريقة في التمثيل بجعل آخر ولد يؤشر إلى األب

هذا يعني أن ف" 1"و إذا كانت قيمته , فهذا يعني أن العقدة تؤشر إلى أخ " 0"إذا كانت قيمته , أب ؟ إذاً لنضيف حقل من نوع عدد صحيح

.العقدة تؤشر إلى األب

:مثال

:تحويل شجرة معممة إلى شجرة ثنائية :فيمكن تحويلها إلى شجرة ثنائية بواسطة الخوارزمية التالية , إذا لم يكن هناك ترتيب معرف على أبناء العقد في شجرة معممة

.ري لنفس العقدة في الشجرة الثنائية االبن األول لعقدة في الشجرة المعممة يصبح االبن اليسا •

.أخو عقدة في الشجرة المعممة يصبح االبن اليميني لنفس العقدة في الشجرة الثنائية •

:مثال

:تمرين . باستخدام مصفوفات من المؤشراتgحيث تم تمثيل , gاكتب خوارزمية لطباعة األوراق في شجرة معممة

:الحلvoid printLeafs(Gtree g) { if (g!=0) if (g->a[0]==0) cout<<g->val; else for (int i=0;i<n;i++) printLeafs(g->a[i]); }

a

b c d

e g f

0

0

0 1

1

1

0

a

b c d

f ge

شجرة معممة

a

b

c

d f g

e

شجرة ثنائية مكافئة

Page 77: Algorithms Data Structures 1

–1–الخوارزميات و بنى المعطيات

75 آلية الهندسة المعلوماتية - جامعة البعث

:تمرين

.اكتب خوارزمية التحويل من شجرة معممة إلى شجرة ثنائية :الحل

const n=6; struct node{ int val; node *l,*r; }; typedef node* BTree; struct gnode{ int val; gnode* a[n]; }; typedef gnode* GTree; BTree b=0; GTree g=0; /***************************************************************************************/ void c(GTree g,BTree &b) { if (g->a[0]!=0) { b->l=new node(); b->l->val=g->a[0]->val; b->l->l=0; b->l->r=0; }

else return ; // إنهاء اإلجراء BTree b1=b->l; for (int i=1;i<n;i++) if (g->a[i]!=0) { b1->r=new node(); b1=b1->r; b1->val=g->a[i]->val; b1->l=0; b1->r=0; } else break; b1=b->l; for (i=0;i<n;i++) if (g->a[i]!=0) { c(g->a[i],b1); b1=b1->r; } else break; } /***************************************************************************************/ void convert(GTree g,BTree &b) { if (g!=0) { b=new node(); b->val=g->val; b->l=0; b->r=0; c(g,b); } }

Page 78: Algorithms Data Structures 1

–1–الخوارزميات و بنى المعطيات

76 آلية الهندسة المعلوماتية - جامعة البعث

Graphs –البيانات

.حيث أن األشجار حالة خاصة من البيانات , إن البيانات عبارة عن تعميماً للبنى غير التسلسلية من الناحية النظرية

:Graph -تعريف البيان

<v1,v2>ائيات المرتبة مجموعة منتهية من الثنEو ) vertices (العقد مجموعة منتهية من V حيث <G=<V,Eهو ثنائية

.) edgesأو حافات ( أسهماًتسمى هذه الثنائيات . v1,v2 ∈Vحيث

. إذا وجد سهم بينهما متجاورتاننقول عن عقدتان أنهما

:يوجد نوعين من البيانات

<v,w>=<w,v>: تكون فيها الثنائيات التي تمثل األسهم غير مرتبة) : Undirected Graph( البيانات غير الموجهة -1

<v,w>≠<w,v>: أي , تكون فيها الثنائيات التي تمثل األسهم مرتبة ) : Directed Graph( البيانات الموجهة -2

:مالحظات

.v≠w: سهماً في البيان فإن <v,w>إذا كان

وحيداً على األكثر في حال كون البيان غير و سهماً , بين عقدتين يمكن أن يوجد سهمان موجهان على األكثر في حال كون البيان موجهاً

.موجه

:1مثال

<G : G = <V,Eيان غير الموجه التالي ليكن الب V<G> = {1,2,3,4}

E(G) = {<1,2>,<1,4>,<2,3>,<2,4>,<3,4>}

هم عبارة عنكمثال عملي يمكن أن تمثل كل عقدة محافظة ما و بالتالي لتكون األس

أي إذا وجد, علماً بأن خط نقل باتجاهين ( خطوط النقل الممكنة ما بين المحافظات

خط ما بين محافظة أولى إلى ثانية بالطبيعة يوجد خط من المحافظة الثانية

:أي) إلى األولى

:2مثال

<G2 : G2 = <V,Eيان الموجه التالي ليكن الب V<G2> = {1,2,3,4}

E(G2) = {<1,2>,<2,1>,<2,3>,<3,4>,<4,2>}

عقدة يساوي n يحوي غير موجه عدد الروابط األعظم في بيان :مالحظة2

)1( −nn , بيان تام و بالتالي نقول عن البيان أنه)

complete graph. (

1

2

3

4

1

2

3

4

حمص

حماه دمشق

حلب

1

2

3 4

Page 79: Algorithms Data Structures 1

–1–الخوارزميات و بنى المعطيات

77 آلية الهندسة المعلوماتية - جامعة البعث

:3مثال

<G : G = <V,Eوجه و التام التالي يان غير المليكن الب V<G> = {1,2,3,4}

E(G) = {<1,2>,<1,3>,<1,4>,<2,3>,<2,4>,<3,4>}

:تعريف البيان الجزئي

>′′<هو ثنائية EV : حيث ,- VV ⊆′ and EE ⊆′ - Ewv ′>⊆< , ⇔ Vv ′∈ and Vw ′∈

:تعريف درجة العقدة

Degلذلك نميز ما بين الدرجة الواردة . هي عدد األسهم الواردة إلى هذه العقدة و الصادرة عنها Deg(v)درجة العقدة -(v)درجة و ال

Degالصادرة +

(v).

:مثال

ليكن لدينا البيان الموجه التالي

Deg(x3) = 5 Deg(x4) = 2 Deg(x1) = 1

Deg+

(x1) = 1 Deg+

(x4) =1 Deg+

(x3) = 2

Deg-(x1) = 0 Deg

-(x4) = 1 Deg

-(x3) = 3

) :path(تعريف الطريق

. i ≤ k ≤ j-1 عندما vk+1 و vkحيث يوجد أسهم بين , من العقد vi , vi+1 , ..... , vjالطريق ضمن بيان هو كل متتالية

. إذا لم تتكرر أي عقدة فيه مرتين )elementary(بسيطاً و يكون الطريق

) :cycle(تعريف الحلقة

. في حالة البيان موجه حلقة موجهةو نسميها , vi = vjهي طريق بسيط بحيث

) :strongly connected(تعريف البيان متصل بقوة

v إلى wو طريق من , w إلى v من البيان يوجد طريق من w و vلكل عقدتين

:تمثيل البيانات الموجهة

:يمكن تمثيل بيان موجه بطرق عديدة حيث نذكر منها ثالثة ) :مصفوفة من المتحوالت المنطقية ( تمثيل البيان الموجه باستعمال مصفوفة تجاور -1

نضع في العنصر . األسطر و األعمدة فيها هي أرقام العقد , في هذه الحالة مربعة Adjacency Matrix (M(تكون مصفوفة التجاور

M[i][j] القيمة true ) أو"y ( "عقدة إذا كان يوجد رابط موجه من الvi إلى العقدة vj . على حين نضع القيمةfalse ) أو"n ( " عند

.تصبح هذه المصفوفة متناظرة بالنسبة إلى القطر الرئيسي , نالحظ بأن في حالة البيان غير الموجه . عدم وجود رابط بين العقدتين

:إذاً يصبح التمثيل على الشكل التاليconst n=100; typedef char MGraph[n][n];

x1

x3

x2

x4

1

2

3

4

Page 80: Algorithms Data Structures 1

–1–الخوارزميات و بنى المعطيات

78 آلية الهندسة المعلوماتية - جامعة البعث

:مثال

:يتم تمثيل البيان الموجه المجاور بالشكل التالي

:تمثيل البيان الموجه باستعمال مصفوفة تعطي كلفة قوس -2

إلىفمثالً إذا عدنا , يمكن للبيان الموجه أن يبين كلفة االنتقال من عقدة إلى أخرى

مثال المحافظات و خطوط النقل الممكنة ما بينها فيمكن إضافة البعد ما بين

لنأخذ كمثال. الخ ... , أو الزمن الالزم لالنتقال , أو سعر بطاقة النقل , المحافظات

.المسافات بالكيلومتر

:يمكن أن نبين نوع القرابة ما بين عدة أشخاص : لنأخذ مثال آخر

قيمة كلفة M[i][j]نضع في العنصر . األسطر و األعمدة فيها هي أرقام العقد , في هذه الحالة أيضاً مربعة Mوفة التجاور تكون مصف

عند عدم وجود 1-على حين نضع القيمة . vj إلى العقدة viإذا كان يوجد رابط موجه من العقدة , vj إلى العقدة viاالنتقال من العقدة

إذاً يصبح . تصبح هذه المصفوفة متناظرة بالنسبة إلى القطر الرئيسي , نالحظ أيضاً أنه في حالة البيان غير الموجه . العقدتين رابط بين

:التمثيل على الشكل التاليconst n=100;

typedef int MVGraph[n][n]; // or: float , char , ... حسب نوع الكلفة

:مثال

:يتم تمثيل البيان الموجه المجاور بالشكل التالي

:تمثيل البيان الموجه بواسطة سالسل التجاور -3

شرات بعده هو عدد العقد في نمثل البيان بواسطة شعاع من المؤ, ) Adjacency Lists(في حالة تمثيل البيان بواسطة سالسل التجاور

وفق االتجاه i التي ترتبط بـ j هي مؤشر إلى بداية سلسلة خطية تحوي جميع العقد iخانة كل عقدة . و مرقم حسب أرقام العقد , البيان

i إلى j , و تكون هذه السلسلة مرتبة تصاعدياً حسب أرقام العقد.

:إذاً يصبح التمثيل على الشكل التاليconst n=100; struct vertex{ element val; // element= int , float , char , ... vertex* next; }; typedef vertex* LGraph[n];

n Y Y n Y n n Y n Y n n n n n n

-1 43 18 -1 25 -1 -1 32 -1 57 -1 -1 -1 -1 -1 -1

x0

x2

x1

x3

1

2

3

4

حمص

حماه دمشق

حلب

30

110

200120

350

x0

x2

x1

x3

فواز سعاد

سعيد فاتن

أب

أب

جد

ابنة

أخت

ابنة

x0

x2

x1

x3

25

43 32

57 18

Page 81: Algorithms Data Structures 1

–1–الخوارزميات و بنى المعطيات

79 آلية الهندسة المعلوماتية - جامعة البعث

:مثال

:يتم تمثيل البيان الموجه المجاور بواسطة سالسل التجاور على الشكل التالي

:بعض العمليات على البيانات

:نختار منها العمليات التالية , يوجد عدد كبير من العمليات المهمة التي تجري على البيانات Traversal Graph - البيانات مسح

: مسح البيان غير الموجه -1

Gميع العقد في يعني زيارة ج) Graph Traversal(فمسح هذا البيان . عقدة ما منه v بيان غير موجه و < G = < V , Eبفرض

.العمق أوالً و العرض أوالً : هناك طريقتين للمسح . vالتي يمكن الوصول إليها بطريق من

:Depth First -مسح البيان بالعمق أوالً -1-1

ذا بطريقة عودية ونتابع هك, ثم نختار عقدة مجاورة لها غير ممسوحة بعد , ) حيث يمكن تحديدها حسب الرغبة(يتم مسح عقدة البداية أوالً

نعود إلى آخر عقدة ممسوحة و لها عقد مجاورة لم تمسح بعد , عندما نصل إلى عقدة ليس لها عقد مجاورة غير ممسوحة , ... عند هذه العقدة

.ننتهي عند مسح جميع العقد .

:لتاليلنمثل العقد الممسوحة بالشعاع ا, عقدة البداية v بيان غير موجه و < G = < V , Eبفرض char visited[n];

. عند مسح العقدة’y‘و نغير المحتوى إلى , أي جميع العقد غير ممسوحة , ’n‘حيث نعطي قيم بدائية لجميع عناصر هذا الصف

: pseudocodeلنكتب خوارزمية المسح بالعمق أوالً بلغة الـ char visited[n]; for (int i=0;i<n;i++) visited[i]=’n’;

void DFS(int v) // v = دليل عقدة البداية {

int w; // w = دليل عقدة ما visited[v]=’y’; for (each vertex w adjacent to v) if (visited[w]==’n’) DFS(w); }

:Breadth First -مسح البيان بالعرض أوالً -1-2

من أجل كل عقدة متبقية في ). Queue(ثم نمسح جميع العقد المجاورة لها غير الممسوحة بعد و نضعها في رتل , أوالً يتم مسح عقدة البداية

.ننتهي عندما يفرغ الرتل كاملةً . الرتل نمسح العقد المجاورة لها و نضعها في رتل و هكذا

:كل التالي على الش pseudocodeتصبح خوارزمية المسح بالعرض أوالً بلغة الـ

x0

x2

x1

x3

0

1

2

3

1 2

0 3

1

Page 82: Algorithms Data Structures 1

–1–الخوارزميات و بنى المعطيات

80 آلية الهندسة المعلوماتية - جامعة البعث

void BFS(int v) // v = دليل عقدة البداية { char visited[n];

int w; // w = دليل عقدة ما Queue q; for (int i=0;i<n;i++) visited[i]=’n’; visited[v]=’y’; emptyQueue(q); do{ for (all vertices w adjacent to v) if (visited[w]==’n’) { enqueue(q,w); visited[w]=’y’; } if (isEmpty(q)==’y’) exit; else { v=Top(q); dequeue(q); }

} while (1==1); // exit حلقة النهائية ال تنتهي إال إذا تم تفريغ الرتل و بالتالي نخرج بتعليمة }

: عقدة البداية v1 ليكن لدينا البيان غير الموجه التالي و لتكن :مثال

) : الطواف بالعمق(=نتيجة مسح البيان بالعمق أوالً v1,v2,v4,v8,v5,v6,v3,v7

) :الطواف بالعرض(=ة مسح البيان بالعرض أوالً نتيج v1,v2,v3,v4,v5,v6,v7,v8

: مسح البيان الموجه -2

. ه األسهم الفرق الوحيد هو مراعاة اتجا. ال تختلف طرق المسح و إجرائياتها هنا عن تلك اإلجرائيات المطبقة في مسح البيان غير الموجه

i > باالتجاه j و iيجب أن يكون السهم بين , التي عندها الخوارزمية i المجاورة للعقدة jلذلك عندما يجب أن تمسح الخوارزمية العقدة

, j > , بمعنى آخر يجب أن تنتمي العقدةj إلى Deg+(i) ) و التي نعتبرها هنا مجموعة العقد المجاورة لـiان موجه في حالة بي.(

التي تسمح بالمرور بجميع العقد OrDFSحيث نستخدم هنا اإلجرائية المساعدة , DFSلنأخذ طريقة العمق أوالً و نعيد كتابة الخوارزمية

.التي يمكن الوصول إليها من عقدة معينة و التي لم يسبق المرور فيها )pseudocode(

void DTraversal(Graph G) { char visited[n]; for (int i=0;i<n;i++) visited[i]=’n’; for (i=0;i<n;i++) if (visited[i]==’n’) DFS(i,visited); }

v1

v2 v3

v4

v5v6

v7

v8

Page 83: Algorithms Data Structures 1

–1–الخوارزميات و بنى المعطيات

81 آلية الهندسة المعلوماتية - جامعة البعث

1

3

5

6

7 8

4 2

9

void DFS(int v,char visited[]) { visited[v]=’y’; for (int j=0;j< Deg+(v);j++) if (visited[j]==’n’) DFS(j,visited); }

:مثال

الموضح في الشكل Gعند تطبيق خوارزمية التجول بالعمق أوالً على البيان

:فإن ترتيب المرور في العقد هو, لمجاورا

:أما بالنسبة للتجول بالعرض أوالً يكون ترتيب المرور

:تمرين

.ن كان هذا البيان عبارة عن شجرة ثنائية أم ال اكتب خوارزمية تختبر إ. بيان موجه تم تمثيله باستخدام سالسل التجاور Gليكن

:إذاً , يجب أن يكون لكل عقدة في البيان عقدتان متجاورتان على األكثر ألن نعتبر البيان عبارة عن شجرة ثنائية : الحلconst n=10; srtuct vertex{ int val; vertex* next; }; typedef vertex* LGraph[n]; LGraph G; /***************************************************************************************/ char isBTree(LGraph G) { int sum=0; // اورة لكل عقدةعداد يعد عدد العقد ا vertex *p,*q; // مؤشرين مساعدين إىل عقدة for (int i=0;i<n;i++) { p=G[i]; sum=0; while (p!=0) { ++sum; if (sum>2) return ‘n’; for (j=0;j<n;j++) if (j<>i) { q=G[j]; while (q!=0) { if (q->val==p->val) return ‘n’; q=q->next; } } p=p->next; } } return ‘y’; }

1 , 3 , 2 , 6 , 5 , 7 , 4 , 9 , 8

1 , 3 , 5 , 6 , 7 , 2 , 4 , 9 , 8