Transcript Document
ساختمان داده ها
متغیر :نامی است برای قسمتی از حافظه یا سلولی از حافظه .
تعریف متغیرها در زبان cدو چیز را مشخص می کند .
اول :این که متغیر به چه میزان حافظه نیاز دارد
دوم :رشته بیتی ذخیره شده در آن حافظه چگونه تفسیر میشود .
معموال هر متغیر کاراکتری یک بایت،صحیح دو بایت ،اعشاری چهاربایت و مضاعف double
هشت بایت فضا را اشغال می کند که به آن سایز متغیر می گویند .
برای تعریف اشاره گرها از فرمول روبرو استفاده می کنیم :
; نام * نوع
مثال :
; Char * p
آرایه های یک بعدی:
آرایه ساده ترین ساختمان داده است که در زبان cاز آن استفاده می شود .آرایه انواع مختلفی دارد
ساده ترین نوع آرایه ،آرایه ی یک بعدی است .از دیدگاه تعریف آرایه مجموعه ای محدود از نوع
همگن است .
برای تعریف آرایه از فرمول زیر استفاده می کنیم:
; [تعداد عناصر آرایه] نام آرایه نوع
مثال:
; ]Char x[10
آرایه ها ناحیه ی پیوسته را به خود اختصاص می دهند.
برای بدست آوردن تعداد خانه های آرایه ی یک بعدی از فرمول زیر کمک می گیریم:
+1حد پایین -حد باال
آرایه های دو بعدی:
یک آرایه ی دو بعدی از دیدگاه برنامه نویس شبیه به یک جدول است.میتوان آن را همانند آرایه ای
از آرایه ها تصور کرد ،اما بر خالف تصور برنامه نویس حافظه شکل جدولی ندارد .
مثال:
; ]Char x[3][5
کامپیوتر می بایست دیدگاه منطقی را که حالت جدولی دارد به صورت دیدگاهی فیزیکی در آورد و
آرایه را در سلول های حافظه که به صورت دنباله ای از بایت ها هستند پیاده سازی کند .بدین
منظور به دو روش می تواند عمل کند روش سطری و روش ستونی.
در روش سطری عناصر آرایه سطر به سطر در حافظه قرار می گیرد ودر روش ستونی عناصر
آرایه ستون به ستون در حافظه ریخته می شود.
محاسبه ی آدرس ] X[i,jبه روش سطری
فرض کنید تعداد سطر های آرایه برابر با rowو تعداد ستونها برابر با colباشد .
روش سطری:
X [i] [j]=base + (I *col+i)*size
روش ستونی:
X [i] [j]=base + (j *row+i)*size
: آرایه های سه بعدی
تعداد سطر ها: row
Base + (i*col +j)*size
Col :تعداد ستونها
H : ارتفاع
Base + (k * row * col + I * col + j) * size
k = h X[k][i][j]
I = row
J = col
Base + ( l * h* row * col + k * row *col + I * col +j) * size
L = t X[l][h][i][j]
H=k
I = row
J = col
چند روش مختلف برای ذخیره سازی اعداد در آرایه های سه بعدی
Base +( k+row * col +I *col +j ) *size
Base +( k+row *col + j *row +i) *size
Base ( i * h * col + k * col +j ) *size
Base ( j * h * row +k * row + i) *size
نمایش چند جمله ای ها به کمک آرایه:
چند جمله ای زیر را در نظر بگیرید می توان آنرا به کمک آرایه ها پیاده سازی کرد روشهای مختلفی
برای این کار وجود دارد مثال می توان بزرگترین درجه ای که در چند جمله ای می تواند وجود
داشته باشد به عنوان Maxدرنظر گرفت دراین صورت می توان آرایه ای تعریف کرد که تعداد
سلول های ان برابر با Max+1باشد .
4x^5+3x^2_6x+1
5x^2-7
]A[iاگر درجه چند جمله ای را بدانیم میتوان هر جمله را در آرایه پیاده سازی کرد در واقع ضریب
) X^(n-iخواهد بود.
پس از ذخیره چند جمله ای ها در داخل آرایه ها می توان اعمالی مانند جمع چند جمله ای و ضرب
چند جمله ای را انجام داد .
حاصل جمع دو عبارت باال
4x^5+8x^2-6x-6
روش قبل برای ذخیره سازی چند جمله ای ممکن است مناسب نباشد برای مثال چند جمله ای شما
ممکن است x^1000+1باشد .
روش دیگری نیز برای ذخیره چند جمله ای ها وجود دارد دراین روش از یک آرایه با دو سطر و
kستون استفاده می شود .
نکته k :تعداد کل جمالت تشیکل دهنده ی همه چند جمله ای هاست.
ماتریس پراکنده یا اسپارس:
برای ذخیره ی یک ماتریس M*Nمی توان از یک آرایه ی دو بعدی با mسطر و nستون
استفاده کرد گروهی از ماتریسها وجود دارد که به آن ماتریس خلوت یا اسپارس می گوییم .در این
ماتریس ها اکثریت عناصر مقدار صفر دارند .
از آنجاییکه ماتریس های اسپارس در عمل وجود دارندوبرخی موارد اندازه های آنها بسیار بزرگ
است می بایست روش بهینه تری را برای ذخیره آنها در کامپیوترارائه کنیم .یک روش آن است
که ازیک آرایه دو بعدی با سه ستون استفاده کنیم .ستون های اول و دوم این آرایه موقعیت
سطروستون مقداردر ماتریس اسپارس رانشان می دهند و ستون سوم مقدار ذخیره شده در آن
سطر و ستون رانشان میدهند (.تعداد سطرهای آین آرایه به تعداد مقدار ذخیره شده در ماتریس
اصلی است )
:برای پیاده سازی ماتریس اسپارس میتوان از یک ساختمان کمک گرفت
Struct elements
{
Int row, col ,value ;
{;
void main()
{
Elements s[max];
S[0].row=0;
S[0].col=0;
S[0].value=7;
}
ترانهاده ماتریس (ماتریس معکوس)
برای بدست آوردن ترانهاده یک ماتریس باید جای سطرو ستون ها راعوض می کنیم در نتیجه
عنصری که روی مکان ][i][jازماتریس اولیه قرارداردبه مکان ][j][iدرماتریس ثانویه منتقل میشود.
در ماتریس اسپارس ساده ترین راه جهت تولید معکوس آن این است که ابتدا دنبال عناصر بگردیم که
در ستون صفر ماتریس قرار دارد آنها را به ترانهاده منتقل کرد به گونه ای که جای سطروستون
عوض شود سپس برای ستون یک و غیره این کار انجام شود.
ساختمان :
برای پیاده سازی یک ساختمان از فرمول زیر کمک می گیریم :
نام ساختمان Struct
{
اجزای ساختمان
;}
مثال :
Struct rect
{
; Int x,y,s,p
;}
پشته ها یا :Stack
پشته مجموعه ای مرتب از چند قلم داده است که عمل درج یا حذف اقالمی یا عناصری از مجموعه ای
آن فقط از با الی پشته امکان پذیر است (مثل خشاب اسلحه).
(آخرین ورودی اولین خروجی ()LIFO (last in first out
در زبان Cنوع داده ای مثل پشته نداریم می بایست به وسیله ساختارهای موجود پشته را شبیه سازی
کنیم به عنوان مثال می توان از یک آرایه جهت نگهداری عناصر پشته استفاده کرد.پشته ای که در آن
هیچ عنصری وجود نداشته باشد پشته خالی نام دارد .
بر اساس پشته ای که ارائه شد دو عمل روی پشته می توان انجام داد:
-1درج عنصرجدیددرباالی پشته:به این کار Pushگفته میشود برای انجام این عمل به دوپارامترنیاز
داریم یکی نام پشته ای که می خواهیم در آن درج کنیم و دوم نام عنصری که قرار است در پشته درج
شود.
-2عمل حذف ازباالی پشته :که به آن Popمی گوییم ،برای انجام این عمل فقط الزم است نام پشته را
بدانیم.
از دیدگاه تئوری پشته یک فضای نامحدود است که می توان به هر تعداد عنصر در آن درج کنیم اما
در عمل به علت محدود بودن فضا چنین چیزی امکان پذر نیست.
همان طور که واضح است نمی توان از یک پشته خالی عمل حذف را انجام داد بنابراین برا ی حذف
باید از خالی نبودن پشته اطمینان حاصل شود.
در زبان Cنوع پیش فرضی به نام پشته وجود ندارد بنابراین میبایست پشته رابا استفاده از ساختار
های موجود در این زبان شبیه سازی کنیم بنابراین پیاده سازی یک ساختارپشته ای وPush, pop
همگی به عهده برنامه نویس است.
پیاده سازی پشته در زبان :C
برای اینکه بتوانیم پشته را به کمک آرایه پیاده سازی کنیم می بایست بدانیم که تا این لحظه چه تعداد
از سلول های آرایه بوسیله پشته پرشده است بدین منظور از متغیری استفاده می کنیم که
موقعیت
باالترین عنصر پشته را در آرایه به ما نشان می دهد به این متغیر Topمی گویند .
درج : Top ++ورود عنصر جدید
:خروج عنصر
حذفTop --
# Define max 100
Struct stack
{
; ]Char items [max
;Int top
;}
مقدار اولیه Topباید -1انتخاب شود تا بتوان از تمام آرایه ها استفاده کرد بنابراین اگر (-1),top
باشد به این معناست که پشته خالیست.
پیاده سازی تابع :Empty
این تابع در صورتی که پشته خالی باشد مقدار ( )1و در غیر این صورت ( )0را برگشت می زند پس
تابع emptyباید از نوع INTباشد.
Int empty (stack *p)
{
If (p->top==-1)
Return (1);
Else
Return (0);
}
آدرس یک متغیر از نوع پشته را دریافت می کند
:Push پیاده سازی تابع
void Push (stack *p , char x)
{
If (p->top == max -1)
Printf )“stack is full”(;
Else
{
P->top++;
P->items [p->top]=x;
}
}
: Pop پیاده سازی تابع
char Pop (stack *p)
{
Char x;
If (empty (p))
Printf)“stack is empty”(;
Else
{
x= p->items [p->top];
p->top- -;
return (x);
}
}
هر تالش برای حذف از پشته خالی منجر به وقوع رخدادی به نام پایریز) (under flowمی شود و
هر تالش برای درج در پشته پر موجب سرریز یا ))Overflowمی شود .
کاربرد پشته ها:
عبارتهای پیشوندی Prefix
عبارتهای میانوندی Infix
Postfix
عبارتهای پسوندی
برای بدست آوردن Postfixازیک عبارت Infixباید تقدم عمگرها را در نظر داشت.ساده ترین راه
برای تبدیل infixبه postfixآنست که عبارت را براساس تقدم عمگرها پرانتزگذاری کنیم .سپس از
پرانتزهای داخلی شروع کرده و موقعیت هر عملگر را به نزدیکترین پارانتز بسته ای که قبال
اشغال نشده جا به جا کنیم.
مثال:
)(((A / B)-((C * D)/E))+F
infixpostfix= ab / cd *e/-f+
برای تبدیل Postfixبه Infixمی توان از یک پشته خالی کمک گرفت بدین منظورازابتدای عبارت
postfixشروع کرده با مشاهده هر عملوند آنرا به باالی پشته اضافه کنید و با دیدن هر عملگر دو
عنصر باالی پشته را برداشته عملگر راروی آن اعمال کرده حاصل را مجددا به پشته اضافه می کنیم.
مثال:
A + B/C
برای تبدیل Postfixبه Infixشبه کد زیر آورده می شود .
شبه کد :برنامه ای که جزییات در آن در نظر گرفته نمی شود .
ABC /+
)((A * B) + C
AB * C +
(A + (B / C) :
تبدیل infixبه : prefix
()infix prefix
براي تبدیل infixبه prefixنیز همانند تبدیل infixبه postfixعمل مي كنیم فقط به جاي اینكه
از ابتداي عبارت شروع كنیم از انتهاي آن آغاز مي كنیم.
به مثال زیر توجه كنید:
))((A+ ((B / C) *E )) - (G * H
infix prefix :- + A * / BCE * GH
تبدیل prefixبه : infix
)(prefix infix
در این تبدیل نیز همانند تبدیل postfixبه infixعمل میكنیم منتهي از آخر عبارت شروع مي كنیم تا
به ابتداي آن برسیم.به مثال زیر توجه كنید:
+ * ABC
prefix infix: A * B+C
sیک رشته خالی است
) به انتهای رشته ورودی نرسیده ای( While
{
;نماد بعدی در رشته ورودی = Symb
) symbیک عملوند است( If
;) Push (s , symb
Else
{
;)Op2 = pop (s
;)Op1 = pop (s
;)عبارت حاصل از Push (s , op1 symb op2
}
}
شبه کد تبدیل prefixبه :infix
sیک رشته خالی است
) به ابتدای رشته ورودی نرسیده ای( While
{
;نماد قبلی در رشته ورودی = Symb
) symbیک عملوند است( If
;) Push (s , symb
Else
{
;)Op2 = pop (s
;)Op1 = pop (s
;)عبارت حاصل از Push (s , op2 symb op1
}
}
شبه کدی برای تبدیل infixبه Postfixاز ابتدای عبارت infixشروع کرده و با دیدن هر عملوند
آنرا درخروجی چاپ می کنیم و با دیدن هر عملگر آنرا به پشته اضافه می کنیم به شرطی که تقدم
عملگر موجود در باال کمترازعملگر مشاهده شده باشد در غیر این صورت عملگر های موجود
درپشته را آنقدر Popمی کنیم و چاپ می کنیم .تا زمانی که به پشته خالی برخورد کنیم یا با
عملگرتقدم کمتری برخورد نماییم دراین لحظه عملگرمشاهده شده را به پشته می افزاییم و پس
از رسیدن به انتهای عبارت عملگرهای موجود در پشته را یکی یکی Popکرده و مشاهده می
کنیم .
مثال دیگری از کاربرد پشته ها:
فرض کنید بخواهید یک عبارت شامل پرانتز گذاری ها را از نظر صحت بررسی کنید بدین منظور می
توان از ابتدای عبارت شروع کرد و با مشاهده هر پرانتز باز یک واحد اضافه و پرانتز بسته یک
واحد کم نمود .
)(1(2A + (3B / C2)* E1)-F0
)(1A + B0) -1
شرایط زیراگر برقرار باشد عبارت معتبر است:
اوال :در خاتمه می بایست صفر به دست آید.
ثانیا :در طول مسیر هیچ گاه شماره منفی دیده نشود.
اما فرض کنید عبارت شما به جزپرانتز شامل کروشه و آکوالد بوده باشد در این صورت شماره گذاری
کمکی نخواهد کرد .ساده ترین روش جهت تست چنین عبارتی استفاده از پشته است .
}){A*(B+C
جهت بررسی عبارتی که به جز پرانتز ازمحدود کننده های دیگرمانند کروشه یا آکوالد کمک می گیرند
از پشته استفاده می کنیم .پیمایش عبارت را از ابتدای عبارت اغاز می کنیم.با دیدن هر باز کننده
آنرابه باالی پشته اضافه می کنیم وبا مشاهده هرخاتمه دهنده یک نمادازباالی پشته حذف می کنیم
نماد حذف شده می بایست با باز کننده ای که مشاهده شده مطاقبت داشته باشد.
شرایط غلط بودن عبارت:
مثال ({ )}:
-1خاتمه دهنده با عنصر باالی پشته مطابقت نداشته باشد
-2در طول پیمایش عبارت مجبور باشیم از پشته خالی حذف کنیم مثال }(({ }) :
مثال{( )}) :
-3پس از خاتمه پیمایش پشته خالی نشده باشد
: شبه کدی برای بررسی صحت عبارت
یک رشته خالی استs
V=1;
While ()به انتهای رشته نرسیده ای
{
Symb = ; نماد ورودی بعدی
If ) symb == ‘)’ || symb == ‘]’ || symb == ‘{‘(
Push(s,symb);
If ) symb == ‘(’ || symb == ‘[’ || symb == ‘{’(
{
If (empty (s))
{
V=0;
Break ;
}
Else
{
Symb 2 = pop (s) ;
If ( !match (symb, symb 2)) دونماد را از نظر هم گروه بودن چک کندmatchفرض کنیم
{
V=0;
Break;
}//Else
}//if
}//while
If (!empty (s))
V=0;
If (v == 0)
Printf )“ ;(”عبارت غلط است
Else
Printf )“;(”عبارت صحیح است
}
صف:
صف مجموعه اي ازعناصر مرتب است كه هرعنصر از ابتداي صف حذف شده و در انتهاي صف
درج مي شود.
)FIFO (First In First Out
به صف نیز Queueگفته مي شود.
از آنجا كه درج صف ازدوطرف انجام مي شود مي بایست موقعیت عنصرابتدا وانتهاي صف را بدانیم
معموال به عنصر ابتدا ) Front (Fو به عنصر انتهاي صف ) Rear ( Rگفته مي شود.
اعمال ابتدایي روي صف:
-1عمل درج در صف كه به آنInsertنیز گفته مي شود .براي انجام عمل درج معموال به دو پارامتر
نیازمندیم .
الف) صفي كه قرار است در آن عنصر جدید درج شود.
ب) عنصر جدید كه قرار است وارد صف شود.
-2عمل حذف از صف كه به آن Removeگفته مي شود ،این عمل در صورت خالي نبودن صف
عنصر اول را حذف مي كند،براي انجام عمل .Removeبه یك عمل نیاز داریم آن هم نام صف است.
صف نیز مانند پشته فضایي نامحدود تصور مي شود كه در عمل به علت نامحدود بودن فضا این گونه
نیست بنابراین باید در نظر گرفت كه تعداد اقالم درج شده در صف باعث سرریز نشود همچنین
واضح است كه از یك صف خالي نمي توان حذف كرد چون منجــر به پا ریز مي شود.
پیاده سازي صف در زبان: C
براي پیاده سازي صف از یك آرایه كمك مي گیریم .جهت نگهداري موقعیت ابتدا و انتهاي صف
متغیر به نام هاي F,Rدر آرایه استفاده مي كنیم .دو
# Define Max 100
Struck Queue
{
;]Char Items [Max
;Int f, r
;}
پیاده سازي تابع:Insert
)Void Insert (Queue *q, Char x
{
)If (q r == Max-1
;)" Print f ("Queue is full
Else
{
;q r ++
;q Items [q r] =x
}
}
:Removeپیاده سازي تابع
Char Remove (Queue *q)
{
Char x;
If (empty (q))
Print f ("Queue is empty");
Else
{
X=qItems [qf];
qf++;
Return(x);
}
}
پیاده سازي تابع:Empty
)Int empty (Queue *q
{
)If (q f >q r
;)return (1
else
;)return (0
}
صف به شكلي كه پیاده سازي شد یك ایراداساسي دارد وآن این است كه پس از تعدادي عمل درج
حذف ممكن است به حالتي rبه آخرین اندیس آرایه رسیده باشدوعلي رغم خالي بودن و
خانه هاي قبل از Fبرخورد نتوان عنصر دیگري به صف اضافه كرد .
براي حل این مشكل راه حل هایي وجود دارد مثال مي توان لحظه ي رسیدنrبه آخرین اندیس تمامي
عناصررابه ابتداي آرایه منتقل كرد یا اینكه با هر بارعمل حذف عناصر صف یك واحد به سمت چپ
انتقال داده شود هــردو پیشنهاد مستلزم تعداد بسیار زیادي عملShiftاست راه حل بهتر استفاده
از صف هاي دایره اي است .
صف هاي دایره اي (چرخشي):
دریك صف چرخشي با آرایه به گونه اي رفتار مي شود كه به نظر مي رسد سلول اندیس]Max [i
قبل از سلول اندیس صفر قرار گرفته است در این صورت تمامي اصولي كه در صفهاي خطي گفتیم
میبایست اصالح شود در صف های دایره ای f>rنمي تواند نشان دهنده ي خالي بودن صف
شرط
باشد همچنین شرط R==max-1نشان دهنده پر بودن صف نیست تعداد عناصر داخل صف نیز
نمي تواند از رابطه R-f+1به دست آید .
شرایط خالي بودن صف را به صورت F==Rدر نظر مي گیریم یعني زماني كه صف خالي استF,R
به خانه ي واحدي مراجعه مي كند در اثر این عمل مشكلي پیش مي آید و آن این است كه اگـــر آرایه
كامال پر شود Rبا Fبرابر خواهدبود براي پیشگیري ازچنین مشكلي فرض مي كنیم كه خانه متعلق
به Fهمواره باید خالي باشد .
:Insertپیاده سازي تابع
Void Insert (Queue *q , Char x )
{
If ((qr+1) % Max ==q f)
Print f ("Queue is full ");
Else{
q r =(qr+1)% Max ;
q Items [q r] =x;
}
: Empty پیاده سازي تابع
Int empty (Queue *q)
{
if (q f == q r)
Return (1);
Else
Return (0); }
: Removeپیاده سازي تابع
Char Remove (Queue *q)
{
Char x;
If (empty (q))
Print f )"Queue is empty”(;
Else
{
q f=(qf+1)%Max;
x=q Items [qf];
Return (x);
}
}
صف اولویت:
در صف اولویت تربیت ورود و خروج به صورت Fifoنیست .در این صفها تربیت خروج بر اساس
اولویت عناصر است از دیدگاهي ساده تر مي توان صفها ي اولویت را به دو شکل صف اولویت
صعودي وصف اولویت نزولي دسته بندي كرد .در صف اولویت صعودي عناصر مي توانند به
هرترتیبي واردشونداما عمل حذف یك عنصر همواره روي عناصر كوچك تر انجام مي پذیرد .
درج و حذف در صف اولویت صعودي:
-1درج :عنصر جدید در انتهاي صف درج مي شود ( .یک عمل)
حذف :با جستجو در صف كوچكترین عنصر پیدا شده و حذف مي شود n ( .مقایسه)
-2درج :عنصر جدید در محل منطقي اش (به كمك جست و جو ) درج شود n/2(.مقایسه)
حذف :از ابتداي صف (یک عمل)
نکته :از نظر تعداد مقایسات روش دوم از روش اول بهتــر است .
مثال:
186924
روش اول 1 8 6 9 2 4 :
روش دوم 9 8 6 4 2 1 :
نکته ا ی راجع به پیاده سازی پشته ها در آرایه ها:
می توان با استفاده از یک آرایه دو پشته را پیاده سازی کرد در این صورت پشته اول از چپ به
راست و پشته دوم از راست به چپ در آرایه قرار می گیرد .
;]x=Items [top2
حذف از پشته دوم
;top2++
;top2--
درج در پشته دوم
;Items[top]=x
: top1 == -1شرط خالی بودن پشته اول
: top2 == maxشرط خالی بودن پشته دوم
:Top1 + 1 == top2شرط پر بودن هردو پشته
]x=Items[top1
حذف از پشته اول
;top1--
;top1++
درج در پشته اول
; Items[top]=x
در یک آرایه می توان چندین پشته را پیاده سازی کرددراین صورت می بایست آرایه را تقسیم بر
تعداد پشته ها کنیم فرضا اگر آرایه 20سلول دارد و تعداد پشته ها n=4است هر پشته 5خانه از
آرایه را اشغال خواهد کرد .
maxتعداد سلول های آرایه
]b [i] = i * [max/n
nتعداد پشته ها
top [i] = i * [max/n]-1
هر پشته max/nسلول اشغال می کند.
در یک آرایه می توان چندین پشته را پیاده سازی کرددراین صورت می بایست آرایه را تقسیم بر
تعداد پشته ها کنیم فرضا اگر آرایه 20سلول دارد و تعداد پشته ها n=4است هر پشته 5خانه از
آرایه را اشغال خواهد کرد .
]b [i] = i * [max/n
top [i] = i * [max/n]-1
هر پشته max/nسلول اشغال می کند.
maxتعداد سلول های آرایه
nتعداد پشته ها
لیست هاي پیوندي:
مشكل بزرگ آرایه ها آن است كه جهت پیاده سازي ساختارهایي مثل صف و پشته نمي دانیم كه دقیقا
چند سلول از حافظه مورد نیاز است پس مجبوریم حداكثــر برآورد رادرانتخاب تعداد عناصر
آرایه
اعمال كنیم این كار باعث مي شود كه در بسیاري از موارد حافظه هــدر رود و بالاستفاده باقي بماند
یكي از راه كارهاي از بین بردن این مساله استفاده از لیست هاي پیوندي است .
فرض كنید عناصر پشته و یا صف ،در داخل خودشان آدرس عنصر بعدي را داشته باشند چنین ترتیبي
یك ساختمان داده اي به نام لیست پیوندي خطي راایجاد مي كند هریك ازعناصرتشكیل دهنده
لیست
پیوندي Nodeو یا گره نام دارد .
شكل ساده اي از یك گــره :
بخش : infoاطالعات مورد نظر ما را نگه داري مي كند
بخش : Nextیك اشاره گر است كه به گره ي بعدي در لیست پیوندي اشاره مي كند .
یك لیست پیوندي خطي معموال به شكل زیر است:
براي دسترسي به لیست پیوندي از یك اشاره گر خارجي به اولین گره در لیست پیوندي اشاره مي كند
استفاده مي كنیم.
نكته :اشاره گر در آخرین گره مقدار Nullیا تهي دارد این بدان معنا است كه پس از این گره ،گره
دیگري در لیست پیوندي وجود ندارد.
نكته :براي پیاده سازي گره مي توان از یك ساختمان كمك گرفت به عنوان مثال ساختمان زیر گره اي
را تشریح مي كند كه بخش infoدر آن از نوع Charاست.
Struck node
{
;Char info
;Node * next
;}
اگر pاشاره گر به گره باشد (pinfoقسمت اطالعاتي )Infoدر گره را مشخص مي كند و منظور
از P nextاشاره گري است كه در آن گره خارج مي شود.
فرض كنیم خواسته باشیم گــره را به لیست پیوندي اضافه كنیم برا ي این كار ابتدا مي بایست گره
جدیدي را ایجاد كنیم فرض كنید تابعي به نام Get nodeوجود دارد كه وظیفه ي ایجاد گره ي جدید
و تولید آدرس آن را به عهده دارد پس از ایجاد گره جدید بخش Info , Nextآن را مقداردهي
هاي
مي كنیم.
;) ( P=get node
;P info=x
;P next=list
;List=p
پیاده سازي تابع : Get node
در زبان Cتابعي وجود دارد به نام mallocكاربرد این تابع بدین صورت است كه به اندازه عدد
ذكر شده درپرانتزجلوي آن حافظه رابه شمااختصاص مي دهد براي اینكه بتوانیم بتوانیم به اندازه ی
یك گره فضا بگیریم از این تابع به شكل زیر استفاده مي كنیم.
))Malloc (size of (node
فضاي اختصاص داده شده مي بایست در قالب یك گره پیكربندي شود بدین منظور مي بایست بنویسیم:
))Node *malloc (size of (node
*ذكــر شده جلوی nodeبدین خاطر است كه آدرس حافظه ي اختصاص داده شده تولید شده و نهایتا
به وسیله ي تابع Get nodeبرگشت داده شود شکل تابع get nodeبراساس آنچه گفته
شدبه صورت زیر است:
( )Node *get node
{
))Return ((node *) malloc (size of (node
}
حذف یك گره از ابتداي لیست پیوندي :
list
;P=list
;List= list next
;X= p Info
;)Free (p
پیاده سازي پشته ها با استفاده از لیست هاي پیوندي خطي:
عمل افزودن یك عنصر به ابتداي لیست پیوندي مانند اضافه كردن عنصري در باالي پشته است و
عمل حذف اولین عمل عنصر از لیست پیوندي مانند حذف عنصر باالي پشته مي باشد بنابراین
توابع push , popرا مي توان به شكل زیر پیاده سازي كرد.
ابتدا تابع emptyرا طراحي مي كنیم .
:Empty پیاده سازي تابع
Int empty (node *p)
{
If (p==Null)
Return (1);
Else
Return (0);
}
:Push پیاده سازي تابع
Void push (node *list, char x)
{
Node *p;
P=Get node ();
Pinfo=x;
P next=list;
list=p;
}
:Pop پیاده سازي تابع
Char pop (node *stack)
{
Node *p;
Char x;
If (empty (stack))
Print f ("stack is empty");
Else
{
P=stack;
stack = stack next;
x=pinfo;
Free (p);
Return (x);
}
}
پیاده سازي صف ها به كمك لیست ها ي پیوندي خطي :
اگر لیست پیوندي خطي به گونه اي مدیریت شود كه اولین عنصر ورودي ،اولین عنصر خروجي
باشد مي توان گفت یك صف پیاده سازي شده است در نتیجه مجبوریم از یك طرف لیست پیوندي عمل
حذف و در طرف دیگر آن عمل درج را انجام دهیم.
:Insert پیاده سازي تابع
Void Insert (node *p , char x)
{
P=Get node ();
Pinfo=x;
P next=Null;
If (r==Null)
{
f=P;
r=P;
}
Else
{
r next=P;
r =P;
}
}
:Remove پیاده سازي تابع
Char Remove (node *p )
{
Char x;
If (f==Null)
Print f ("Queue is empty");
Else {
P=f;
f=f next;
X=pinfo;
Free (p);
If (f==null)
f=null;
Return (x);
}
}
معایب پیاده سازي صف و پشته با استفاده از لیست هاي پیوندي:
-1هر گره در لیست پیوندي از هر سلول آرایه فضاي بیشتري تلف مي كند.
-2مدیریت لیست هاي پیوندي نسبت به آرایه مشكل تر است.
به طور كلي لیست ها پیوندي و آرایه ها را مي توان مورد ارزیابي قرار داد.
مزایاي لیست پیوندي نسبت به آرایه ها :
عالوه بر آنچه كه گفته شد در لیست هاي پیوندي درج و حذف از میا نه ي لیست پیوندي به سادگي
امكان پذیر است اما در آرایه ها هر عمل درج و هر عمل حذف نیاز به Shiftدادن عناصر آرایه
دارد
مزایاي آرایه نسبت به لیست پیوندي :
عالوه بر آنچه که گفته شد دسترسي به هر یك از عناصر آرایه به شكل مستقیم انجام مي شود اما در
لیست های پیوندي براي رسیدن به گره nام مي بایست n-1گره پشت سر آن پیمایش شده باشد .
به گره اي اشاره كــرده با شدگره بعداز آن را حذفpشبه كدي بنویسید كه در یك لیست پیوندي اگر
: كند
Delafter (p)
{
If ( p next ==Null)
Print f ("can not remove ")
p
Else
{
B
C
D
E
A
q= p next;
P next= q next;
q
Free (q);
}
}
فرض كنید خواسته با شیم بعد از گره اي كه Pبه آن اشاره مي كند گره جدیدي را درج كنیم.
)Insafter (p, x
{
;)( q=Get node
;q Info = x
;next
;q Next = p next
;P Next = q
q
}
نكته :در بسیاري از كاربردها مي بایست لیست پیوندي پیمایش شود معموال براي پیمایش لیست هاي
پیوندي از یك یا دو اشاره گر كمكي استفاده مي كنیم كه به دنبال یكدیگر درون لیست حركت مي كنند .
مثال:در یك لیست پیوندي حاوي عدد صحیح كلیه ي گره هایي را كه حاوي عدد 4هستند را حذف
كنید
While (list info == 4 && list! = Null){
Pop (list);
p = list;
q = list Next;
While (q! = Null)
{
If (q info == 4)
{
Delafter (p);
q = p Next;
}
Else {
p = p Next;
q = q Next;
}
}
لیست مرتب:
لیستي كه درآن عناصر کوچکترقبل ازعناصر بزرگتر قرار گرفته باشند .بنابراین اگر بخواهیم عنصر
جدیدي به آن اضافه كنیم مي بایست به گونه ای باشد كه ترتیبش هم نخورد.
می خواهیم شبه كدي براي درج یك عنصر جدید در داخل لیست مرتب بنویسیم .
-1عنصر جدید از تمامي عناصر لیست كوچكتر است .
-2مقدار جدید به گونه اي است كه در میان لیست قرار مي گیرد.
-3عنصر جدید از تمام عناصر لیست بزرگتر است.
1)
If (x< list info)
Push (list, x);
Else
{
p=list;
q=list Next;
While (qinfo < x)
{
p=p Next;
q=q Next;
}
Insafter (p, x)
}
2)
If (x< list info)
Push (list, x);
Else
{
p=list;
q=list Next;
While (qinfo < x && q! =Null)
}
p=p Next;
q=q Next;
}
Insafter (p, x) }
}
الگوریتم فوق از آنجا كه عنصر جدید را در محل واقعیش قرار مي گیرد جهت پیاده سازي صفهاي
اولویت به کار رود این الگوریتم را Placeنام گذاري مي كنیم.
اگر لیست پیوندي ما تهي باشد چه كار باید بكنیم؟
)If (x< list info || list == Null
نکته :براي پیاده سازي صف اولویت مي توان از پیاده سازي لیست پیوندي استفاده كنیم فرضا اگر
صف اولویت صعودي باشد مي توان از صف اولویت صعودي خود استفاده كنیم .
نکته :صف اولویت نزولي مشابه با مواردي كه در پیاده سازي صف صعودي گفته شد قابل پیاده
سازي است.
نکته :در بعضي از كتابها به Infoاز كلمه ي Dataو به جاي Nextاز كلمه Linkاستفاده
جای
مي شود .
در كدهاي زبان پاسكال به جاي دستوراتي مثل p infoاز p infoو p nextاز
p infoاستفاده مي شود.
عمل درج در ابتداي لیست با عمل درج در میانه یا انتهاي لیست پیوندي تفاوت ساختاري داشت ،براي
درج در ابتدا از Push, Insertاستفاده می شود وبرای درج در انتها یا میانه از Insafter
استفاده مي شود .
در برخي مواقع براي اینكه درج یكسان درآید ( همواره به صورت )insafterیك گره اضافه به نام
گره راس درابتداي لیست درنظرمي گیریم حتي زماني كه لیست پیوندي تهي است وگره راس
موجود است.
بخش Infoدرگره راس دربرخي موارد بالاستفاده قرار مي گیرد و در برخي دیگر از موارد اطالعاتي
از لیست پیوندي در گره قرار مي گیرد مثال مي توان تعداد گره هاي موجود را در آن ثبت كنیم.
و در برخي دیگر گره راس مي تواند دو اشاره گر یكي به ابتدا و دیگري به انتها ي لیست پیوندي
داشته باشد.
از لیست هاي پیوندي مي توان براي پیاده سازي چند جمله ایها استفاده كرد در این صورت هر گره
شامل سه بخش خواهد بود.
فرض كنید دو چند جمله اي دارید و مي خواهید آنها را با هم جمع كنید.
7x^5 + 3x^3 – 6x^2+ 4
5x^6-4x^5+2x^4+2x^2-x
هنگام جمع دو چند جمله اي حالتهاي زیر مي تواند وجود داشته باشد :
)1دو جمله اي كه با آن مواجه هستیم هم توان باشند :ضرایب با هم جمع شوند وهردوجمله راپشت
سرمی گذاریم.
)2یكي از جمالت توان بیشتري دارد آن جمله انتخاب شده و پشت سر گذاشته مي شود .
p=list1;
q=list2;
List3=Get node ();
If ( p t = = q t)
{
List3 t= p t
List3 z=p z + q z;
p=p Next;
q=q Next;
}
Else if (p t > q t)
{
List3 t=p t;
List3 z=p z;
p=p Next;
}
Else
{
List3 t=q t;
List3 z=q z;
q=q next;
r=list3;
While (p! =Null && q! =Null)
{
If (p t==q t)
{
Insafter (r, p z + q z, p t);
p= p Next;
q= q next;
r = r Next;}
Else if (p t >q t)
{
Insafter (r, p z, p t);
r=r Next;
}
Else
{
Insafter (r, q z, q t);
r=r Next;
}
}//while
If (p! =Null)
{
While (p! =Null)
{
Insafter (r, p t, p z);
r= r Next;
p=p Next;
}
}
If (q! =Null)
{
While (q! =Null);
{
Insafter (r, q t, q z);
r= r Next;
q= q Next;
}//while
}
لیست هاي پیوندي دایره ا ي:
اگر اشاره گر خارج شده از آخرین گره به جاي Nullبه گره ابتدایي اشاره كند ساختار جدیدي به نام
لیست پیوندي دایره اي پدید مي آید.
در لیست هاي پیوندي دایره اي به خاطر بسته بودن لیست مي توان از هر نقطه لیست به نقاط دیگر
دسترسي پیدا كرد.
براي آنكه مدیریت لیست ساده تر انجام شود اشاره گر خارجي به لیست را روي آخرین گره فرض مي
گیریم در نتیجه گره ي بعد از آن گره ي اول خواهد بود.
به وسیله ي لیست هاي دایره اي میتوان پشته ها وصف ها را پیاده سازي كرد.
پشته ها درلیست هاي پیوندي دایره اي :
C
B
A
: Push شبه كدي براي تابع
Void push (stack, x)
{
p=Get node ( );
p info=x;
If (stack! =Null)
{
p Next =stack next;
Stack next=p;
}
Else
{
p Next=p;
Stack=p;
}
}
: Pop شبه كدي براي تابع
Char pop (stack)
{
If (stack == Null)
Print f ("stack is empty);
Else
{
P= stack Next;
Stack Next=p Next;
X=p info;
If (p==stack)
Stack=Null;
Free (p);
Return (x);
}
}
پیاده سازي صف ها با استفاده از لیست هاي پیوندی دایره ای
: Insert پیاده سازي تابع
Void Insert (queue, x)
{
p=Get node ( );
p info = x;
If (queue! =Null)
{
p Next = queue Next;
queue Next=p;
}
Else {
p Next=p;
queue =p;
}
queue = queue Next;
}
f
r
q
A
B
C
null
q
q
q
: Remove پیاده سازي تابع
Char remove (queue)
{
If (queue == Null)
Print f ("queue is empty");
Else {
p=queue Next;
queuenext=p Next;
X=p Info;
If (p==queue)
queue == Null;
Free (p);
Return (x);
}
}
لیست هاي دو پیوندي:
یكي از مشكالت بزرگ لیست هاي یک پیوندي (خواه خطي باشد خواه دایره اي ) آن است كه امكان
پیمایش معكوس در آن ها وجود ندارد این مشكل به وسیله ي لیست هاي دو پیوندي قابل حل است.
نكته :لیست هاي دو پیوندي را گاهي لیست هاي پیوندي دو طرفه نیز مي گویند.
شكل هر گره در لیست هاي دو پیوندي به شكل زیر است.
نكته :اشاره گر هاي Left, Rightرا در بعضي كتاب ها به ترتیب Prev , Nextتعریف
كرده اند.
همان طور كه گفته شد در لیست ها ي دو پیوندي مي توان از هر نقطه به گره بعدي ویا قبلي
دسترسي پیدا كرد.از جمله كارهایي كه به سادگي مي توان روي لیست هاي در پیوندي انجام داد حذف
مستقیم گره اي است كه pبدان اشاره مي كند.
به عنوان مثال در یك لیست دو پیوندي زیر مجموعه دستورات باعث حذف گره pمي شود.
r
L=p left;
R=p right;
L right =r;
R left=l;
X=p info;
Free (p);
فرض كنید خواسته باشید در یك لیست دو پیوندي سمت راستي كه گره بدبن اشاره مي كند گره جدیدي
.را درج كنیم
Q=Get node ();
Q Info=x;
r= p right;
Q Right=r;
Q Left=p;
P right=q;
R left=q;
درختها:
درخت دودویی :
یک درخت دودویی ساده ترین شکل درخت می باشد که از سه مجموعه تشکیل شده است
مجموعه اول یک عنصر به نام ریشه دارد و دو مجموعه دیگر به نام زیر درخت چپ و زیر درخت
راست
موسوم است .هر یک از زیر درخت ها می تواند تهی باشد.
در شکل فوق Aریشه درخت B ،ریشه زیر درخت چپ و cریشه زیر درخت راست می باشد .
همانطور که در شکل می بینید زیر درخت چپ و راست Bشامل E , Dهستند.
هر عنصر درخت دودویی گره نامیده می شود .در مثال قبل 9گره وجود دارد .گره ای که زیر درخت
چپ و راست خالی داشته باشد برگ نامیده می شود .
ریشه و Bریشه زیر درخت چپ یا راست آن باشد آنگاه Aرا پدر Bو Bرا پسرچپ یا راست
اگر A
َََ Aمی نامیم.
اگر Aپدر Bیا پدرچند گره باالتراز Bباشد Aراجد Bو Bرانوه ی Aمی نامیم.اگر Bپسر چپ
َََ Aیا نوه ی پسر چپ Aباشد آنگاه Bنوه ی چپ Aمحسوب می شود .
تعریف مشابهی برای نوه ی راست نیز می توان ارائه داد.
اگر دو گره فرزندان چپ و راست یک پدر باشند با هم برادرند.
نکته :در برخی کتابها به جای پدر ازکلمه والد یا ) (parentاستفاده می شود به جای پسر از واژه
فرزند وبه جای برادر از واژه همزاد استفاده می شود.
درخت دودویی محض :
درختی که هر گره آن یا فرزند ندارد یا دو فرزند دارد.
یک درخت دودویی محض اگر nبرگ داشته باشد 2n-1گره دارد
یک درخت دودویی کامل می تواند به شکل زیر شماره گذاری شود:
در برخی کتابها سطح را از صفر شروع می کنند.
مثال درخت باال سه عمق دارد.
درخت دودویی پر :
درختی که محض باشد و تمام برگ های آن در یک سطح قرار داشته باشد.
شکل های 1،2،3هم محض هستند هم پر ولی شکل 4فقط محض است .
درخت دودویی پر باید ساختار مثلثی داشته باشد .
اگر درخت دودویی پر عمقی برابر با Dباشد تعداد گره های آن برابر است با :
تعداد گره ها tnعمق D
1
1
)( tn1
2
3
tn = 2 ^ d – 1
D = 2 ^ d = tn + 1 d = log
2
3
7
درخت دودویی کامل :
اگر درخت دودویی کامل Dشرایط زیر داشته باشد کامل است .
-1کلیه برگهای آن حداکثر در 2سطح Dو D-1واقع شده باشد.
-2درخت از چپ به راست پر شود .
-3اگر آخرین سطر برگهای درخت حذف شود یک درخت پر پدیدار می شود .
یک درخت دودویی کامل می تواند به شکل روبرو شماره گذاری شود:
ریشه شماره 1
1
3
هرفرزند چپ 2برابر پدرش
2
7
4
5 6
هر فرزند راست 2برابر پدرش 1+
یک درخت دودویی کامل را می توان به کمک آرایه پیاده سازی کرد .
در این صورت فرزندان چپ وراست هریک ازعناصر آرایه درموقعیتهای دوبرابر و دو برابر ++قرار
دارد ،همچنین برای پیدا کردن پدر هر گره کافیست اندیس مربوط به آن را تقسیم بر 2کرده و جزء
صحیح آنرا انتخاب نمود .
اعمال ابتدایی روی درخت دودویی :
چند عمل ابتدایی را روی درخت دودویی می توان انجام داد قبل از شرح این اعمال می بایست ساختار
گره را بررسی کرد یک گره در ساده ترین حالت می تواند مشابه گره ای در لیست دو پیوندی باشد .
اگر از چنین روشی استفاده کنیم پیمایش به سمت باال امکان پذیر نیست .برای حل این مشکل درپاره
ای از موارد اشاره گری به سمت باال در گره ایجاد می شود.در نتیجه می توان گره را با ساختمان
Struct node
زیر پیاده سازی کرد :
{
;Char info
};Node *left,*right,*father
توجه :واضع است که فقط در گره fatherبرابر nullاست همچنین واضح است که در تمامی
برگ ها اشاره گرهای right,leftبرابر nullهستند .ریشه
نکته :در موارد بسیار نادری یک گره اشاره گر برادر خواهد داشت .
می توان تابعی به نام )Isright (pطراحی کرد ) Isright (pدر صورتی Trueبرگشت خواهد داد
که خود گره pفرزند گره سمت راستی پدرش باشد وگرنه Falseبرگشت می دهد .
تابع ): Isleft (pمشابه ) Isright (pاست منتهی برای فرزند چپ .
)Make tree(xاولین گره یعنی ریشه درخت را می سازد این تابع یک گره حاوی xراایجادمی کند
هر سه اشاره گر خارج شده از این گره Nullاست پس آدرس گره ساخته شده را بر گشت می دهد.
;)Tree=maketree(a
Setleftبا پارامتر های (: )p,xدر صورتی که سمت چپ گره pگره ای موجود نباشد گره جدیدی
حاوی xسمت چپ pایجاد می کند.
setrightمشابه setleftبرای فرزند سمت راست می باشد .
نمونه ای از کاربرد درخت دودویی:
درخت دودویی ساختمان داده ای است که در فرایند تصمیم گیریهای دو طرفه بسیار پر کاربرد است .
هنگام کار با درخت ها همواره مایلیم درخت هایی بسازیم که تمامی شاخه های آن به شکل نرمال رشد
کرده باشد منظور ما از یکی درخت نرمال درختی است که تفاوت سطح برگ های آن به طور کلی زیاد
نباشد واضح است که در بهترین حالت دنبال یک درخت پر یا کامل باشیم .
نکته :اگر این حالت ایده آل را در نظر بگیریم طبق آنچه گفته شد عمق درخت پر از رابطه زیر بدست
می آید.
=tn
=tn+1
tn1
1
d
log
d=2
2n
2
n
log
یک درخت نرمال
≈ ( dعمق درخت) :در 2
number of nods
2
log
حال فرض کنید که خواسته باشید در میان لیستی از عناصر ،عناصر تکراری را یافته یا حذف کنید.
)nتعداد عناصر) ≈ nn 1تعداد مقایسات :برای درج nگره در چنین درختی
یک روش برای اینکار این است که عنصر2اول را با n-1عنصر باقیمانده مقایسه کنیم ودر این مسیر
عناصر تکراری را چاپ کنیم (تعداد مقایسات )n-1باشد سپس عنصردوم را با n-2عنصر باقیمانده
مقایسه کنیم که در این صورت n-2مقایسه دیگر انجام می شود این کار تا انتهای لیست باید تکرار
شود در این صورت تعداد کل مقایسات از رابطه زیر بدست می آید :
== (n - 1) + (n - 2)+(n-3(+…+1تعداد کل مقایسات
روش بهتراستفاده ازیک درخت دودویی است دراین روش عنصر اول لیست ریشه درخت را می سازد
عناصر باقیمانده به گونه ای وارد درخت می شوند که ریشه هر زیر درخت از نوه های چپ بیشتر
باشد و از نوه های راست کمتر .
6 3 9 1 4 7 8 7 2 1 5 10
تعداد مقایسات برابر است با عمق گره )Log (n
تعداد مقایسات در مثال فوق برای یک گره برابر است با :
)تعداد گره ها( ≈ log2تعداد مقایسات برای یک گره جدید
n
)nتعداد عناصر( ≈ n log2تعداد مقایسات برای درج Nگره در چنین درختی
N=100
: (1000*999)/2 ≈ 500000روش اول
:1000 * log2 1000 =10000روش دوم
6
3
9
7
10
8
4
5
1
2
: شبه کد عناصر تکراری
اولین عنصر باشدx اگر
Tree=maketree(x);
While({)عددی در لیست وجود دارد
X=;عدد بعدی لیست
p=tree;
q=tree;
While(q!=null && p info !=x){
p=q;
If (x>pinfo)
q=qright;
Else
q=qleft;
}//while
If(x==pinfo)
printf(“%c”,x);
Else{
if(x>pinfo)
setright(p,x);
else
setleft(p,x);}
}
پیمایش درخت :
پیمایش درخت حرکت در سر تا سر درخت و مالقات تمام گره هاست .
سه روش پیمایش در درختها وجود دارد :
(VLR) Preorder
-1پیش ترتیب
(LVR) Inorder
-2میان ترتیب
(LRV) Postorder
-3پس ترتیب
براي پیمایش Preorderسه عمل زیر باید انجام شود:
)1مالقات ریشه
)2پیمایش زیر درخت چپ به روش preorder
)3پیمایش زیر درخت راست به روش preorder
Preorder : ABDFGHEICJKL
براي پیمایش Inorderسه عمل زیر باید انجام شود:
)1پیمایش زیر درخت چپ به روش inorder
)2مالقات ریشه
)3پیمایش زیر درخت راست به روش inorder
inorder : DGFHBIEAJCLK
برای پیمایش postorderسه عمل زیر باید انجام شود:
)1پیمایش زیر درخت چپ به روش postorder
)2پیمایش زیر درخت راست به روش postorder
)3مالقات ریشه
Postorder : GHFDIEBJLKCA
نكته :یكي از روش هاي مرتب سازي استفاده از درختان دودویي است اگر درخت مربوط به پیدا کردن
اعداد تكراري را به گونه اي ایجاد كنیم كه عناصر تكراري نیز داخل درخت درج شو د با پیمایش
Inorderآنها ،اعداد به ترتیب صعودي sortمي شود.
به چنین درختي ،درخت جست و جوي دودویي ) (binary search treeمحض گفته مي شود.
نكته :مي توان یك عبارت حاوي عملوندها وعملگرها رابه وسیله ي یك درخت دودویي محض
پیمایش
كرد.
بدین منظور ابتداعبارت را پرانتز گذاري کرده و سپس از داخلي ترین پرانتزهازیردرخت را می سازیم
ودرخت را از پایین به باال تكمیل می کنیم.
))(((A*B)-((C/D)*E)) + (F*G
اگر درخت به درستي ایجاد شده باشد سه پیمایش Inorder ,postorder ,preorderآن به
ترتیب معادل Infix, postfix, prefixعبارت را تولید مي كند.
درخت هاي دودویي نخي :
اگر در ساختارهاي درختي دقت كنید خواهید دید كه اشاره گر Left,Rightتمامي برگها Nullمي
باشد همچنین گره هایي كه فقط یك فرزند دارند صاحب یك اشاره گر Nullنیز هستند.
تعداد زیاد اشاره گر هاي Nullكه بالاستفاده مانده اند ایده اي براي تولید درختاني به نام درختان
نخي شده است.در درختان نخي هر اشاره گر Nullكه از گره خارج مي شود به گره اي اشاره خواهد
کرد كه در پیمایش Inorderگره بعدی یا قبلی محسوب شوداگر اشاره گر rightتهی باشد آن
را به گره ای وصل می کند که در پیمایش inorderگره بعدی ما محسوب شده وگرنه به گره
ماقبل وصل مي كنیم.
مثال :در درخت زیر اشارهگرهای نخی را به درخت اضافه می کنیم .
Inorder : DGFHBIEAJCLK
نمایش لیست هاي پیوندي با استفاده از درختان دودویي:
همان طور كه به خاطر دارید در یك لیست پیوندي رسیدن به Kامین عنصر مستلزم به پیمایش K-1
عنصر ماقبل است.
مي توان یك لیست را روي یك درخت سوار كرد به گونه اي كه یافتن یك عنصر خاص با سرعت
بیشتري انجام شود .به مثال زیر توجه کنید:
لیستي مانند لیست زیر را در نظر بگیرید:
A
B
C
D
E
F
G
H
I
J
مي توان عناصر این لیست را به عنوان برگ هاي یك درخت دودویي قرار داد با این شرط كه با
پیمایش Inorderترتیب عناصر لیست حفظ شود یك نمونه از چنین درختي به شكل زیر است:
داخل هر گره غیر برگ عددي قرار مي گیرد كه نشان دهنده ي برگ هاي موجود در زیر درخت چپ
آن گره است.
عدد نوشته شده در هر گره به ما مي گوید كه كدام زیر درخت را طي كنیم اگر به دنبال عنصري
هستید كه از آن كمتر است زیر شاخه ي سمت چپ وگرنه زیر شاخه ي سمت راست را انتخاب كنید
اگر زیر درخت سمت راست انتخاب شود به اندازه ي شماره ي گره مي بایست از عدد جست و جو كم
كنید واگر كمتر و یا برابر باشد سمت چپ .
براي یافتن یك گره ي خاص مي توان شبه كد زیر را ارائه كرد.
به دنبال kامین گره می گردیم.
;r=k
;p=tree
( Pبه برگي نرسیده استWhile ( .
{
)If (r<=p Info
;p=p left
Else
{
;r=r- p Info
;p=p right
}
}
واضح است در چنین درختي سرعت دستیابي بیشتر خواهد شد تعداد مقایسات دراین درخت حداكثر به
اندازه ي عمق آن خواهد بود واگر درخت به شكل نرمال رشد كرده باشد عمق درخت برابر است
با log nیعني حداكثر تعداد مقایسات برابر با log nخواهد شد اما حداكثر تعداد مقایسات در
داخل یك لیست برابر با nخواهد بود.
درخت هاي عمومي :
یك درخت عمومي به طور كلي مجموعه اي از عناصر یك لیست غیر تهي است كه یكي از آن ها به
نام ریشه و ما بقي به m>=0زیر مجموعه ي مجزا تقسیم مي شود كه هر یك درخت مي باشد
هرعنصر درخت گره نامیده مي شود.
مفاهیم پدر ،پسر ،برادر ،جد ،نوه ،سطح وعمق همانند مفاهیم گفته شده در درختان دودویي است .
درجه ي هر گره برابر است با تعداد فرزندان آن گره .
درجه ي درخت برابر است با بیشترین درجه ي موجود در كل درخت.
درخت مرتب:
درختي است كه زیر درخت هر گره ي آن مجموعه ي مرتبي را تشكیل داده است.
در درخت مرتب پسران هر گره معموال به نام پسر اول ،پسر دوم و ...تا پسر آخر نامیده مي شود این
نامگذاري معموال از چپ به راست انجام مي شود .
اولین پسر پیرترین پسر و آخرین پسر جوان ترین پسر است.
تبدیل درخت عمومي به دودویي :
)1ارتباط بین هرپدربا کلیه فرزندانش به جز اولین فرزند قطع مي شود.
)2ارتباط جدیدي بین اولین فرزند تا آخرین فرزند به وجود مي آید .
)3گره هایي كه حاوي اتصال جدید شده اند 45درجه در جهت حركت عقربه هاي ساعت دوران مي
كنند.
اگر پیمایش preorder,inorderدرخت دودویی رابه ما داده باشند می توانیم درخت دودویی
معادل آن را بسازیم به مثال زیر توجه کنید:
A
Preorder: A B C D E F G H I
Inorder: C B D A G F I H E
B
E
F
H
D
C
G
I
به دو پیمایش فوق توجه کنیدهمان طور که مشاهده می شود در پیمایش preorderاولین عنصر
مشاهده شده ریشه درخت است .پیمایش inorderبه ما کمک می کند تا بتوانیم مجموعه
عناصر موجود در زیر درخت چپ وراست ریشه را تعیین کنیم.
همان طور که مشاهده می شود می بایست B,C,Dزیر درخت چپ و همچنین E,F,G,H,Jدر
سمت راست.
A
E FG H I
BCD
در ادامه می توان از دو پیمایش نتیجه گرفت گرفت که بین B ، B,C,Dریشه است .همچنین در
زیر درخت راست ریشه Eاست.مجددأ می توان به شکل قبل عمل کرد چون در پیمایش
C، inorderقبل از Bقرار گرفته فرزند چپ Bخواهد بود و به همین دلیل Dفرزند راست
Bخواهد شد.
A
A
B
E
F
IH
D
F
C
FGHI
B
D
C
G
در واقع برای تشکیل یک درخت ما همواره به 3اطالع نیازمندیم اوالً در هر مرحله ریشه ،چه
خواهد بود پیدا کردن ریشه از طریق پیمایش preorderمعلوم می شود ثانیا ً زیر درخت
چپ چگونه خواهد بود .زیر درخت چپ از طریق inorderفایل تشخیص است ثالثا ً زیر
درخت راست چگونه خواهد بود .زیر درخت راست نیز از طریق inorderپیدا می شود پس
مراحل کار به شکل زیر خالصه می شود .در هر گام:
-1ریشه از طریق preorderپیدا کنید.
-2زیر درخت چپ وزیردرخت راست را از طریق inorderپیدا کنید.
این کار تا زمانی که تمام گره ها خالی بوده یا حداکثر یک عنصر داشته باشند ادامه می یابد.
درخت حاصل را بدست آورید؟. درختی به شکل زیر استpreorder,inorder:مثال
Preorder: A B C D E F G H I
Inorder: B C A E D G H F I
A
A
BC
B
DEFGHI
D
C
E
FGHI
F
GH
F
G
H
I
I
نکته:با استفاده از روشی مشابه فوق می توان به کمک postorder,preorderیک درخت
دودویی به دست آورد.
نکته:پیمایش های preorder,inorderفقط یک درخت را نشان می دهد همچنین به ازای
پیمایش های inorder,postorderنیز تنها یک درخت به وجود می آیداما با داشتن
پیمایش های preorder,postorderممکن است بیش از یک درخت پدید آید.
توجه:به وسیله nمقدار متمایز می توان به تعداد ترکیب
2n
n
درخت متمایز ایجاد کرد.
n 1
!n
!)m!*(n m
=
n
m
!6
)3!*(6 3
4
:فرمول ترکیب
=
6
3
4
جنگل
جنگل مجموعه اي مرتب از درخت هاي مرتب است.
سه روش براي پیمایش درختان جنگل وجود دارد.
روش preorder , Inorder , postorder
پیمایش :preorder
)1ریشه درخت اول جنگل را مالقات كنید.
)2جنگل تشكیل شده توسط زیر درخت هاي اولین درخت را در صورت وجود به شكل preorder
پیمایش كنید.
)3جنگل تشكیل شده توسط زیر درخت هاي باقیمانده جنگل را در صورت وجود به شكل preorder
پیمایش دهید.
(طبق شکل صفحه قبل)
( برادرانم فرزندانم خودم ( Preorder :
ABECFGDHIKJ LMORPQN STUWXYZV
درخت اول
درخت دوم
درخت سوم
پیمایش :Inorder
)1جنگل تشكیل شده توسط زیر درخت هاي اولین درخت جنگل را در صورت وجود به شكل
Inorderپیمایش كنید.
)2مالقات ریشه درخت اول جنگل.
)3جنگل تشكیل شده توسط درخت هاي باقیمانده جنگل را در صورت وجود به شكل Inorder
پیمایش دهید.
)برادرانم خودم فرزندانم) Inorder :
EBFGCHKIJDA
ROPQMNL TXYZWUVS
(طبق شکل صفحه قبل)
درخت اول
درخت دوم
درخت سوم
پیمایش : Postorder
)1جنگل تشكیل شده توسط زیردرخت هاي اولین درخت جنگل را در صورت وجودبه شكل
postorderپیمایش كنید.
)2جنگل تشكیل شده توسط زیر درخت هاي تشكیل شده را در صورت وجود به شكل Postorder
پیمایش دهید.
)3ریشه اولین درخت جنگل را مالقات كنید.
(طبق شکل صفحه قبل)
(خودمبرادرانم فرزندانم) Postorder :
EGFKJIHDCB
RQPONM
ZYXWVUTSLA
درخت اول
درخت دوم
درخت سوم
نكته:
اگر یك درخت عمومي را تبدیل به دودویي كنید در هر دو درخت هر سه پیمایش مي بایست نتیجه ي
یكساني در بر داشته باشد.
Preorder:ABECFGDHIKJ
Inorder:EBFGCHKIJDA
Postorder:EGFFKJIHDCBA
كدهاي هافمن:
الفبایي با nعالمت وجود دارد یك پیام طوالني از نمادهاي این الفبا موجود است مي خواهیم پیام را
به صورت رشته اي طوالني از بیت ها به رمز درآوریم.
مثال:فرض كنید الفباي شما از 4حرف A,B,C,Dتشكیل شده باشد.
اگر نماد ها به شكل فوق انتخاب شده باشند براي كد كردن 8حرف به 16بیت نیازمندیم.
A B A C C D A A = 111011010100111116 bit
کد
11
10
01
00
نماد
A
B
C
D
اگر نماد ها به شكل فوق انتخاب شده باشند براي كد كردن 8حرف به 16بیت نیازمندیم(8*2=16).
در روش هافمن تعداد تكرارعال َِِیم مد نظر قرار مي گیرد به این صورت كه درخت دودویي ایجاد مي
شود كه ریشه ي آن تمام عالیم موجود در ریشه است .سپس فرزند چپ درخت همان نمادي است كه
بیشترین تكرار را دارد و فرزند راست آن نمادهاي باقي مانده است.
زیر درخت هاي سمت راست نیز بنا به همین قانون توسعه مي یابد.
بر اساس رشته فوق تكرار عالیم درخت بدین صورت پدید مي آید.
براي پیاده كردن هر نماد به روش زیر عمل مي كنیم:
از برگ حاوي عالمت مورد نظر شروع كرده و به سمت باالي درخت حركت كنید در مسیر پیشروي
اگر از زیر درخت چپ به ریشه رسیدید ()0را به سمت چپ كد حاصل اضافه كنید وگرنه ( )1را اضافه
كنید این كار تا رسیدن به ریشه ي اصلي درخت ادامه پیدا مي كند.
A=0
C = 10
B = 110
D = 111
مروري بر پیچیدگي ها :
الگوریتم هاي مختلفي براي انجام اعمال مختلف طراحي شده اند هر الگوریتم معیارهایي دارد كه مي
توان به وسیله ي آن معیارها چند الگوریتم مختلف را با یكدیگر مقایسه كرد به عنوان مثال در روش
جست و جو ما با الگوریتم هاي مختلفي مواجه هستیم كه هر یك كارایي خاص خود را دارد اگر
خواسته باشیم الگوریتم هاي مختلف را با یكدیگر بسنجیم مي بایست روشي استاندارد براي سنجش
آن ها داشته باشیم كه مورد پذیرش همگان باشد .براي مقایسه الگوریتم ها باید معیارهایي انتخاب
شود كه وابسته به كامپیوتر ،برنامه نویس ،زبان برنامه نویسي و امثال آن نباشد .بحث پیچیدگي
الگوریتم ها مي تواند به معناي درجه سختي الگوریتم باشد براي پیدا كردن پیچیدگي الگوریتم ها
ساده ترین راه آن است كه ابتدا عمل اصلي الگوریتم را حدس بزنیم به مثال زیر توجه كنید.
الگوریتم :1
)Int search (into s [ ],int n,int x
{
;Int i=0
)While (s [i]! =x && i <=n-1
;i++
)If (i>=n
;)Return (-1
Else
} ;)Return (i
الگوریتم فوق به روش جست و جوي خطي معروف است در این روش عنصر مورد جست و جو ()X
قرار است در بازه اي از عناصر به نام Sجست و جو مي شود اگر عنصر مورد نظر در آرایه ي S
قرارداشت اندیس آرایه را كه شامل Xاست برگشت خواهد شد وگرنه -1برگشت داده می شود (-1
یعني عنصر مورد نظر وجود نداشت).در الگوریتم فوق عنصر Xابتدا با اولین اندیس Sمقایسه
میشود اگر برابر نبود مقایسه با عنصربعدي انجام خواهد شد .انجام مقایسات تا لحظه اي ادامه
پیدا مي كند كه یا عنصر پیدا شده باشد یا اینكه از محدوده ي Sعبور كرده باشیم .در الگوریتم
فوق عمل مقایسه عمل اصلي الگوریتم است.
الگوریتم :2
{)Int max (int s [ ], int n
;Int max=0, i
;]Max=s[0
{)For (i=0, i<= n-1, i++
)]If (max < s[i
};]max=s[i
};)Return (max
در الگوریتم فوق نیز عمل اصلي مقایسه Maxبا ]S[iمي باشد دستور ;]max=s[iنمي توانست
عمل اصلي با شد زیرا این دستور بعضي اوقات انجام مي شود امادربرخی ازمواردانجام نمی شود
پس مي توان گفت :دستور اصلي دستوري است كه بیشترین تعداد تكرار را در الگوریتم دارا با
شد.
الگوریتم :3
)Int Sum (int s [ ], int n
{
;, sum=0هInti
)For (i=0, i< =n, i++
;]Sm = sm+s[i
;)Return (sm
}
در الگوریتم فوق عمل اصلي عمل جمع Smبا ]S[iمي باشد پس از شناخت عمل اصلي مي بایست
تعداد تكرار هاي آن را بدست آورید در اكثر الگوریتم ها این تعداد بر اساس nبدست مي آید ( nتعداد
عناصروروی است)در الگوریتم ها ي دوم و سوم تعداد تكرار عمل اصلي nمرتبه مي باشد در
الگوریتم اول تعداد تكرار اعمال اصلي مي تواند یك یا دو یا ...یا nمرتبه بوده باشد پس از
تعیین تكرار هاي عمل اصلي معموال رابطه اي بر اساس nپیدا مي شود معموال یك چند جمله اي
بر اساس nپیدا مي شود در چند جمله اي بدست آمده كافي است بزرگترین جمله را انتخاب كرده
ضرایب ثابت آن را حذف كنید آنچه كه بدست مي آید پیچیدگي الگوریتم شما است .
در الگوریتم دوم تعداد اعمال اصلی برابر nاست پس مي توان گفت پیچیدگي الگوریتم nمي باشد.
هنگام پیدا كردن پیچیدگي به طور كلي با دو گروه از الگوریتم ها مواجه هستیم .
)1الگوریتم هایي كه پیچیدگي آن ها وابسته به مقادیر ورودي نیست به عنوان مثال الگوریتم سوم یا
sumبدون توجه به این كه چه مقداري در Sقرار دارند آنها را با هم جمع كنند هم چنین در
الگوریتم maxاگرچه عناصر ]S[iمهم هستند الگوریتم مجبور است تمام آن ها را بررسي كند تا
بتواند maxرا بیابد.
)2الگوریتم هایي كه پیچیدگي آن ها وابسته به مقادیر ورودي است به عنوان مثال تعداد تكرار ها
در الگوریتم Searchوابسته به این است كه عناصر مورد جست و جو در كجاي Sواقع شده با
شد .الگوریتم هایي كه پیچیدگي آن ها وابسته به مقادیر ورودي نیست گروه اول از الگوریتم هاي ما
بودند پیچیدگي این الگوریتم ها را با نماد )T(nنشان مي دهیم.
)T (nعبارت است از پیچیدگي زماني الگوریتم مورد نظر بر اساس nعنصر ورودي .الگوریتم
هایي كه پیچیدگي زماني آن ها وابسته به مقادیر ورودي است با سه نماد زیر پیچیدگي آن ها را نشان
مي دهیم.
بهترین حالت
)B (n
حالت متوسط
)A (n
بدترین حالت
)W (n
به عنوان مثال الگوریتم پیدا كردن یك عنصر خاص (جست و جوي خطي )را در نظر بگیرید در
بهترین حالت با یك مقایسه عنصر مورد نظر پیدا مي شود بنابراین B (n)=1در بدترین حالت باn
مورد نظر پیدا مي شود w(n)=nو در حالت متوسط تقریبا نیمي از عناصر
مقایسه عنصر
n
مقایسه مي شود . An در الگوریتم حاصل جمع تعداد اعمال اصلي به مقادیر ورودي
2
وابسته نیست و همواره nعمل جمع باید انجام شود .در این صورت مي گوییم T(n)=nهم چنین
براي پیدا كردن بزرگترین عنصر در میان لیست تمامي عناصر لیست باید مقایسه شود و این
الگوریتم نیز به مقادیر ورودي وابسته نیست پس تعداد اعمال اصلي آن بر اساس( T(nبیان مي
شود .
مثال:مرتب سازي حبابي را در نظر بگیرید .
n 1
2
n
)1+2+3+…+ )n-2) (n-1
مقایسه ) =(n-1مرحله اول
مقایسه ) =(n-2مرحله دوم
مقایسه ) =(n-3مرحله سوم
در الگوریتم مرتب سازي حبابي )(bobel sortعمل اصلي ،عمل مقایسه است .تعداد مقایسات در
این الگوریتم برابر است با n n 1یعني پیچیدگي الگوریتم در حالت معمولي n n 1مي با شد
2
2
.
مثال :جست و جوي دودویي )(binnary search
در روش جست و جوي دودویي فرض مي شود كه عناصر موجود مرتب هستند وقراراست عنصري
در میان آن ها پیدا شود براي سرعت بخشیدن به جست و جو عنصر مورد نظر با عنصر میان لیست
مقایسه مي شوداگر برابر باشد جست و جو خاتمه مي یابد وگرنه بررسي مي شود كه میانه لیست از
عنصر مورد نظر بزرگتر است یا كوچكتر اگر میانه لیست از عنصر جست و جو بزرگتر باشد جست و
جو را در بازه ي چپ لیست تكرار مي كنیم وگرنه در با زه ي راست لیست جست و جو انجام مي شود
این كار تا رسیدن به عنصر مورد نظر و یا پیدا نشدن آن تكرار مي شود .
nاگر nعنصر در اختیار ما باشد در روش جست و جوي دودویي حداكثر تعداد مقایسات برابر
log 2خواهد بود .از دو مثال فوق مشاهده مي شود كه ممكن است تعداد اعمال اصلي در یك
الگوریتم همواره مثل An+bنباشد.ممكن است تعداد اعمال اصلي تواني از nو یا Log nبدست
آید.
1
1
n 1 = 1
nn 1 = n2 n
2
2
2
2
n
براي سنجش الگوریتم ها به طور استاندارد آن ها را در گروه هایي دسته بندي مي كنند به این گروه
ها گروه هاي پیچیدگي مي گوییم .گروه هاي پیچیدگي معروفnعبارت اند از:
n
C
n
n^2
!n^2log n n^3 … 2^n 3^n n
n log
log
2
2
عدد ثابت
هنگام دسته بندي الگوریتم ها در گروه هاي پیچیدگي از 3نماد زیر استفاده مي شود:
: Big O
اگر پیچیدگي در گروه Oبزرگ قرار بگیرد به این معنا است كه الگوریتم در بدترین حالت پیچیدگي
اش در محدوده ي Oواقع شده است به عنوان مثال :
1 2 1
2
n n €O n
2
2
از دیدگاه نموداري ،نمودار الگوریتمي كه متعلق به Oیك پیچیدگي باشد زیر نمودار گروه پیچیدگي
n € O n2
قرار خواهد گرفت.
Ωامگا :
اگر یك تابع پیچیدگي (منظور رابطه اي است كه تعداد اعمال اصلي را بیان مي كند) متعلق به Ωیك
گروه باشد آن گاه تابع پیچیدگي شما در بهترین حالت در گروه پیچیدگي ذكرشده واقع خواهد شد به
بیان دیگر تابع پیچیدگي شما از نظر نموداري باالي گروه پیچیدگي یاد شده واقع مي شود.
: N € O n2تابع پیچیدگي
( : N 2 € Ω )nگروه پیچیدگي
نماد :Ө
اگر هم تابع پیچیدگي بتواند هم در گروه پیچیدگي Oهم در گروه پیچیدگي Ωواقع شود آن گاه مي
توان گفت تابع پیچیدگي متعلق به Өگروه پیچیدگي است .ساده ترین روش شناخت Өاستفاده از حد
و یا Limمي باشد .
اگر
مقداري ثابت =گروه پیچیدگي /تابع پیچیدگي Lim
∞n
آن گاه
(گروه پیچیدگي ) € Өتابع پیچیدگي
مثال:در جست و جوي خطي تعداد اعمال اصلي برابر با nبود (در بدترین حالت ) تابع پیچیدگي در
بد ترین حالت یعني F(n)=nخواهد بود.از آن جا كه Lim n/n=1آن گاه مي توان گفت
پیچیدگي روش جست و جوي خطي در بدترین حالت متعلق به ) Ө (nاست هم چنین چون كلمه
ي بد ترین حالت ذكر شده است مي توان گفت به )O (nتعلق دارد.
در مثال دوم Maxتعداد اعمال اصلي برابر با nاست و پیچیدگي آن متعلق به )Ө(nاست .
در مثال سوم) (sumپیچیدگي الگوریتم متعلق به ) Ө (nخواهد بود.
در مثال چهارم)مرتب سازی حبابی) تعداد اعمال اصلي از رابطه ي زیر بدست مي آید.
2
پیچیدگي این الگوریتم متعلق به Ө nمي باشد .
1 2 1
n n
2
2
= )F (n
در جست و جوي دودویي پیچیدگي الگوریتم در بدترین حالت Ө log n خواهد بود این جا نیز مي
n
توان گفت پیچیدگي متعلق به O log 2خواهد بود.
نکته :در رابطه با درختان نرمال گفته بودیم که یک درخت نرمال درختی است که عمق تمامی
شاخه
های آن تقریبا هم اندازه باشد .تعریف دقیقتری به نام درخت AVLوجود دارد .
درخت : AVLدرختی که تفاضل ارتفاع هر دو زیر درخت آن برابر با 0یا 1باشد .
تفاضل زیر درخت Aبرابر ، 0
تفاضل زیر درخت Bبرابر 1و
تفاضل زیر درخت Cبرابر 1است.
روش هاي مرتب سازي:
الگوریتم هاي مرتب سازي زیادي وجود دارد كه برخي از آن ها مطا لعه شده اند به عنوان مثال
2
روش مرتب سازي حبابي با پیچیدگي nونیز استفاده از یك درخت جست و جوي دودویي و
پیمایش Inorderآن با پیچیدگي( ) nlog nقبال بررسي شد.
مرتب سازي درج ساده یا :Insertion sort
در این روش لیستي از اعداد نا مرتب وجود دارد قصد داریم آن ها را یكي یكي برداشته و یك صف
اولویت صعودي به وسیله ي آن ها ایجاد كنیم هر عنصر جدید از ابتداي لیست مقایساتش را آغاز مي
كند وبا پیشروي در لیست در محل منطقي اش درج مي گردد.
مثال:در بدترین حالت وبهترین حالت θالگوریتم جه خواهد بود؟
7
2
9
4
6
8
3
7
2
7
2
7
9
2
4
7
9
2
4
6
7
9
2
4
6
7
8
9
2
3
4
6
7
8
9
در بهترین حالت یعني زماني كه عناصر به شكل نزولي مرتب هستند روش مرتب سازي درج تنها با
n-1مقایسه قادر است اعداد را مرتب كند در نتیجه مي توان گفت پیچیدگي الگوریتم در بهترین
حالت از درجه ي nمي با شد یا)(Ωnبرای بهترین حالت.
در بدترین حالت یعني زماني كه عناصر ساختاري صعودي دارند هر عنصر جدید مجبور است با تمام
2
عناصر لیست مقایسه شودوپیچیدگی آن) O( nمی شود.
1
2
3
4
5
1
1
1
2
2
1
2
3
)1+2+3+...+(n-1
2
3
nn 1 = 1 n2 1 n
1
2
3
4
Ө
(
)
n
2
2
1
2
3
4
5 4
2
مرتب سازي سریع یا :Quick sort
در این روش یكي از عناصر موجود در لیست را به عنوان عناصر محوري انتخاب مي كنند .تمام
عناصر لیست با عنصر محوري مقایسه مي شوند اگر عنصري كوچكتر باشد سمت چپ وگرنه سمت
راست قرار مي گیرد اعداد كوچكتر و بزرگتر از عنصر محوري 2لیست مجزا را به وجود مي آورند
براي هریك از لیست هاي بدست آمده عمل فوق را تكرار كنید این كار تا زماني كه تمام عناصر از
یكدیگر جدا شوند ادامه دارد تا nلیست تك عنصري به وجود مي آید.
5 7 3 9 1 4 6 8
اعداد را به صورت صعودی در نظر می گیریم :
5
)1+…+)n-1
= nn2 1
2
= 12 n2 12 n = O n
4
3
2
تعدادمقایسات
)(n-1
)(n-2
)(n-3
1
در این روش بدترین حالت زماني است كه هربار یك طرف محور كامال خالي باشد به عنوان مثال
(اعداد شكلي صعودي داشته باشند ) در این صورت مجموع تعداد مقایسات از رابطه ي زیر به دست
مي آید1+2+…+ )n-1) .
1
پس مي توان گفت پیچیدگي روش Quick sortدر بدترین حالت bigO n2مي باشد.
گونه اي است كه تعداد عناصر سمت راست و چپ آن تقریبا برابر است
در بهترین حالت عنصر به
n
logمرحله الزم است تا عناصر كامال جدا شود در هر مرحله
در این صورت حداكثر
2
حداكثر nمقایسه انجام مي شود بنابراین مي توان گفت كل مقایسات برابر است با
پس مي توان گفت پیچیدگي Quick sortدربهترین حالت Өn log nاست ویا n log n2
مي باشد .مي توان ثابت كرد در روش Quick sortدر حالت متوسط پیچیدگي اش nlog n
بیشتر نیست .
نكته :اگر اعداد كامال تصادفي باشد روش Quick sortدر روش مرتب سازي جز بهترین هاست.
مرتب سازي ادغام یا :Merge sort
در این روش لیست هاي حاوي nعنصر به دوزیر لیست هر
2
یك حاوی nعنصر شكسته مي شود هریك از دو عنصرزیر لیست
مجددا به دو بخش شكسته خواهد شد این عمل آن قدر ادامه
پیدا مي كند كه nلیست تك عنصري پدید آید هریك از لیست
هاي تك عنصري دو به دو در یكدیگر ادغام مي شوند عمل
ادغام به گونه ایست كه هر دو زیر لیست را به صورت مرتب
شده در زیر لیست ادغام مي نماید عمل ادغام زیر لیست ها آن
قدر تكرار مي شود كه یك لیست مرتب شده پدید آید.
از دیدگاه ساده تر مي توان گفت كه روش Merge sortبه نوع مقادیر ورودي وابستگي ندارد
مشابه با تحلیل الگوریتم مي توان گفت پیچیدگي Merge sortتا لحظه اي كه لیست ها تك عنصري
مي شوند برابر با( )n log nمي شود از طرفي اعمال تركیب تا رسیدن به لیست واحد نیز انعكاسي
از بخش فوقاني است پس پیچیدگي آن نیز n log nخواهد بود نتیجه اینكه پیچیدگي كل مراحل
همان ( )n log nاست زیرا ( (2n log nبا پیچیدگي )(n log nبرابر است (چون 2یك
ضریب ثابت است ) پس نهایتا به ) Ө( nlog nرسیدیم.
مرتب سازي هرمي یا :heap sort
تعریف درخت : heap
درختي است كه پدر مقدارش از فرزندانش بیشتر (كمتر)است .
براساس تعریف فوق دو گونه از درختان heapوجود دارد.
Min heap )2
Max heap )1
:Max heapدرختي است كه اوال ساختارش مثل یك درخت دودویي كامل است و عالوه بر آن مقدار
هر گره پدر از فرزندانش بیشتر باشد.
:Min heapدرختي است كه اوال ساختارش مثل یك درخت دودویي كامل است و عالوه برآن
مقدارهرگره ی پدرازفرزندانش کمتراست.
تعریف مشابهي را براي Min heapنیز مي توان ارائه داد .
در روش heap sortفرض مي كنیم كه درخت دودویي همانند یك درخت كامل رشد مي كند هر گره
جدید كه به درخت اضافه مي شود مقدار جدیدي را در خود خواهد داشت پس از درج مقدار جدید مي
بایست بررسي كنیم كه قانون درخت به هم نخورده باشد اگر چنین شد جاي فرزند و پدر را با یكدیگر
عوض مي كنیم این كار ممكن است چندین مرحله تكرار شود.
مثال:اعداد زیر را در یك درخت Min heapقرار دهید؟
2
1
6
7
4
3
9
5
پس از ایجاد یك Min heapاز اعداد ورودي مي توانیم آن ها را به شكل زیر از درخت حذف كنیم
به گونه اي كه اعداد حذف شده ترتیب صعودي داشته باشند .محتواي ریشه را با آخرین گره اي كه به
درخت اضافه شده جا به جا كنید سپس آخرین گره را به عنوان كوچكترین مقدار حذف نمایید این
اعمال را آن قدر تكرار كنید كه گره اي در درخت باقي نماند.
توجه داشته باشید كه در هر مرحله ممكن است مجبور باشید مقادیر گره را جا به جا كنید.
تحلیل پیچیدگي :heap sort
در درختان heapعمق درخت همواره به طور تقریب log2nاست اگر گره اي جدید به درخت
اضافه شود براي اینكه درخت Min heapباقي بماند ممكن است مقدار آن گره جدید مرتبا جا
به جا شده اگر این جا به جایي تا ریشه ي درخت ادامه پیدا كند تعداد این جا به جایي ها متناسب با
عمق درخت تقریبا log nخواهد شد حال اگر فرض كنیم كه nگره جدید قرار است به درخت اضافه
شود وبا هر اضافه شدن حداكثر log2nجا به جایي انجام پذیرد كل جا به جایي ها تقریبا برابر با
n log nخواهد شد در نتیجه پیچیدگي ساخت یك min heapحداكثرازدرجه ي (O (n logn
خواهد بود هنگام حذف گره ها نیز ممكن است نیاز به جا به جایي گره ها داشته باشیم كه این تعداد
نیز مي تواند تا عمق درخت ادامه داشته باشد در نتیجه همانند آنچه كه در تحلیل باال آمده پیچیدگي
حذف همه ي گره ها برابر با ) O( n log nخواهد بودپیچیدگي كل روش heap sortبرابر با
مجموع پیچیدگي هاي مربوط به قسمت ساخت درخت که پیچیدگی آن n log nو قسمت تخریب آن كه
پیچیدگي آن ) )nlog nمي با شد كه این پیچیدگي ))n log nرا در پي خواهد داشت .
n log n + n log n= 2 n log n nlog n
پیچیدگی کامل
پیچیدگی تخریب پیچیدگی ساخت
مرتب سازي مبنا یا : Radix sort
دراین روش ابتدا عناصربراساس كم ارزش ترین مكانشان مرتب مي شوند سپس آنچه بدست مي آید
را بر اساس مكان با ارزش بیشتر مرتب مي كنند این اعمال تا پرارزش تر ین مكان ادامه مي یابد.
مثال:اعداد زیر را به روش Radix sortمرتب كنید؟
125,290,43,321,443,118,12,20,39,110,256
بر اساس یکان
بر اساس دهگان
بر اساس صدگان
0 290,20,110
0
0 12,20,39,43
1 321
1 110,12,118
1 110,118,125
2 12
2 20,321,125
2 256,290
3 43,443
3 39
3 321
4
4 43,443
4 443
5 125
5 256
5
6 256
6
6
7
7
7
8 118
8
8
9 39
9 290
9
اگرmتعداد ارقام بزرگترین عددوnتعداد اعداد باشد پیچیدگی الگوریتم آن به صورت زیر است:
)T(n) € (m,n
توابع بازگشتي:
توابعي هستند كه در بدنه تابع خود آن تابع فراخواني مي شود .
مثال :با استفاده از توابع بازگشتي فاكتوریل nرا محاسبه كنید؟
n>=1
)n* fact (n-1
n ==0
1
n>=1
)n * (n-1
= ) fact (n
=!n
1
n=0
)int fact(int n
{
)if (n==1
;)return(1
else
;))return (n*fact(n-1
}
مثال هاي دیگري از توابع بازگشتي:
مثال :1با استفاده از توابع بازگشتي a^bرا محاسبه كنید؟
b>=1
b=0
a * a b1
b
=a
1
)int power (int a , int b
{
)If (b==0
;)return (1
else
;))return (a * power(a , b-1
}
) را حساب كنید؟a , b) با استفاده از توابع بازگشتي ب م م:2 مثال
b
if
a%b ==0
bmm(a,b)=
bmm (b , a%b)
int bmm (int a , int b)
{
If ( a%b ==0 )
return (b);
else
return (bmm (b , a%b ));
}
a%b !=0
مثال :3جستجوي دودویي را با استفاده از توابع بازگشتي پیاده سازي كنید؟
) int binsearch ( int s[n] , x
{
xرا با عنصر وسط لیست sمقلیسه كن .
اگر برابر باشد
بازگشت بده اندیس عنصر وسط را
وگرنه اگر بزرگتر باشد
;) , xنیمه سمت راست binsearch ( s
;) , xنیمه سمت چپ binsearch ( s
{
روش هاي merge sortو quick sortرا نیز مي توان به كمك توابع بازگشتي پیاده سازي كرد.
گراف ها:
هر گراف Gشامل دو مجموعه به نام هاي V,Eمي باشد .
: Vمجموعه اي متنا هي و غیر تهي از رئوس مي باشد.
: Eمجموعه اي از زوج راس ها كه به آن یال گفته مي شود.
) : V (Gمجموعه اي از راس هاي گراف G
) : E (Gمجموعه اي از یال هاي گراف G
براي نمایش یك گراف به شكل زیر عمل مي كنند.
گراف بدون جهت :
گرافي است كه در آن زوج رئوسي كه یك یال را نشان مي دهند ترتیبشان بي اهمیت است مثال اگر
v,uدو راس طرفین یك یال باشند آن گاه )(u,v) , (v,uهر دو یك یال را نشان مي دهند.
مثال زیر نمایشي از یك گراف بدون جهت است .
}V(G)={v1,v2,v3,v4
})E(G)={(v1,v2),(v2,v4),(v2,v3),(v4,v2
گراف جهت دار:
در گراف جهت دار هر یال با یك زوج مرتب نشان داده مي شود به عنوان مثال یال ><u,vدر یك
گراف جهت دار یالي است كه از uآغاز شده و به vختم مي شود .
مثال زیر نمونه اي از یك گراف جهت دار است :
}V(G2)={V1,V2,V3,V4,V5
>E(G2)={<V1,V2>,<V2,V1>,<V1,V3>,<V5,V3
}>,<V5,V4>,<V4,V1>,<V2,V4
نكته:معموال در داخل هر راس فقط شماره ي آن نوشته مي شود .
در گراف هایي كه با آن كار مي كنیم محدودیت هاي زیر را در نظر مي گیریم اگر چه گراف ها مي
توانند این محدوده را نداشته باشند.
)1یك گراف از هر راس به خودش یالي ندارد(به چنین یال هایي Self edgeیا خودیالی گفته مي شود) .
)2در یك گراف یك یال نباید تكرار شود به چنین گراف هایي Multi graphگفته مي شود به این
گراف ها ،گراف چند كاره نیز گفته مي شود .
nn 1
n|
2
اگر یك گراف بدون جهت شامل nراس داشته باشیم حداكثر تعداد یال هاي آن برابر با n(n-1)/2
مي باشد.
n
e
1
0
2
1
3
3
4
6
5 10
nn 1
گراف بدون جهت تعداد یال هاي آن 2 باشد با وجود nراس گراف كامل نامیده مي شود.در
یك گراف جهت دار بدون راس تعداد یا ل ها برابر )n(n-1مي باشد.
اگر در یك گراف مانند Gیالي به صورت )(u,vوجود داشته باشد آن گاه رئوس u,vرا مجاور
گویند و یال )(u,vرا یك یال متالقي روي u,vمي نامنددر واقع مي توان گفت یال هاي متالقي روي
راس vیال هایي هستند كه یك طرف آن ها راس vمي باشد به عنوان مثال گراف زیر را در نظر
بگیرید.
در این گراف راس 0,1مجاورند و همچنین رئوس )(0,3) ,(3,2) ,(0,2هریك دو به دو مجاور هم
هستند اما راس 1,2مجاور هم نمي باشند در این گراف یال هاي متالقي روي راس 0عبارت اند
از .(1,0),(2,0),(3,0):
مفاهیم فوق در یك گراف جهت دار نیز مطرح مي شود اگر یال ><u,vیك یال جهت دار باشد آن گاه
راس uرا مجاور به راس vو راس vرا مجاور از راس uمي گویند همچنین یال ><u,vروي دو
راس u,vمتالقي است.
مثال :در گراف زیر راس 0به راس 1,3مجاور است.
راس 3مجاور از راس 0است یال ها ي متالقي روي راس 0عبارت اند از :
><0,1> , <2,0>,<0,3
یك زیر گراف از گراف :G
گرافي مانند ́Gرا داریم به نحوي كه )E(Ǵ) E(G), V(Ǵ) V(Gباشد.
به عنوان مثال گراف زیر را در نظر بگیرید تعدادي از زیر گراف ها ي Gعبارت اند از :
مسیر یا :Path
در یك گراف بدون جهت یك مسیر از راس Uبه راس Vدنباله اي از رئوس مثل Ui1 i2 … ik
Vمي باشد به طوري كه ((u,i1),(i1,i2(,….)ik, Vهمگي یال هایي در مجموعه ي )E(G
مي باشد .
مسیری از 0تا 4
0,3,2,1,4
0,3,1,4
0,4
به عنوان مثال در گراف فوق رئوس 0,3,2,1,4مسیري را از 0تا 4مشخص مي كنند
(مسیرهاي دیگري نیز مي توان از 0به 4پیدا كرد )
در یك گراف جهت دار نیز مي توان مسیري را تعریف كرد تفاوت آن فقط این است كه مي بایست
مجموعه ي یال هاي ><u,i1>,<i1,i2>,…<ik,vهمگي در مجموعه ي )E(Gوجود داشته
باشد.
طول مسیر:
طول مسیر عبارت است از تعداد یال هاي موجود در آن مسیر.
مثال طول مسیر 0تا 4از مسیر 0 , 3 , 2 , 1 , 4برابر 4و از مسیر 0 , 3 , 1 , 4برابر 3است.
مسیر ساده:
مسیري است كه احتماال جز اولین و آخرین راس تمام رئوس متمایز باشد.
یك مسیر مي تواند جهت دار یا بدون جهت باشد.
: 0 , 1 , 2 , 3 , 5مسیر ساده
: 0 , 1 , 2 , 3 , 4 , 1 , 2 , 3 , 5مسیر غیر ساده
سیكل (چرخه):
مسیري ساده است كه راس اول وآ خر آن یكي است .به عنوان مثال در این گراف باال ) (1,2,3,4یك
سیكل را به وجود آورده است( .در یك سیكل فقط رئوس اول وآ خر تكراري هستند)
هم در گراف جهت دار و هم بدون جهت مي توان سیكل را اعمال كرد.
در گراف هاي جهت دار معموال به تعاریف فوق كلمه ي جهت دار اضافه مي شود(مثالً مي گویند
سیكل جهت دار یا مسیر جهت دار) در یك گراف بدون جهت مثل Gدو راس را همبند گوییم در
صورتي كه بتوان مسیري از یكي به دیگري پیدا كنیم .
گراف بدون جهت همبند گرافي است كه بتوان بین هر دو راس آن مسیري پیدا كرد به عنوان مثال
گراف زیر یك گراف غیر همبند است.
یك مولفه ي اتصال مانند Hاز یك گراف بدون جهت عبارت است از بزرگترین زیر گراف همبند در آن
گراف .به عنوان مثال در گراف روبرو مولفه اتصال G2میشود چون تعداد عناصر G2از G1
بیشتر است.
درخت یك گراف هم بند و بدون چرخه است.
گراف كامال همبند:
گرافي جهت داراست كه به ازاي هرزوج u,vبتوان مسیري جهت داراز uبه vواز vبه uپیدا كرد.
درجه گراف بدون جهت:
درجه ي یك راس عبارت است ازتعداد یال هاي متالقي روي آن راس درمثال فوق درجه ي راس 5=4
و 0=1مي باشد.
درجه ي وارده:
درجه ي وارده به یك راس در گراف جهت دار عبارت است از تعداد یال هایي كه به آن راس ختم مي
شود .
راس
درجه
درجه
درجه
خارجه
وارده
1
2
3
1
0
1
1
0
2
0
2
2
1
1
2
3
درجه خارجه :
اگر Gیك گراف بدون جهت با nراس باشد كه درجه ي راس Iام برابر با
یك گراف است رابطه ي زیر صحت دارد.
نصف حاصل جمع درجه تمام رئوس
معموال اگر كلمه ي جهت دار گفته نشود منظور یك گراف بدون جهت است.
diو eتعداد یال هاي
e = ) ∑ di (/2
نمایش گراف:
)1ماتریس مجاورتي :
براي یك گراف Gبا nراس ماتریس مجاورتي آرایه اي دو بعدي و n*nمي باشد كه آن را Aمي
نامیم اگر )(i,jدر گراف بدون جهت یا یال ><i,jدر گراف جهت دار وجود داشته باشد آن گاه
A(i,j)=1وگرنه 0خواهد بود.
0
0
0
0
A[i][j]=0
اگر از iبه jیال نداشته باشیم
اگر از iبه jیال نداشته باشیم
A[i][j]=1
0
0
0
1
1
0
1
0
0
0
1
0
توجه :ماتریس مجاورتي گراف هاي بدون جهت روي قطر اصلي متقارن است اما در گراف هاي
جهت دار ممكن است متقارن نباشد .هر سلول از ماتریس مجاورتي مي تواند یك بیت از حافظه را
اشغال كند در نتیجه براي یك گراف جهت دار n^2بیت الزم است.
)2لیست مجاورتي :
درا ین روش nسطر ماتریس مجاورتي را به وسیله ي nلیست پیوندي نشان مي دهند در واقع
براي هر راس از گراف Gیك لیست پیوندي وجود دارد.
یال هاي وزن دار:
در بسیاري از كاربردها به هر یال عددي نسبت داده مي شود كه وزن هر یال جهت دار نشان دهنده ي
فاصله ي هر دو راس بوده باشد .در چنین گراف هایي ماتریس مجاورتي مي تواند حاوي وزن یال ها
باشد به عنوان مثال در گراف زیر ماتریس مجاورتي به شكل زیر خواهد بود.
∞
15
12
0
14
13
0
12
17
0
13
15
0
17
14
∞
لیست مجاورتي مي تواند براي نمایش گراف هاي وزن دار به كار گرفته شود كافي است به هر گره
در لیست پیوندي فیلدي جهت وزن آن اضافه كنیم.
شبكه :گرافي است كه یال هاي آن وزن داشته باشد.
نكته :درجه هر رأس در یك گراف بدون جهت برابر است با تعداد گره هاي مربوط به آن رأس در لیست
مجاورتي مربوط به آن .واضح است كه تعداد گره هاي موجود در كل لیست مجاورتي برابر است با
2برابر تعداد یال ها .
نكته :در یك گراف جهت دار تعداد كل گره هاي لیست مجاورتي برابر با تعداد یال هاي گراف مي باشد.
نكته :در گراف هاي جهت داري كه بررسي كردیم لیست مجاورتي گره هایي را نشان مي داد كه مجاور
از گره موردنظر ما بودند.
5
1
2
3
4
لیست مجاورتي معكوس:
در برخي از موارد مي خواهیم رئوس مجاور به رأس موردنظرمان را مشخص كنیم .درچنین مواردي
از لیست مجاورتي معكوس استفاده مي شود .در لیست مجاورتي معكوس همانطور كه گفته شد به
ازاي هر رأس رئوس مجاور به آن در لیست پیوندي قرار مي گیرد.
با توجه به گراف فوق ،لیست مجاورتي معكوس را ایجاد كرده ایم:
پیمایش گراف :
همانند درخت ها مي توان گراف ها را نیز پیمایش كرد .پیمایش یك درخت به 2شكل انجام پذیراست .
این 2روش عبارتند از :
-1روش جستجوي عمقي )(DFS
-2روش جستجوي سطحي )(BFS
در هر 2روش با یك رأس كار را آغاز مي كنیم و به ترتیبي كه خواهیم گفت پیشروي خواهیم كرد.
توجه :اگرچه این 2روش درگراف هاي جهت دار امكانپذیر است ما آن را در گراف هاي بدون جهت
شرح مي دهیم .
روش جستجوي عمقي ): (DFS
در این روش با رأس Bكا را آغاز مي كنیم یعني رأس Bرا مالقات مي كنیم سپس رأسي مانند Wرا
پیدا مي كنیم كه با رأس Bمجاور است و قبالً مشاهده نشده .این كار براي رأس Wنیز تكرار مي
شود و آنقدر اعمال فوق را تكرار مي كنیم كه تمام رئوس مجاور به دورترین گره از Bمالقات شده
باشد .اگر رأسي براي مالقات مانده باشد به عقب برگشته واین عمل را براي آن نیز تكرار مي كنیم.
به مثال زیر توجه كنید:
0
2
6
1
4
5
3
7
فرض كنید مي خواهیم پیمایش DFSرا از گره صفر آغاز كنیم.
0,1,3,7,4,5,2,6
براي این كار اگر رأس ) (u,vرا درنظر بگیرید یكي از پیمایش ها را روي رأس uانجام دهید اگر رأس
vنیز در آن پیمایش موجود باشد این 2رأس در یك مؤلفه همبند قرار دارند وگرنه خیر.
1
2
4
3
5
7
6
درخت پوشا:
یك گراف را درنظر بگیرید .فرض كنید این گراف بدون جهت بوده و همبند است .درخت پوشا در یك
گراف درختي است كه تمام رئوس را پوشانده باشد(.توجه داشته باشید كه درخت خود یك گراف
همبند است با این شرط كه سیكل یا دوره نداشته باشد).
اگر یك گراف شامل nرأس باشد درخت پوشا آن دقیقا ً ) (n-1یال خواهد داشت.
نكته :با استفاده از جستجوي عمقي یا سطحي مي توان درخت پوشا را بدست آورد.
0
2
: 0 , 1 , 3 , 7 , 4 , 5 , 2 , 6پیمایش DFS
: 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7پیمایش BFS
6
1
4
5
3
7
با توجه به شكل فوق كافي است یال مرتبط با هر رأس جدیدي كه از طرف قبلي مشاهده مي شود را به
درخت اضافه كنید.
مولفه های دو اتصالی)دو طرفه(:
به رئوسی از گراف که با حذف آنها و یالهای منتهی به آنها دو زیر گراف مجزا )یا بیشتر( پدید می
آید رأس محوری گویند .به عنوان مثال گراف زیر را در نظر بگیرید:
0
8
9
1
7
5
6
2
3
4
در گراف فوق رئوس شماره 7,5,3,1رئوس محوری
می باشد.
گراف دو اتصالی ،گراف همبندی است که نقطه محوری نداشته باشد.
درخت پوشای کمینه یا با کمترین هزینه ):(minimum spaning tree
یک گراف بدون جهت وزن دار را در نظر بگیرید از بین درختان پوشایی که می توان برای چنین
گرافی در نظر گرفت می توان درخت یا درختانی را پیدا کرد که مجموع وزن یالهای آن
درختان پوشا minimumباشد.
برای پیدا کردن درخت پوشای کمینه سه الگوریتم مختلف وجود دارد :
-1الگوریتم راشال(کروسکال :)kruskal
در این الگوریتم ابتدا تمامی رئوس گراف را جدای از هم در نظر می گیریم (در واقع اگر گراف شامل
nرأس باشد nمجموعه تک عنصری خواهیم داشت ).سپس یالها را به ترتیب صعودی مرتب می
کنیم.حال تا زمانی که ) (n-1یال از بین مجموعه یالها انتخاب نشده است (و در درخت قرار
نگرفته) اعمال زیر را تکرار کنید :
: 10 12 14 16 18 22 24 25 28مجموع وزن یالها
}) (n-1): E(T)={(0,5),(2,3),(1,6),(1,2),(4,3),(4,5یال
T
یال با وزن کمینه را از مجموعه یالها بردارید بررسی کنید که آیا اضافه شدن این یال به درخت
پوشا مجاز است یا نه (.در صورتی که سیکل ایجاد کند مجاز نخواهد بود).
در صورت مجاز بودن یال ،آن را به درخت اضافه کنید وگرنه آن را کنار بگذارید.
-2الگوریتم پرچم:
در این الگوریتم یکی از رئوس گراف را به عنوان رأس شروع در نظر میگیرد نزدیک ترین رأس
به آن را پیدا می کند .آن رأس به همراه یالی که آن را به رأس شروع وصل می کندبه ساختار
درخت اضافه می گردد (در این حالت درخت به وجود آمده شامل 2رأس خواهد بود ).سپس
نزدیک ترین رأس به درخت حاصل را پیدا می کندآن را به همراه یال مربوطه به درخت اضافه
می کند.اعمال فوق آنقدر تکرار می شود تا اینکه تمام رئوس دیگر نیز به درخت اضافه شده
باشد(.در شکل 1رأس شروع گره 6می باشد)
2
1
نکته :یک گراف ممکن است بیش از یک درخت پوشای کمینه داشته باشد .اگر گرافی چند درخت
پوشای کمینه داشته باشد می بایست وزن مجموع یالها در تمام درختان پوشای کمینه برابر بوده
باشد.
نکته :الگوریتم راشال و پرچم تضمین می کند که در هر گراف دلخواه (بدون جهت ،همبند) درخت
پوشای کمینه را به دست می آورد .
-3الگوریتم سولین:
در این الگوریتم ابتدا گره ها به شکل مجزای از هم در نظر گرفته می شود سپس به هر گره یال با
کمترین وزن متالقی روی آن انتخاب می شود در این صورت چند درخت در گراف پدید می آید .
بین هر دو درخت مجزا یالی انتخاب می شود که وزن آن کمینه بوده وبتواند دو درخت را به هم
وصل کند این کار تا رسیدن به یک درخت واحد تکرار می شود (.در شکل 1رأس شروع گره
0میباشد)
2
1
نکته :الگوریتم فوق نیز تضمین می کند که درخت پوشای کمینه را تولید کند.
نکته:اگر گراف بیش از یک درخت پوشای کمینه داشته باشد ممکن است هر الگوریتم به شیوه
خود به یکی از آنها برسد .
نکته های فراموش شده:
پیمایش ترتیب سطحی درختان دودویی(پیمایش سطح – ترتیب):
یکی از ساده ترین پیمایش ها ،پیمایش ترتیب سطحی است .کافی است از ریشه (سطح اول)
شروع کنید آن را مالقات کنید و سپس فرزندان ریشه را (سطح بعدی) از چپ به راست
مالقات کنید سپس در سطح بعدی و همین طور تا آخر.
برای انجام چنین پیمایشی میتوان از یک صف کمک گرفت .بدین منظور ریشه را در ابتدای صف
قرار دهیدسپس آن را از صف حذف کرده(چاپ کنید) فرزندان آن را به ترتیب از چپ به راست
در صف قرار دهید به ازای هر فرزند می بایست ابتدا آن را حذف کرده (چاپ کنید ) و
فرزندان آن را از چپ به راست به انتهای صف اضافه کنید این کار تا اضافه شدن تمام گره ها
A
به صف و حذف تمام آن ها از صف تکرار می شود.
C
A B C D E F G H
B
F
E
H
D
G
پایان