درختهایدودوئینخکشیشده
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 2026 Paperzz