بائنری درخت
جاوا میں، ڈیٹا ڈھانچے کی بہت سی مختلف اقسام ہیں۔ ڈھیر درخت کی ساخت پر مبنی ہے جسے بائنری ٹری کہتے ہیں ۔ ایک بائنری ٹری نوڈس پر مشتمل ہوتا ہے، جن میں سے ہر ایک میں زیادہ سے زیادہ 2 چائلڈ نوڈس ہوسکتے ہیں: ایک بائنری ٹری پیرنٹ نوڈ پر مشتمل ہوتا ہے جس میں 0 سے 2 نوڈس ہوسکتے ہیں۔ اس میں لیفٹ چائلڈ نوڈ اور/یا رائٹ چائلڈ نوڈ ہو سکتا ہے، یا بالکل بھی کوئی نوڈ نہیں ہو سکتا۔ ایک مکمل بائنری ٹری میں، تمام نوڈس بھرے ہوتے ہیں سوائے آخری سطح کے جو کہ بھرا ہو سکتا ہے، لیکن اسے بھرنے کی ضرورت نہیں ہے۔ آخری سطح، نویں سطح میں 1 سے 2n نوڈس ہو سکتے ہیں، جہاں پہلا n = 0 پر ہے اور جڑ ہے۔زیادہ سے زیادہ ڈھیر
میکس ہیپ (یا میکس ہیپ) ایک مکمل بائنری ٹری ہے ۔ اس کے بارے میں اہم بات یہ ہے کہ پیرنٹ نوڈ کی قدر لیفٹ اور رائٹ چائلڈ نوڈس سے زیادہ یا اس کے برابر ہونی چاہیے۔ اگر اس پر عمل نہیں کیا جاتا ہے، تو آپ کے پاس زیادہ سے زیادہ ہیپ نہیں ہے۔ کم ہیپ، دوسری طرف، جڑ کے برعکس ہے کیونکہ سب سے چھوٹی قدر یکے بعد دیگرے نوڈس کی قدر میں بڑھ رہی ہے۔ ہر چائلڈ نوڈ کی قدر اس کے والدین سے زیادہ یا اس کے برابر ہوتی ہے۔ یہ ایک مکمل بائنری درخت بھی ہے۔ زیادہ سے زیادہ ہیپ کی ایک مثال یہ ہے: زیادہ سے زیادہ ہیپ ایک صف سے بنایا جا سکتا ہے۔ اس صف کے بارے میں ایک درخت کے لحاظ سے سوچا جائے گا۔ ایک ہیپ کے لیے، اگر جڑ، (درخت کا سب سے اوپر پیرنٹ نوڈ) پوزیشن (انڈیکس) n پر ذخیرہ کیا جاتا ہے، تو اس کی تعریف array، theArray کے لیے کی جاتی ہے ، بطور theArray[n] ۔ لیفٹ اور رائٹ چائلڈ نوڈز بالترتیب theArray [2n+1] اور theArray[2n+2] پر ہیں۔ زیادہ سے زیادہ ہیپ کے لیے، جڑ array[0] پر ہے ۔ لیول n کے لیے، روٹ n = 0: theArr[n] پیرنٹ نوڈ ہے theArr[(2*n)+1] بائیں چائلڈ نوڈ ہے TheArr[(2*n)+2] دائیں چائلڈ نوڈ ہے۔ترجیحی قطار کی کلاس
جاوا میں ہیپس کو PriorityQueue کلاس کا استعمال کرتے ہوئے لاگو کیا جا سکتا ہے۔ ترجیحی قطاروں کا استعمال کسی مجموعہ میں سب سے زیادہ یا کم از کم اہم شے تلاش کرنے کے لیے کیا جاتا ہے۔ PriorityQueue کلاس java.util.package میں مل سکتی ہے ۔ ترجیحی قطاریں ایسی اشیاء سے بنائی جانی چاہئیں جن کا موازنہ کیا جا سکے تاکہ انہیں قطار میں ایک خاص ترتیب میں رکھا جائے۔ PriorityQueue میں موازنہ کرنے والا ہو سکتا ہے تاکہ اشیاء کے درمیان موازنہ کیا جائے اور اس موازنہ کے مطابق قطار بنائی جائے۔ ایک مثال یہ ہے:import java.util.Comparator;
import java.util.PriorityQueue;
public class Main
{
public static void main(String[] args) {
// Create PriorityQueue with comparator for ascending order of array length
PriorityQueue intQueue = new PriorityQueue((a,b) -> a - b);
Integer [] array1 = {1, 2, 4, 6, 8, 9};
Integer [] array2 = {3, 6, 9};
Integer [] array3 = {2, 4, 8, 16, 32, 64, 128};
Integer [] array4 = {5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55};
Integer [] array5 = {4};
//Add the array lengths to intQueue
intQueue.add(array1.length);
intQueue.add(array2.length);
intQueue.add(array3.length);
intQueue.add(array4.length);
intQueue.add(array5.length);
//Write out contents of intQueue as stored
while (intQueue.size() != 0) {
System.out.println(intQueue.remove());
}
}
}
آؤٹ پٹ دینا:
1 3 6 7 11
اس مثال میں، intQueue کا ڈیفالٹ سائز 11 ہے، اس لیے بیان نہیں کیا گیا ہے (عام طور پر موازنہ کرنے والے سے پہلے پہلی دلیل) اور comparator کو اس طرح دیا گیا ہے:
(a,b) -> a - b
یہ intQueue میں آئٹمز کے درمیان موازنہ کرے گا اور اسے صعودی ترتیب کی صف کی لمبائی میں ترتیب دے گا۔
زیادہ سے زیادہ ہیپ بنانے کے لیے ترجیحی قطار کا نفاذ
PriorityQueue کلاس بغیر کسی موازنہ کے کم سے کم ہیپ پر ڈیفالٹ ہوتی ہے۔ کم سے کم ہیپ زیادہ سے زیادہ ہیپ کے برعکس ہے اور اس لیے جڑ سب سے چھوٹی قدر ہے اور یکے بعد دیگرے چائلڈ نوڈس جڑ اور اس کے بعد آنے والے پیرنٹل نوڈس کے برابر یا بڑے ہوتے ہیں۔ اس وجہ سے، زیادہ سے زیادہ ہیپ کے لیے، جاوا کے کلیکشن فریم ورک سے reverseOrder() کو بطور موازنہ استعمال کرنا ضروری ہے ۔ یہ یقینی بنائے گا کہ ہمیں زیادہ سے زیادہ ہیپ ملے گا نہ کہ ایک منٹ ہیپ۔ اس کلاس میں مفید طریقے ہیں جیسے add() , contains() , remove() , poll() , اور peek() ۔طریقہ | تفصیل | وقت کی پیچیدگی |
---|---|---|
شامل کریں(J) | درخت کے آخر میں عنصر J شامل کرتا ہے۔ | O(LogN) |
ہٹا دیں(J) | درخت سے قدر J کو ہٹا دیں۔ | O(N) |
رائے شماری() | درخت کے زیادہ سے زیادہ عنصر کو ہٹاتا ہے۔ | O(LogN) |
جھانکنا() | درخت کے اوپری حصے میں جڑ کا عنصر لوٹاتا ہے۔ | O(1) |
پر مشتمل ہے (J) | اگر J قطار میں ہے تو درست لوٹاتا ہے، اگر نہیں تو غلط | O(N) |
mport java.util.Collections;
import java.util.PriorityQueue;
public class MaxHeap {
public static void writeQueue(PriorityQueue<Integer> priorityQueue)
{
// Write out elements in queue, priorityQueue, and remove them using poll()
while(priorityQueue.size() != 0)
{
System.out.println(priorityQueue.poll());
}
}
public static void writeMaxHeap(PriorityQueue<Integer> priorityQueue)
{
// Write out elements in queue as a max heap - root, left child, right child, etc
for (Integer element : priorityQueue) {
System.out.println(element);
}
}
public static void main(String args[])
{
// Array of numbers to create a max heap array from
int[] theArray = {5, 3, 13, 10, 99, 19, 6, 51, 9};
// theQueue is created
PriorityQueue<Integer> theQueue =
new PriorityQueue<Integer>(Collections.reverseOrder());
// Elements are added to theQueue
for (int i = 0 ; i <theArray.length; ++i)
{
theQueue.add(theArray[i]);
}
// The head or root element (priority element) is printed out
System.out.println("The root value is : " + theQueue.peek());
// Find size of theQueue. Use method size()
Integer s = theQueue.size();
System.out.println("Size of theQueue? " + s);
// All elements of theQueue are printed in terms of parent,
// left child, right child
System.out.println("theQueue written using for loop:");
writeMaxHeap(theQueue);
// Does theQueue contain 10? Use method contains()
boolean b = theQueue.contains(10);
System.out.println("Does theQueue contain 10? " + b);
// Erasing value 10 from array using remove()
theQueue.remove(10);
// All elements of theQueue are printed out and removed.
// Each one is the maximum value left in the queue.
// At the end theQueue will be empty
System.out.println("theQueue written out using poll():");
writeQueue(theQueue);
// Find size of theQueue. Use method size()
s = theQueue.size();
System.out.println("Size of theQueue? " + s);
}
}
آؤٹ پٹ:
جڑ کی قیمت ہے: 99 قطار کا سائز؟ 9 the Queue for loop 99 51 19 13 10 5 6 3 9 کے لیے لکھی گئی کیا قطار میں 10 شامل ہیں؟ صحیح دی قطار پول () 99 51 19 13 9 6 5 3 کا استعمال کرتے ہوئے لکھی گئی قطار کا سائز؟ 0
Max Heapify
Max Heapify الگورتھم اس بات کو یقینی بنانے کے لیے استعمال کیا جاتا ہے کہ بائنری ٹری زیادہ سے زیادہ ہیپ ہے۔ اگر ہم ایک نوڈ پر ہیں، n، اور اس کے چائلڈ نوڈس، بائیں اور دائیں بھی خود زیادہ سے زیادہ ہیپس ہیں، تو بہت اچھا، ہمارے پاس زیادہ سے زیادہ ہیپ ہے۔ اگر پورے درخت میں ایسا نہیں ہے تو ہمارے پاس زیادہ سے زیادہ ڈھیر نہیں ہے۔ Max Heapify الگورتھم درخت کو ترتیب دینے کے لیے استعمال کیا جاتا ہے تاکہ یہ maxheap اصولوں پر عمل کرے۔ Max Heapify صرف ایک نوڈ پر کام کرتا ہے۔ اگر ضرورت یہ ہے کہ صف ایک زیادہ سے زیادہ ہیپ اری ہے، تو تمام ذیلی درختوں کو جڑ سے پہلے میکس ہیپ میں تبدیل کرنا ضروری ہے، ایک وقت میں ایک۔ الگورتھم کو ہر نوڈ پر استعمال کیا جانا چاہیے۔ یہ N/2 نوڈس پر کیا جائے گا (پتے زیادہ سے زیادہ ہیپ کی ضروریات پر عمل کریں گے)۔ ہیپ کی وقتی پیچیدگی O(NlogN) ہے، اور اونچائی X پر ایک نوڈ کے لیے، وقت کی پیچیدگی O(X) ہے۔ درج ذیل کوڈ سے پتہ چلتا ہے کہ درخت (ایک صف) کو زیادہ سے زیادہ ہیپیفائی کرنے کا طریقہ۔public class MaxHeapify
{
public static Integer[] maxHeapify(Integer[ ] array, Integer i)
{
// Create left-child and right-child for the node in question
Integer leftChild = 2 * i + 1;
Integer rightChild = 2 * i + 2;
// Assign maxVal to parent node, i
Integer maxVal = i;
// Set maxVal to greater of the two: node or left-child
if( leftChild < array.length && array[leftChild] > array[maxVal] )
maxVal = leftChild;
// Set maxVal to greater of the two: maxVal or right-child
if( rightChild < array.length && array[rightChild] > array[maxVal] )
maxVal = rightChild;
// Check if maxVal is not equal to parent node, then set parent node to
// maxVal, swap values and then do a maxheapify on maxVal
// which is now the previous parent node
if( maxVal != i )
{
Integer value = array[i];
array[i] = array[maxVal];
array[maxVal] = value;
array = maxHeapify(array, maxVal);
}
return array;
}
public static Integer[] maxHeapCreate(Integer array[])
{
// Call maxHeapify to arrange array in a max heap
Integer [] theNewArr = array;
for( Integer i = array.length/2; i >= 0; i-- )
theNewArr = maxHeapify(array, i);
return theNewArr;
}
public static void main(String[] args)
{
// Create array to be maxheapified, theArray,
// and array, newArray, to write results into, by calling maxheapCreate
// newArray will now be a maxheap
Integer[] theArray = {5, 3, 13, 10, 99, 19, 6, 51, 9};
Integer[ ] newArray = maxHeapCreate(theArray);
// Print out contents of newArray
System.out.println("newArray:");
for(int i = 0; i < newArray.length; ++i)
{
System.out.println(newArray[i]);
}
// Print out labelled contents of newArray
System.out.println(" root : " + newArray[0]);
for (int i = 0; i <= newArray.length/2 - 1; i++) {
System.out.print(" parent node : " + newArray[i] + " left child : " +
newArray[(2*i)+1] + " right child :" + newArray[(2*i)+2]);
System.out.println();
}
}
}
آؤٹ پٹ دینا:
newArray: 99 51 19 10 3 13 6 5 9 جڑ: 99 پیرنٹ نوڈ: 99 لیفٹ چائلڈ: 51 رائٹ چائلڈ: 19 پیرنٹ نوڈ: 51 لیفٹ چائلڈ: 10 رائٹ چائلڈ: 3 پیرنٹ نوڈ: 19 لیفٹ چائلڈ: 13 رائٹ چائلڈ: 6 پیرنٹ نوڈ: 10 بائیں بچہ: 5 دائیں بچے: 9
اس کوڈ میں، TheArray بنائی گئی ہے اور نمبروں سے بھری ہوئی ہے۔ ایک دوسری صف، newArray ، بنائی گئی ہے اور اس بار اس میں طریقہ کا نتیجہ ہوگا، maxheapCreate ، max heap array۔ طریقہ maxHeapCreate کو main سے بلایا جاتا ہے ، اور یہاں ایک نئی صف، theNewArr ، بنائی جاتی ہے اور maxHeapify نتائج سے بھر جاتی ہے۔ یہ ان پٹ سرنی کے نصف سائز سے زیادہ لوپ کرکے کیا جاتا ہے۔ لوپ کے ہر پاس کے لیے، طریقہ maxHeapify ، کو کہا جاتا ہے جو کہ صف کے بیچ میں عنصر سے شروع ہوتا ہے اور پہلے کے ساتھ ختم ہوتا ہے۔ maxHeapify کی ہر کال کے لیے ، پیرنٹ نوڈ، i، کے بائیں بچے اور دائیں بچے کو تلاش کیا جاتا ہے اور یہ معلوم کرنے کے لیے جانچ پڑتال کی جاتی ہے کہ تینوں میں سے کون بڑا ہے، اس کی وضاحت maxVal کے طور پر کی جاتی ہے ۔ اگر maxVal پیرنٹ نوڈ کے برابر نہیں ہے تو ایک سویپ کیا جاتا ہے تاکہ پیرنٹ نوڈ اور maxVal کو تبدیل کر دیا جائے اور پھر maxHeapify کو اس بار maxVal پر دوبارہ کال کیا جائے گا اور وہی اقدامات کیے جائیں گے جو پہلے کیے گئے تھے۔ آخر کار زیادہ سے زیادہ ڈھیر بن جائے گا اور اس پر عمل کرنے کے لیے مزید تکرار نہیں ہوگی۔ اپ ڈیٹ کردہ سرنی، array ، کو اب newArray کے طور پر مین پر واپس کر دیا گیا ہے اور پھر ہر ایک لگاتار عنصر کنسول پر پرنٹ کیا جاتا ہے۔ newArray اب زیادہ سے زیادہ ہیپ ہے۔ نوٹ کریں، جیسا کہ پچھلی مثال میں PriorityQueue کا استعمال کرتے ہوئے نمبر لکھے گئے ہیں: جڑ، والدین کے طور پر جڑ کا دائیں بچہ، والدین کے طور پر جڑ کا بائیں بچہ، والدین کے طور پر پہلے دائیں بچے کا دائیں بچہ، پہلے کا بائیں بچہ لیفٹ چائلڈ بطور والدین، دائیں بچے کے پہلے بائیں بچے کا بطور والدین، پہلے دائیں بچے کا بائیں بچہ بطور والدین، وغیرہ۔ ترجیحی قطار استعمال کرتے وقت وہ ان سے قدرے مختلف ترتیب میں ہوتے ہیں کیونکہ موازنہ لگاتار عناصر کے درمیان کیا جاتا ہے ۔ جبکہ maxheapify مثال میں، نوڈ کا مقابلہ صف میں اگلے دو لگاتار عناصر سے کیا جاتا ہے اور سب سے بڑی قدر کے لیے تبدیل کیا جاتا ہے۔ مختصر میں، دو مختلف الگورتھم استعمال کیے جاتے ہیں۔ دونوں ایک زیادہ سے زیادہ ڈھیر بناتے ہیں۔
GO TO FULL VERSION