Presentation is loading. Please wait.

Presentation is loading. Please wait.

درختان 3.

Similar presentations


Presentation on theme: "درختان 3."— Presentation transcript:

1 درختان 3

2 Heaps for searching جستجو در Heap:
به ريشه نگاه مي کنيم. اگر کوچکتر بود، به فرزندان سمت راست و چپ نگاه مي کنيم. از هر نودي که کوچکتر باشد، به فرزندان سمت راست و چپ آن نود نگاه مي کنيم. ممکن است که تمام نودها را ببينبم، لذا، در بدترين حالت، جستجو O(n) خواهد بود. زمان کل ساخت و استفاده از heap: درست کردن heap: nO(log2n) n جستجو: هر کدام O(n) nO(n) O(n log2n + n2)

3 Heaps for Searching Heap فقط براي مسائلي خوب است که يک عنصر مشخص (مثل بزرگترين يا کوچکترين) مورد نظر باشد. مي خواهيم راه حلي پيدا کنيم که جستجوي آن براي هر آيتم O(logn) باشد. البته در heap مي توانيم تمام عناصر را تک تک حذف کنيم تا به يک ليست مرتب نزولي برسيم. به اين روش Heapsort گفته مي شود. ساخت heap: O(nlog2n) استخراج ليست مرتب: O(nlog2n)

4 A Better Way to Search: Binary Search Trees
درخت جستجوي دودويي: درخت دودويي صفر نود يا بيشتر اگر >0 نود: هر نود داراي يک کليد يکتا است. کليد تمام نودهاي زير درخت سمت چپ نود، ازخود نود کمتر است. کليد تمام نودهاي زير درخت سمت راست نود، ازخود نود بيشتر است. زير درختهاي سمت چپ و راست نيز درخت جستجوي دودويي هستند.

5 Binary Search Trees 60 30 70 5 40 2 80 65 کليدهاي يکتا
نودهاي سمت چپ کمتر از ريشه نودهاي سمت راست بيشتر از ريشه زير درختهاي سمت چپ و راست نيز درخت جستجوي دودويي هستند. کليدهاي يکتا نودهاي سمت چپ کمتر از ريشه نودهاي سمت راست بيشتر از ريشه زير درختهاي سمت چپ و راست نيز درخت جستجوي دودويي هستند.

6 Binary Search Trees 20 15 25 12 22 درخت جستجوي دودويي نيست.
فرزند سمت راست 25 ازخودش کمتر است. 18 کليدهاي يکتا نودهاي سمت چپ کمتر از ريشه نودهاي سمت راست بيشتر از ريشه زير درختهاي سمت چپ و راست درخت جستجوي دودويي نيستند.

7 Binary Search Trees دقت کنيد که شرط کامل بودن در تعريف درخت جستجوي دودويي حضور ندارد. لذا، پياده سازي لينک پيوندي بهتر است. تعريف بازگشتي درخت جستجوي دودويي = الگوريتمهاي بازگشتي

8 Binary Search Trees: Search
جستجو: از خواص درخت جستجوي دودويي استفاده کنيد. از ريشه شروع کن اگر ريشه برابر صفر بود، پيغام بده که درخت خالي است. در غير اين صورت: x را با ريشه مقايسه کن. اگر x با کليد ريشه برابر بود، نود را برگردان. اگر x از کليد ريشه کمتر بود، زير درخت سمت چپ را بگرد. در غير اين صورت زير درخت سمت راست را بگرد.

9 Binary Search Trees: BSTNode Definition
template <class Type> class BSTNode { private: BSTNode* leftChild; BSTNode* rightChild; Element<Type> data; }; class Element { private: Type key; ??? OTHER DATA }

10 Binary Search Tree: Search Implementation
template <class Type> BSTNode<Type>* BST<Type>::Search(const Element<Type>& x) { return Search(root,x); } template<class Type> BSTNode<Type>* BST<Type>::Search(BSTNode*<Type> *b, const Element<Type>& x) { if (b == 0) return 0; if (x.key == b->data.key) return b; if (x.key < b->data.key) return Search(b->LeftChild, x); return Search(b->rightChild, x); }

11 Binary Search Trees: Search Example
15 را پيدا کن. ريشه خالي است؟ نه 15 را با مقدار ريشه (30( مقايسه کن 15 < 30 لذا زير درخت سمت چپ را بگرد. 15 را با 5 مقايسه کن 15 > 5 لذا زير درخت سمت راست را بگرد. 15 را با 15 مقايسه کن 15 == 15 نود جاري را بر گردان 30 5 40 2 15

12 Binary Search Trees: Big Oh Analysis
در ريشه يک مقايسه انجام مي دهيم > Root يا < Root با توجه به نتيجه: به يکي از فرزندان مي رويم يک مقايسه انجام مي دهيم. حداکثر به اندازه ارتفاع درخت اين کار را انجام مي دهيم: لذا، پيچيدگي زماني جستجو، وابسته به شکل درخت است. خطی: O(n) متوازن: O (log 2 n)

13 Binary Search Trees: Insertion
قوانين - الحاق بايد شرايط زير را برآورده کند: کليد يکتا فرزند سمت راست < پدر فرزند سمت چپ > پدر نودهاي مياني نيز بايد شرايط فوق را برآورده کنند. يکتا بودن را چگونه چک کنيم؟ به همه نودها نگاه کنيم؟

14 Binary Search Trees: Insertion
نيازي نيست که به تمام نودها نگاه کنيم از اين حقيقت استفاده مي کنيم که قبل از الحاق نود جديد، درخت از نوع جستجوي دودويي است. لذا کافيست دنبال نود جديد در درخت بگرديم. Add 30 15 5 40 Search for 15 15 ? 30, 15 < 30 => Left 15 ? 5, 15 > 5 => Right 15 ? 15, 15 == 15 => Not Unique 2 15

15 Binary Search Trees: Insertion
جستجوي نود جديد نه تنها مساله يکتا بودن را حل مي کند، بلکه ما را به جاي درست نود جديد رهنمون مي سازد. Add 30 15 5 40 Search for 15 15 ? 30, 15 < 30 => Left 15 ? 5, 15 > 5 => Right No right child, so not present 2 15 Add 15 as right child of 5

16 Binary Search Trees: Insertion Implementation
template <class Type> bool BST<Type>::Insert(const Element<Type> & x) { // search for x BSTNode<Type> *current = root; BSTNode<Type>* parent = 0; while (current) { parent = current; if (x.key == current-> data.key) return false; if (x.key < current->data.key) current = current->leftChild; else current = current->rightChild; } current = new BSTNode<Type>; current->leftChild = 0; current->rightChild = 0; current->data = x; if (!root) root = current; else if (x.key < parent->data.key) parent->leftChild = current; else parent->rightChild = current; return true; }

17 Binary Search Trees: Insertion Big Oh Analysis
عمده کار تابع الحاق، پياده سازي عمل جستجو است. وابسته به شکل درخت است. خود عمل الحاق داراي هزينه ثابت است. لذا، هزينه کل وابسته به پيچيدگي عمل جستجو است. در بدترين حالت: O(n) در حالت ميانگين: O(log2n)

18 Binary Search Trees: Deletion
قوانين - حذف بايد شرايط زير را برآورده کند: کليد يکتا نيازي به چک کردن ندارد. چون قبل از عمل حذف کليدها يکتا هستند. اما موارد زير بايد رعايت شوند: فرزند سمت راست < پدر فرزند سمت چپ > پدر نودهاي مياني نيز بايد شرايط فوق را برآورده کنند.

19 Binary Search Trees: Deletion
30 5 40 سه حالت: 1- حذف نود انتهايي (15) : نود انتهايي را حذف کن. اشاره گر پدر را برابر صفر قرار بده. 2 15 30 5 40 2

20 Binary Search Trees: Deletion
30 2- نود غير انتهايي، داراي يک فرزند(5): لينک نود پدر را که به نود حذف شونده اشاره دارد را به فرزند نود حذف شونده اشاره دهيد. 5 40 2 30 5 40 2

21 Binary Search Trees: Deletion
3- نود غير انتهايي داراي دو فرزند: مقدار نود حذف شونده را با بزرگترين المان سمت چپ يا کوچکترين المان سمت راست جابجا کنید. نودي را که جابجا کرده ايد را حذف کنيد. اين حذف کردن معادل يکي از حالتهاي 1 يا 2 خواهد بود. 30 5 40 toDelete 2 5 5 40 5 40 2 2

22 Binary Search Trees: Deletion
قانون اصلي حذف: “با بزرگترين المان سمت چپ يا کوچکترين المان سمت راست جابجا کنيد” آيا اين روش هميشه درست است؟ بله – چون بزرگترين المان سمت چپ از تمام عناصر سمت چپ بزرگتر است. از تمام عناصر سمت راست کوچکتراست. کوچکترين المان سمت راست اينها، همان شرايطي هستند که ريشه زير درخت جستجوي دودويي نياز دارد.

23 Binary Search Trees: Height
درخت خطی 40 مسائل درخت جستجوي دودويي از لحاظ پيچيدگي وابسته به ارتفاع درخت هستند که در بدترين حالت O(n) هست. اگر داده ها مرتب يا نبمه مرتب باشند، درخت خطی خواهد گرديد. 30 5 2

24 Binary Search Trees: Height
bool BST<Type>::Insert(const Element<Type> & x) { // search for x BSTNode<Type> *current = root; BSTNode<Type>* parent = 0; while (current) { parent = current; if (x.key == current-> data.key) return false; if (x.key < current->data.key) current = current->leftChild; else current = current->rightChild; } current = new BSTNode<Type>; current->leftChild = 0; current->rightChild = 0; current->data = x; if (!root) root = current; else if (x.key < parent->data.key) parent->leftChild = current; else parent->rightChild = current; return true; } Insert: 3, 4, 6, 5, 8 root 3 4 6 8 5

25 Binary Search Trees: Height
اگر الحاقها به صورت تصادفي انجام گردند، ارتفاع درخت برابر O(log n) خواهد بود. در حالت عمومي الحاقها تصادفي هستند، لذا اغلب ارتفاع برابر O(log n) خواهد شد. راههاي وجود دارد که ارتفاعO(log n) را گارانتي نمود. بايد توابع الحاق و حذف را دستکاري نمود تا درخت متعادل شود.

26 TreeSort: نودهاي درخت جستجوي دودويي داراي نظم خاصي هستند.
تمام نودهاي سمت چپ از ريشه کوچکتر و تمام نودهاي سمت راست از آن بزرگتر هستند. اين مطلب براي تمام نودها صادق است. لذا، مي توان از پيمايش LVR براي توليد يک ليست مرتب استفاده کرد. 30 5 40 2 50 15 35 LVR Ordering: 2,5,15,30,35,40,50

27 TreeSort: آناليز TreeSort:
بايد يک درخت جستجوي دودويي با سايز n بسازيم. به n الحاق نياز داريم. بهترين حالت: درخت متعادل O(n * log 2 n) بدترين حالت: درخت خطی O(n2) سپس LVR را اجرا مي کنيم. هميشهO(n) است. پس پيچيدگي TreeSort برابر است با: بهترين حالت: O(n * log 2 n) بدترين حالت: O(n2)

28 TreeSort: خيلي شبيه quicksort است.
حالت ميانگين [O(n log n)] و بدترين حالت [O(n2)] است. ريشه هر زير درخت معادل محور است. عناصر کوچکتر از محور سمت چپ آن هستند. عناصر بزرگتر از محور سمت راست آن هستند. هر چقدر محور بهتر باشد، درخت متعادل تر است. داده هاي مرتب يا نيمه مرتب هر دو روش را با مشکل مواجه مي کند. در quicksort: تفکيک با مشکل مواجه مي شود. در treesort: ساخت درخت با مشکل مواجه مي شود.

29 Threaded Trees: General Trees
Mike John Thomas Georgia Tyler Kylie Shelley Fred Hall تعداد زیادی از لینکها برابر null هستند. می شود از این لینکها برای افزایش کیفیت پیمایش استفاده کرد.

30 Threaded Trees NULL ff Mike ff John Thomas ff Georgia ff Kylie Shelley
Tyler tt Fred Hall tt tt tt tt

31 Threaded Trees: Insertion
Mike Mike John John Kylie Kylie Bill Hall Bill Hall

32 Threaded Trees: Insertion
Mike Mike John John Kate Kylie Kylie Hall Kate Hall Bill Fred Jane Bill Fred Jane

33 Rank Information اغلب اوقات ما به رتبه نود در لیست علاق داریم:
بزرگترین نود کدام است؟ کوچکترین نود کدام است؟ میانه کدام است؟ پنجمین نود از نظر بزرگی کدام است؟ بزرگترین وکوچکترین معمولا با O(n) انجام می شوند. مگر اینکه از heap استفاده کنیم. اگر دنبال نودی غیر از بزرگترین (یا کوچکترین بودیم)، باید راهی موثر برای پیدا کردن رتبه داشته باشیم.

34 Rank Information راه حل اول پیدا کردن مرتبه:
مرتب کردن داده ها (لیست آرایه ای) لیست را مرتب کنید. O(n log n) مقدار list[rankOfInterest] را برگردانید. O(1) O(n log n) [sort] + O(1) [value retrieval] البته اگر داده دینامیک باشد از لیست پیوندی استفاده می شود.

35 Rank Information راه حل اول پیدا کردن مرتبه:
مرتب کردن داده ها (لیست آرایه ای) لیست را مرتب کنید. (مثلا با mergesort) لیست را تا رسیدن به نود مورد نظر پیمایش کنید. O(n log n) [sort] + O(rankOfInterest) [traversal] این روش با داده دینامیک کار می کند اما کندتر است.

36 Rank Information راه حل دوم پیدا کردن مرتبه:
استفاده از درخت جستجوی دودویی داده ها را وارد درخت جستجوی دودویی کنید. پیمایش میان ترتیب را تا رسیدن به مرتبه مورد نظر انجام دهید. O(n log n) [building tree] + O(rankOfInterest) [traversal] هزینه این روش مثل روش فبلی است اما دیگر نیازی به اجرای mergesort برای لیست پیوندی نیست.

37 Rank Information: راه حل سوم پیدا کردن مرتبه:
استفاده از درخت جستجوی دودویی یک متغییر به هر نود اضافه کنید. این متغییر نشان دهنده تعداد نودهای سمت چپ نود به اضافه یک (به خاطر خود نود) است. ابتدا مقدار این متغییر یک است. وقتی که یک نود به درخت اضافه می شود: از هر نود که می گذریم، یک اشاره گر به پدر آن نود نگهداری میکنیم. اگر نود را به درخت اضافه کردیم. مقدار متغییر را برای والدین یک واحد افزایش می دهیم. نحوه استفاده از این متغییر در صفحه بعد نشان داده شده است.

38 Rank Information: Example
4 leftSize values: دومین عنصر کیست؟ Rank 2 < leftSize(Mike) [4] Move to root->leftChild Rank 2 == leftSize(John) [2] Return John Node پنچمین نود کیست؟ Rank 5 > leftSize(Mike) [4] Move to root->rightChild Rank = 5-4 = 1 < leftSize(Thomas) [2] Move to leftChild of Thomas Rank == leftSize(Shelley) [1] Return Shelley Node Mike 2 2 John Thomas Georgia Tyler Kylie Shelley 1 1 1 1 Real Ranks for Data [First is rank 1, Last is 7]: Georgia, John, Kylie, Mike, Shelley, Thomas, Tyler

39 Rank Information: template <class Type>
BinaryTreeNode<Type>* BinarySearchTree<Type>:: search(int rank) { BinaryTreeNode<Type>* current = root; while (current) if (rank == current->leftSize) return current; else if (rank < current->leftSize) current = current->leftChild; else { rank = rank – current->leftSize; current = current->rightChild;} }

40 Rank Information: Analysis
حالا محدود به ارتفاع درخت هستیم. به طور متوسط O(log n) ساخت درخت قبلا O(n log n)بود. اما ما به درخت یک متغییر و تعدادی پردازش اضافه کردیم: تغییر دادن مقدار leftsize والدین حداکثر به اندازه ارتفاع درخت. پس هر الحاق به 2*logn کار نیاز دارد. لذا n الحاق به O(n log n)کار نیاز دارد. پس برای داده دینامیک و مساله پیدا کردن رتبه داریم: O(n log n) [building] + O(log n) [searching] از روشهای قبلی بهتر است.


Download ppt "درختان 3."

Similar presentations


Ads by Google