درختهایدودوئینخکشیشده Threaded Binary Trees سرفصلها: • تعریف • پیمایش • گسترشمفهوم • جستجو • درجیکگره • حذفیکگره 1 تعریف دردرختدودوئیدریکبرگاشارهگرهابهفرزندچپوفرزندراست،تهیاست. به علت استفاده نکردن از اشارهگرهای فرزند در برگ ها مقداری از حافظه تخصیص دادهشدهعمالبدوناستفادهمیماند. میتوانازایناشارهگرهابرایبهینهکردنپیمایشمیانترتیباستفادهکرد. تا بجای استفاده از الگوریتم بازگشتی پیمایش میان ترتیب از یک الگوریتم غیر بازگشتی)(iterativeاستفادهکنیمکهوقتکمتریمیگیرد. 2 تعریف دریکدرختدودوئی،دریکبرگ،اشارهگرهامقدارتهیدارند. میتوان محتویات اشارگر های چپ و راست تهی را طوری عوض کرد که به گره بعدیوقبلیدرپیمایشمیانترتیبدرختدودوئیاشارهکنند. بهاینترتیبوقتیبهیکگرهبرگمیرسیم،برایپیداکردنگرهبعدینیازیبه فراخوانیبازگشتینیست،چونآدرسگرهبعدیرادرفیلداشارهگرگرهبرگدر اختیارداریم. بهایناشارهگرهانخ)(Threadمیگوییم. 3 تعریف بنا براین در این روش باید مشخص شود که یک اشاره گر از نوع اشاره گر به فرزنداناست(گرههائیکهدرسطوحپائینترقراردارند)ویااشارهگریاز نوع نخ است که به گره ها ی ancestorکه در سطوح باال تر قرار دارند اشارهمیکند. برایتعییناینموردازدومتغییرBooleanاستفادهمیکنیم. ;typedef struct NODE *PNODE {NODE int ;label ;PNODE leftChild, rightChild bool ;LeftThread, RightThread 4 struct } تعریف مثال: اشارهگرفرزندراستدرگرههایبرگکهازنوعنخاستبهگرهبعدیدر ترتیبپیمایشمیانترتیباشارهمیکند. 6 8 11 13 3 5 7 1 اشارهگر ازنوعنخ 9 5 پیمایشمیانترتیبدردرختدودوئینخکشیشده آغاز پیمایش از سمت چپترین گره خواهد بود .مقدار آن را چاپ میکنیم و به سراغنخ(اشارهگر)سمتراستآنمیرویم. زمانیکهبااستفادهازیکنخبهیکگرهمیرسیممقدارآنگرهراچاپکردهوبه سراغزیردرختراستآنمیرویم. درهنگامیکهواردیکزیردرختجدیدمیشویم، ابتداسراغسمتچپترینگرهرفتهومقدارآنراچاپمیکنیمو بههمینترتیببهکارخودادامهمیدهیم. 6 پیمایشمیانترتیبدرخت 6 خروجی 1 8 11 13 3 7 9 5 1 شروعازچپترینگرهوچاپآن 7 پیمایشدرخت 6 خروجی 1 3 8 11 13 3 7 9 5 1 گذرازنخسمتراستوچاپمقدارجدید 8 پیمایشدرخت 6 خروجی 1 3 5 8 11 13 3 7 9 5 1 رفتنبهسمتزیردرختراست،پیداکردن چپترینگرهوچاپکردنآن 9 پیمایشدرخت 6 خروجی 1 3 5 6 8 11 13 3 7 9 5 1 گذرازنخسمتراستوچاپمقدارجدید 10 پیمایشدرخت خروجی 1 3 5 6 7 6 8 11 13 3 7 9 5 1 رفتن به سمت زیر درخت راست ،پیدا کردن چپترینگرهوچاپکردنآن 11 پیمایشدرخت خروجی 1 3 5 6 7 8 6 8 11 13 3 7 9 5 1 گذرازنخسمتراستوچاپمقدارجدید 12 پیمایشدرخت خروجی 1 3 5 6 7 8 9 6 8 11 13 3 7 9 5 1 رفتن به سمت زیر درخت راست ،پیدا کردن چپترینگرهوچاپکردنآن 13 پیمایشدرخت خروجی 1 3 5 6 7 8 9 11 6 8 11 13 3 7 9 5 1 گذرازنخسمتراستوچاپمقدارجدید 14 پیمایشدرخت خروجی 1 3 5 6 7 8 9 11 13 6 8 11 13 3 7 9 5 1 رفتن به سمت زیر درخت راست ،پیدا کردن چپترینگرهوچاپکردنآن 15 پیمایشدرخت : کدالگوریتمغیربازگشتیبرایپیمایشمیانترتیب Thread-Inorder (T: Tree) { var P: position; p = NEXT(T); // The next node in inorder traveral while p ≠ Root do { write (p^.data); p = NEXT(p); } } 16 پیمایشدرخت الگوریتمغیربازگشتیبرایپیداکردنعنصربعدیدرپیمایشمیانترتیب: Given a node Node, this algorithm returns its next node P in in-order traversal NEXT (Node: Position):Position { ;var P: position p = Node^.RC; // P is the right child of Node if Node^.RightIsThread == FALSE then while p^.LeftIsThread == FALSE do p = p^.LC // P becomes its left child // p is the next node in in-order traversal ;return p } -1اگراشارهگرسمتراستنخباشد،گرهبعدیدرپیمایشمیانترتیبگرهیاستکهRCبهآناشارهمیکندکهدربرنامهفوقباP نشاندادهشدهاستکهReturn pآنرابرمیگرداند. -2اگراشارهگرسمتراستنخنباشدوبهفرزنداشارهکند،الگوریتمبرایپیداکردنگرهبعدیبهسراغگرهسمتراسترفتهوسپستا زمانیکهگرهسمتچپنخنباشد،بهسمتچپمیرود .چپترینفرزندزیردرختراستگرهبعدیدرپیمایشمیانترتیباست. 17 گسترشمفهوم درمدلفوقهمچناننیمیازاشارهگرهایگرههایبرگبدوناستفاده باقیمیمانند. میتوانازایناشارهگرهایاستفادهنشده(اشارهگرفرزندچپ)برایاشاره کردنبهگرهقبلیدرپیمایشمیانترتیباستفادهکرد. بااینکارمیتوانعملپیمایشرابهصورتبرعکس(ترتیبازراستبه چپمیانترتیب)انجامدادویاحتیازآنبرایپیمایشپسترتیب استفادهکرد. 18 گسترشمفهوم مثال:توجهکنیدکهبرخیازبرگهابادواشارهگرازنوعنخبهگرههایپدرانAncestors خوداشارهمیکنند. 19 گسترشمفهوم مثال:یکدودوئیدرختنخکشیشدهکاملوپیمایشمیانترتیبآن H D B E A I K F J C G 20 جستجودردرختدودوئینخکشیشده جستجو در درختهای نخکشی شده بسیار شبیه روش جستجو در درختهایجستجویدودوییمیباشد، بااینتفاوتکهدراینجابایدبهتفاوتبیناشارهگرازنوعنخواشارهگربه فرزندانتوجهویژهایداشتهباشیم. درجستجو،زمانیکهبهگرهیکهدارایاشارهگریازنوعنخاستبرسیم یعنیجستجوخاتمهیافتهاستومقدارموردنظرپیدانشدهاست. به جز این مورد تفاوتی دیگر میان جستجوی این دو گونه درخت وجود ندارد. 21 جستجو دردرختدودوئینخکشیشده کدجستجودردرخت جستجویدودوئینخکشیشده باشدk گرهیراپیداکنیمکهدارایلیبلمساوی :اشارهگریبهریشهدرختاستroot NODE* search(PNODE root, int k) { if(root->label == k) return root; if( k < root->label) {//move toward left sub-tree // root of sub-tree must be a real child, // not being pointed by a thread if(!root->LeftThread && root->leftChild != null) return search(root->leftChild, k); else return null; } if( k > root->label) {// move toward right sub-tree // root of sub-tree must be a real child, // not being pointed by a thread if(!root->RightThread && root->rightChild != null) return search(root->leftChild, k); else return null; } } 22 جستجو دردرختدودوئینخکشیشده درختهاینخکشیشدهبرایدرختهایدودویبطورعام تعریفشدهاند. بنابراینمیتوانیمدرختجستجویدودوئینخکشیشدهرانیز تعریفکنیموعملیات جستجو،درجوحذف رابرایآنتعریفنمائیم. 23 درجگرهجدید دریک درختجستجویدودوئینخکشیشده درجگرهجدیددردرختهایجستجویدودوئینخکشیشدهتفاوتچندانی بادرختهایجستجویدودوییندارد. امابایدبرایگرهجدیدنخهایآنرابهگرهبعدوقبلازآنمتصلکرد. فرض کنید گره جدید nکه به درخت اضافه میشود ،فرزند راست پدرش )(pباشد. دراینحالتگرهقبلیnهمانpمیباشد(چرا؟):خاصیتدرختجستجویدودوئی. وگرهیبعدی،nگرهیبعدیpقبلازاینکهnبهدرختاضافهشود،است. حالتفرزندچپبودندقیقاقرینهحالتیاستکهدرباالذکرشد. 24 درجگرهجدید دردرختجستجویدودوئینخکشیشده مثال:اضافهکردنگره5 Node n before insertion 6 6 8 8 3 7 5 1 3 7 Node 5 inserted 25 5 1 درجگرهجدید دردرخت جستجویدودوئینخکشیشده بهدرختn کدتابعبرایدرجگرهجدید :)5(اضافهکردنگره void insert(PNODE root, PNODE n) { PNODE p; // find p, the parent of n, using BST-insert // parent of node 5 is node 3 in previous example PNODE templ , tempr; templ = p->leftChild; //left-child pointer of 3 before 5 is inserted tempr = p->rightChild; //right-child pointer of 3 before 5 is inserted // shown as a thread pointing to node 6 if(n->label < p->label) { //determine the left or right child p->leftChild = n; p->LeftThread = false; n->leftChild = templ; n->rightChild = p; } else { p->rightChild = n; p->RightThread = false; n->leftChild = p; n->rightChild = tempr; } n->LeftThread = n->RightThread = true; } 26 حذفیکگرهدردرختجسسجویدودوئی در حذف گره در درختهای جستجوی دودوئی نخکشی شده ،عالوه بر حفظ ویژگی درخت جستجوی دودویی ،باید تعدادی لینک را نیز به روز رسانیکنیم. گاهیاینکارممکناستآساننباشد. درزمانحذفیکگرهpباید2پارامترزیررابدانیم: • پدرگرهq:p • Pفرزندراستپدرشqبودیافرزندچپآن باتوجهبهدوپارامترباال4،حالتزیربرایحذفگرهقابلتصوراست. 27 حذفگره: حالتاول p داراییکنخدرسمتراستویکفرزنددرسمتچپباشد. دراینحالت2عملزیررابایدانجامدهیم: .1اشارهگرچپqبهفرندچپpاشارهکندq.leftchild = p.eftchild . .2اگر گره قبلی pدر پیمایش میانترتیب گره tباشد (نخ سمت راست tبه pاشاره میکند)،آنگاهنخسمتراستtرابانخسمتراستpجایگزینمیکنیم. t.rightChild = p.rightChild 28 :حذفگره حالتاول : کدبرایحالتاول //<find p, parent q, and right/left relation, determine the //case> q->leftChild = p->leftChild; PNODE t = p->leftChild; while(!t->RightThread) { t = t->rightChild; } t->rightChild = p->rightChild; 29 حذفگره: حالتدوم p داراینخسمتراستونخسمتچپباشدیابهعبارتبهتریکبرگ باشد. دراینحالتتنهایککارالزماست:اگرpفرزندچپ(راست)qبود،آنگاه اشارهگرسمتچپ(راست)،qتبدیلبهنخمیشود. ایناشارهگربهگرهایاشارهمیکندکهقبالنخسمتراست(چپ)pبه آناشارهمیکردهاست. 30 :حذفگره حالتدوم : کدبرایحالتدوم //<find p, parent q, and dir, determine the case> if(dir == "left") { q->LeftThread = true; q->leftChild = p->leftChild; } if(dir == "right") { q->RightThread = true; q->rightChild = p->rightChild; } 31 حذفگره: حالتسوم فرزندسمتراستpیعنی rداراینخسمتچپباشد. فرضکنیدکهqپدرpباشد. دراینجاکافیاستکهrراباpجایگزینکردهواشارههایمربوطرابهروز کنیم: • qکهبه pاشارهمیکرده،حاالبهrاشارهکند. • اشارهگرسمتچپrمساویاشارهگرسمتچپpشود. • هرگرهدیگریکهبهpاشارهمیکرد،اکنونبهrاشارهکند(.مانندنخگره)l 32 حذفگره: حالتچهارم فرزندسمتراست(pیعنیگره)rدارایفرزندچپباشد. دراینحالتبایدگرهیبعدیpدرپیمایشمیانترتیب،یعنیsراپیداکنیم. همچنینبایدپدر،sبنامkراهمپیداکنیم. سپسsراجایگزینpکردهودرمواردالزماشارهگرهارابهروزکنیم. اینحالتخودبه2زیرحالتدیگرشکستهمیشود. 33 حذفگره: حالتچهارم()1 در این حالت sخود دارای فرزند راست است با نام ،dاینجا نیازی به بروز کردن اشارهگرنخچپdنیستزیرابهصورتپیشفرضبهsاشارهمیکند. کارهایالزم: • بهروزکردناشارهگرپدر(pیعنی)qکهحاالبایدبهsاشارهکند. • بهروزکردناشارهگرپدر.)k(s • بهروزکردناشارهگر.s • بهروزکردننخسمتراستگرهقبلی(pدرپیمایشمیانترتیب) دراینمثالگرهقبلیpگرهuاست. بنابرایننخراستuبجایاینکهبهpاشارهکندبهsاشارهخواهدکرد. 34 :حذفگره )1(حالتچهارم :نوعاول، کدبرایحالتچهارم <find p, s, k, d, parent p: q, and dir, determin the case> if(dir == "right") {q->rightChild = s;} if(dir == "left") {q->leftChild = s;} s->hasLeftThread = false; s->leftChild = p->leftChild; s->rightChild = p->rightChild; k->leftChild = d; PNODE t = p->leftChild; while(!t->hasRightThread) { t = t->rightChild; } t->rightChild = s; 35 حذفگره: حالتچهارم()2 دراینحالتsداراینخسمتراستاست،یابهعبارتبهترsیکبرگاست. تفاوت این حالت با حالت قبل این است که اشارهگر سمت چپ kبه نوع نخ تغییر حالتمیدهد. کارهایالزم: • • • • بهروزکردناشارهگرپدر.p بهروزکردناشارهگرپدر.)k(s بهروزکردناشارهگر.s به روز کردن نخ سمت راست گره قبلی ( pدر پیمایش میانترتیب) .یعنی بروز کردن نخسمتراستu 36 :حذفگره )2(حالتچهارم :نوعدوم، کدبرایحالتچهارم <find p, s, k, d, parent p: q, and dir, determin the case> if(dir == "right") {q->rightChild = s;} if(dir == "left") {q->leftChild = s;} s->LeftThread = s->RightThread = false; s->leftChild = p->leftChild; s->rightChild = p->rightChild; k->LeftThread = true; PNODE t = p->leftChild; while(!t->RightThread) { t = t->rightChild; } t->rightChild = s; 37 پایان قسمتدومدرختها درختAVL 38
© Copyright 2025 Paperzz