CodeGym /جاوا بلاگ /Random-UR /جاوا میں ٹری سیٹ
John Squirrels
سطح
San Francisco

جاوا میں ٹری سیٹ

گروپ میں شائع ہوا۔
جاوا عنصر کے مجموعوں کے ساتھ مؤثر طریقے سے کام کرنے کے لیے ڈیٹا ڈھانچے کا ایک وسیع سیٹ فراہم کرتا ہے۔ ایسا ہی ایک ڈیٹا ڈھانچہ TreeSet ہے، جو جاوا میں سرخ سیاہ درخت کا نفاذ ہے۔ TreeSet منفرد عناصر کو ذخیرہ کرنے کے لیے ترتیب شدہ ترتیب کو برقرار رکھتا ہے۔ ابتدائی طور پر جاوا ٹری سیٹ کلاس کا استعمال تھوڑا مشکل ہو سکتا ہے۔ اس مضمون میں، ہم یہ جاننے جا رہے ہیں کہ TreeSet کو کس طرح استعمال کیا جائے ، اس کے بنیادی تصورات کی وضاحت کریں اور کوڈ کی مثالیں فراہم کریں تاکہ آپ کو اپنے جاوا پروجیکٹس میں TreeSet کو شامل کرنے میں مدد ملے۔

ٹری سیٹ ڈھانچہ: سرخ-سیاہ درخت

جیسا کہ ہم نے پہلے ذکر کیا ہے، جاوا ٹری سیٹ کلاس ڈھانچہ ایک خود توازن بائنری سرچ ٹری کے طور پر لاگو کیا جاتا ہے جسے ریڈ-بلیک ٹری کہا جاتا ہے۔ آئیے وضاحت کرتے ہیں کہ یہ کیا ہے... ایک سرخ سیاہ درخت ایک متوازن بائنری سرچ ڈیٹا ڈھانچہ کی نمائندگی کرتا ہے جو عام طور پر ترتیب شدہ ڈیٹا کو ذخیرہ کرنے اور ترتیب دینے کے لیے استعمال کیا جاتا ہے۔ اس کا نام ان خصوصیات سے اخذ کیا گیا ہے جو اس کا توازن برقرار رکھتی ہیں:
  • درخت میں ہر نوڈ سرخ یا سیاہ ہے.
  • سرخ سیاہ درخت کی جڑ ہمیشہ کالی ہوتی ہے۔
  • تمام لیف نوڈس (NIL نوڈس یا null لنکس) سیاہ ہیں۔
  • اگر درخت کا ایک نوڈ سرخ ہے، تو اس کے بچے سیاہ ہیں.
  • نوڈ سے لے کر اس کے ڈیسنڈنٹ نوڈس تک ہر سادہ راستے میں بلیک نوڈس کی مساوی تعداد ہوتی ہے۔
سرخ سیاہ درخت توازن کو یقینی بنا کر اندراج، حذف کرنے، اور عنصر کی تلاش کے کاموں کے لیے موثر کارکردگی کا مظاہرہ کرتے ہیں۔ یہ اس بات کی ضمانت دیتا ہے کہ درخت کی اونچائی اس میں موجود نوڈس کی تعداد کے لوگارتھم کے متناسب رہتی ہے، جس کے نتیجے میں آپریشنز کے لیے لوگارتھمک وقت کی پیچیدگی پیدا ہوتی ہے۔ سرخ سیاہ درخت مختلف ڈومینز میں وسیع ایپلی کیشنز تلاش کرتے ہیں، بشمول پروگرامنگ زبانوں میں متوازن تلاش کے درختوں کا نفاذ، ڈیٹا بیس (مثال کے طور پر، اندرونی انڈیکس ڈھانچے)، اور دیگر منظرنامے جہاں موثر اسٹوریج اور ترتیب شدہ ڈیٹا پر آپریشن ضروری ہیں۔

TreeSet کی خصوصیات اور کمزوریاں

TreeSet کئی کلیدی خصوصیات فراہم کرتا ہے جو اسے اشیاء کے مجموعوں کو ترتیب سے ترتیب دینے کے لیے ایک قابل قدر ٹول بناتا ہے۔ فوائد:
  • ترتیب شدہ ترتیب میں عناصر کی خودکار دیکھ بھال۔ عناصر کو شامل کرتے یا ہٹاتے وقت، درخت کا ڈھانچہ ان کو ترتیب دینے کے لیے ایڈجسٹ کرتا ہے۔ یہ دستی چھانٹنے کی ضرورت کو ختم کرتا ہے اور صعودی یا نزولی ترتیب میں موثر رسائی فراہم کرتا ہے۔
  • موثر تلاش، داخل، اور حذف آپریشنز۔ یہ بائنری سرچ ٹری ڈھانچے کا استعمال کرتا ہے، O(log N) کی وقتی پیچیدگی کے ساتھ ان کارروائیوں کو فعال کرتا ہے ۔ یہاں N عناصر کی تعداد ہے۔
  • TreeSet عناصر کی قدرتی ترتیب یا حسب ضرورت کمپیریٹر کو استعمال کرکے ان کی انفرادیت کی ضمانت دیتا ہے ۔ یہ اس وقت کارآمد ہوتا ہے جب ان مجموعوں کے ساتھ کام کرتے ہیں جن میں الگ الگ عناصر کی ضرورت ہوتی ہے۔
حدود:
  • ترتیب شدہ ترتیب کو برقرار رکھنے کی وجہ سے HashSet سے قدرے سست ۔
  • کالعدم عناصر کی اجازت نہیں دیتا، کیونکہ یہ عنصر کے موازنہ کے لیے قدرتی ترتیب یا حسب ضرورت موازنہ پر انحصار کرتا ہے۔

جاوا ٹری سیٹ: مین آپریشنز کی مثال

اب آئیے یہ ظاہر کرتے ہیں کہ جاوا میں TreeSet کیسے بنایا جائے ، مجموعہ کا سائز حاصل کریں، اس میں عناصر شامل کریں، انہیں ہٹائیں اور چیک کریں کہ آیا کوئی عنصر TreeSet میں ہے ۔ یہ کوڈ مثالیں TreeSet کے ساتھ کام کرتے وقت اہم کارروائیوں کو ظاہر کرتی ہیں : ایک مثال بنانا، عناصر کو شامل کرنا، عناصر کو ہٹانا، عنصر کی موجودگی کی جانچ کرنا، اور TreeSet کا سائز حاصل کرنا ۔ TreeSet مثال بنانا اور عناصر شامل کرنا:
// Creating a TreeSet of Integer type
TreeSet<Integer> numbers = new TreeSet<>();

// Adding elements to the TreeSet
numbers.add(18);
numbers.add(2);
numbers.add(7);
numbers.add(28);

System.out.println(numbers); // Output: [2, 7, 18, 28]
یہاں ہم اپنے TreeSet میں 4 نمبر شامل کرنے کے لیے add() طریقہ استعمال کرتے ہیں ۔ اگر ہم ایک اہم طریقہ بناتے ہیں اور پروگرام چلاتے ہیں، تو آؤٹ پٹ ترتیب شدہ ترتیب میں ہو گا (2، 7، 18، 28)۔ TreeSet سے عناصر کو ہٹانا :
TreeSet<String> names = new TreeSet<>();

names.add("Johnny");
names.add("Ivy");
names.add("David");
names.add("Ricky");

// Removing an element from the TreeSet
names.remove("David");

System.out.println(names); // Output: [Ivy, Johnny, Ricky]
TreeSet میں کسی عنصر کی موجودگی کی جانچ کرنا :
TreeSet<String> musicalInstrument = new TreeSet<>();

musicalInstrument.add("Piano");
musicalInstrument.add("Drums");
musicalInstrumentfruits.add("Violin");
musicalInstrument.add("Double Bass");

// Checking if an element exists in the TreeSet
boolean containsPiano = musicalInstrument.contains("Piano");
boolean containsCello = musicalInstrument.contains("Cello");

System.out.println(containsPiano); // Output: true
System.out.println(containsCello); // Output: false
TreeSet کا سائز حاصل کرنا :
TreeSet<Character> letters = new TreeSet<>();

letters.add('A');
letters.add('B');
letters.add('C');
letters.add('D');

// Getting the size of the TreeSet
int size = letters.size();

System.out.println(size); // Output: 4

ٹری سیٹ میں چھانٹنا اور تکرار کرنا

جاوا میں TreeSet عناصر کے مجموعوں کو چھانٹنے اور اعادہ کرنے کے لیے طاقتور خصوصیات فراہم کرتا ہے۔ اس سیکشن میں، ہم عناصر کو چھانٹنے، TreeSet پر اعادہ کرنے ، اور subSet() , headSet() اور tailSet() طریقوں کا استعمال کرتے ہوئے رینج پر مبنی تلاشیں کرنے کے لیے مختلف تکنیکوں کو تلاش کریں گے۔ پہلے سے طے شدہ طور پر، TreeSet خود بخود عناصر کو ترتیب شدہ ترتیب میں برقرار رکھتا ہے۔ تاہم، ہم TreeSet کی تخلیق کے دوران ایک Comparator فراہم کر کے چھانٹنے والے رویے کو اپنی مرضی کے مطابق بنا سکتے ہیں ۔ آئیے ایک مثال دیکھتے ہیں:
import java.util.Comparator;
import java.util.TreeSet;

public class TreeSetSortingExample {
  public static void main(String[] args) {
    // Create a TreeSet with custom sorting
    TreeSet<Integer> numbers = new TreeSet<>(Comparator.reverseOrder());

    // Add elements to the TreeSet
    numbers.add(5);
    numbers.add(3);
    numbers.add(7);
    numbers.add(1);

    System.out.println(numbers); // Output: [7, 5, 3, 1]
  }
}
مندرجہ بالا کوڈ میں، ہم انٹیجر قسم کا ایک TreeSet بناتے ہیں اور Comparator.reverseOrder() کا استعمال کرتے ہوئے عناصر کو نزولی ترتیب میں ترتیب دینے کے لیے ایک حسب ضرورت موازنہ فراہم کرتے ہیں۔ نتیجے میں TreeSet عناصر پر مشتمل ہوگا [7, 5, 3, 1] ۔ TreeSet پر اعادہ کرنے کے متعدد طریقے ہیں ۔ ہم ایک تکرار کرنے والا استعمال کر سکتے ہیں یا ہر ایک لوپ کے لیے بڑھا ہوا استعمال کر سکتے ہیں ۔ آئیے دونوں طریقوں کی مثالیں دیکھیں:
import java.util.TreeSet;
import java.util.Iterator;

public class TreeSetIterationExample {
  public static void main(String[] args) {
    TreeSet<String> names = new TreeSet<>();

    names.add("Johnny");
    names.add("Ivy");
    names.add("Ricky");
    names.add("David");

    // Iterating using an iterator
    Iterator<String> iterator = names.iterator();
    while (iterator.hasNext()) {
      String name = iterator.next();
      System.out.println(name);
    }

    // Iterating using the enhanced for-each loop
    for (String name : names) {
      System.out.println(name);
    }
  }
}
مندرجہ بالا کوڈ میں، ہم ناموں کے نام سے ایک TreeSet بناتے ہیں اور کچھ عناصر شامل کرتے ہیں۔ اس کے بعد ہم TreeSet پر اعادہ کرنے کے دو طریقے دکھاتے ہیں : ایک تکرار کرنے والا استعمال کرنا اور ہر ایک کے لیے بڑھے ہوئے لوپ کو استعمال کرنا۔ TreeSet رینج کی بنیاد پر تلاش کرنے کے طریقے فراہم کرتا ہے، جس سے ہمیں مخصوص معیار کی بنیاد پر عناصر کے ذیلی سیٹوں کو بازیافت کرنے کی اجازت ملتی ہے۔ رینج پر مبنی تلاش کے تین اہم طریقے ہیں:
  • ذیلی سیٹ (E سے عنصر، E سے عنصر) : عنصر کے ذیلی سیٹ کو عنصر (شامل) سے عنصر (خصوصی) پر لوٹاتا ہے۔
  • headSet(E toElement) : toElement سے کم عناصر کا سب سیٹ لوٹاتا ہے ۔
  • tailSet(E fromElement) : عناصر کا ذیلی سیٹ واپس کرتا ہے fromElement سے بڑا یا اس کے برابر ۔
آئیے ایک مثال دیکھتے ہیں:
import java.util.TreeSet;

public class TreeSetRangeSearchExample {
  public static void main(String[] args) {
    TreeSet<Integer> numbers = new TreeSet<>();

    numbers.add(1);
    numbers.add(3);
    numbers.add(5);
    numbers.add(7);
    numbers.add(9);

    // Performing range-based search using subSet()
    TreeSet<Integer> subset = new TreeSet<>(numbers.subSet(3, 8));
    System.out.println(subset); // Output: [3, 5, 7]

    // Performing range-based search using headSet()
    TreeSet<Integer> headSet = new TreeSet<>(numbers.headSet(6));
    System.out.println(headSet); // Output: [1, 3, 5]

    // Performing range-based search using tailSet()
     TreeSet<Integer> tailSet = new TreeSet<>(numbers.tailSet(5));
    System.out.println(tailSet); // Output: [5, 7, 9]
  }
}
مندرجہ بالا کوڈ میں، ہم نمبرز کے نام سے ایک TreeSet بناتے ہیں اور کچھ عناصر شامل کرتے ہیں۔ پھر ہم subSet() , headSet() , اور tailSet() طریقوں کا استعمال کرتے ہوئے رینج پر مبنی تلاشوں کا مظاہرہ کرتے ہیں ۔
  • ذیلی سیٹ TreeSet میں 3 (شامل) اور 8 (خصوصی) کے درمیان عناصر ہوتے ہیں، جو کہ [3, 5, 7] ہیں ۔
  • ہیڈ سیٹ ٹری سیٹ میں 6 سے کم عناصر ہوتے ہیں جو کہ [1, 3, 5] ہیں ۔
  • ٹیل سیٹ ٹری سیٹ میں 5 سے زیادہ یا اس کے برابر عناصر ہوتے ہیں جو کہ [5, 7, 9] ہیں ۔
یہ رینج پر مبنی تلاش کے طریقے ہمیں مخصوص معیار کی بنیاد پر عناصر کے ذیلی سیٹوں کو بازیافت کرنے کی اجازت دیتے ہیں، ترتیب شدہ ڈیٹا کے ساتھ کام کرنے میں لچک فراہم کرتے ہیں۔

ٹری سیٹ میں موازنہ کرنے والا: حسب ضرورت معیار کے ساتھ ترتیب دینا

قدرتی ترتیب کے علاوہ، آپ TreeSet کو چھانٹنے کے لیے حسب ضرورت کمپیریٹر استعمال کر سکتے ہیں ۔ اس حصے میں، ہم موازنہ کرنے والے کے تصور اور TreeSet میں اس کے کردار کا جائزہ لیں گے ۔ ہم دریافت کریں گے کہ کس طرح ایک کسٹم کمپیریٹر کے ساتھ TreeSet بنایا جائے اور مخصوص معیار کی بنیاد پر TreeSet کو چھانٹنے کا مظاہرہ کرنے کے لیے کوڈ کی مثالیں فراہم کریں۔

Comparator کیا ہے؟

کمپیریٹر جاوا میں ایک انٹرفیس ہے جو اشیاء کی حسب ضرورت چھانٹنے کی اجازت دیتا ہے ۔ یہ مخصوص صفات یا خصوصیات کی بنیاد پر عناصر کی ترتیب کو متعین کرنے کا ایک طریقہ فراہم کرتا ہے۔ Comparator انٹرفیس کو لاگو کرکے اور اس کے compare() طریقہ کو اوور رائیڈ کرکے، ہم یہ بتا سکتے ہیں کہ TreeSet میں عناصر کو کس طرح ترتیب دیا جانا چاہیے ۔

کسٹم کمپیریٹر کے ساتھ ٹری سیٹ بنانا

اپنی مرضی کے مطابق موازنہ کرنے والے کے ساتھ TreeSet بنانے کے لیے ، ہمیں TreeSet مثال بناتے وقت ایک دلیل کے طور پر موازنہ فراہم کرنے کی ضرورت ہے ۔ آئیے ایک مثال دیکھتے ہیں:
import java.util.Comparator;
import java.util.TreeSet;

public class TreeSetComparatorExample {
  public static void main(String[] args) {
    // Create a TreeSet with a custom comparator
    TreeSet<String> names = new TreeSet<>(new LengthComparator());

    // Add elements to the TreeSet
    names.add("Johnny");
    names.add("Ivy");
    names.add("Rick");
    names.add("David");

    System.out.println(names); // Output: [Ivy, Johnny, David, Rick]
  }
}

class LengthComparator implements Comparator<String> {
  @Override
  public int compare(String s1, String s2) {
    return Integer.compare(s1.length(), s2.length());
  }
}
مندرجہ بالا کوڈ میں، ہم LengthComparator نامی اپنی مرضی کے موازنہ کے ساتھ ناموں کے نام سے ایک TreeSet بناتے ہیں ۔ LengthComparator دو تاروں کی لمبائی کا موازنہ کرتا ہے اور اس کے مطابق ترتیب دیتا ہے ۔ نتیجے کے طور پر، TreeSet کو تاروں کی لمبائی کی بنیاد پر ترتیب دیا جاتا ہے، جس سے ہمیں آؤٹ پٹ [Ivy, Rick, David, Johnny] ملتا ہے ۔

کمپیریٹر کا استعمال کرتے ہوئے ٹری سیٹ کو چھانٹنے کی مثالیں۔

اپنی مرضی کے مطابق موازنہ کرنے والے کے ساتھ ایک TreeSet بنانے کے علاوہ ، ہم ٹری سیٹ کو عارضی طور پر ترتیب دینے کے لیے اس کی قدرتی ترتیب کو تبدیل کیے بغیر بھی استعمال کر سکتے ہیں ۔ آئیے ایک مثال دیکھتے ہیں:
import java.util.Comparator;
import java.util.TreeSet;

  public class TreeSetTest {
    public static void main(String[] args) {
      TreeSet<String> names = new TreeSet<>();

      names.add("Johnny");
      names.add("Ivy");
      names.add("Ricky");
      names.add("David");

      // Sort TreeSet temporarily using a comparator
      TreeSet<String> sortedNames = new TreeSet<>(Comparator.reverseOrder());
      sortedNames.addAll(names);

      System.out.println(sortedNames); // Output: [Ricky, Johnny, Ivy, David]
      System.out.println(names); // Output: [David, Ivy, Johnny, Ricky]
    }
  }
مندرجہ بالا کوڈ میں، ہم ناموں کے نام سے ایک TreeSet بناتے ہیں اور کچھ عناصر شامل کرتے ہیں۔ اس کے بعد ہم ایک نیا TreeSet تشکیل دیتے ہیں جسے sortedNames کہتے ہیں ایک حسب ضرورت موازنہ Comparator.reverseOrder() کے ساتھ ۔ اصل ناموں TreeSet سے تمام عناصر کو sortedNames میں شامل کرنے سے ، ہم TreeSet کا ایک عارضی ترتیب شدہ ورژن حاصل کرتے ہیں ۔

دیگر ڈیٹا سٹرکچرز کے ساتھ TreeSet کا موازنہ کرنا

ٹری سیٹ کا ہیش سیٹ سے موازنہ کرنا

TreeSet اور HashSet دونوں جاوا میں سیٹ انٹرفیس کے نفاذ ہیں ۔ تاہم، ان کے درمیان اہم اختلافات ہیں. ٹری سیٹ : ٹری سیٹ منفرد عناصر کو ترتیب شدہ ترتیب میں اسٹور کرتا ہے۔ یہ ترتیب شدہ ترتیب کو برقرار رکھنے کے لیے خود توازن بائنری سرچ ٹری (عام طور پر ایک سرخ سیاہ درخت) کا استعمال کرتا ہے، جس کے نتیجے میں اندراج، حذف کرنے، اور تلاش جیسے کاموں کے لیے لوگاریتھمک وقت کی پیچیدگی پیدا ہوتی ہے۔ ٹری سیٹ ایک ترتیب شدہ مجموعہ کو برقرار رکھنے اور رینج پر مبنی کارروائیوں کو انجام دینے کے لیے موثر ہے۔ تاہم، درخت کے ڈھانچے کی وجہ سے اس میں زیادہ میموری اوور ہیڈ ہے اور یہ کالعدم عناصر کی اجازت نہیں دیتا ہے۔ HashSet : HashSet ہیش کوڈز اور ہیش ٹیبل کو اندرونی طور پر استعمال کرتے ہوئے منفرد عناصر کو غیر ترتیب شدہ انداز میں اسٹور کرتا ہے۔ یہ بنیادی کارروائیوں جیسے اندراج، حذف، اور تلاش کے لیے مستقل وقت کی پیچیدگی فراہم کرتا ہے۔ HashSet تیز عنصر کی تلاش کے لیے موثر ہے اور ترتیب کو برقرار رکھنے کے لیے کوئی اضافی میموری اوور ہیڈ نہیں لگاتا ہے۔ تاہم، یہ عناصر کی کسی خاص ترتیب کی ضمانت نہیں دیتا۔

ٹری سیٹ کب استعمال کریں:

  • جب آپ کو خود بخود ترتیب شدہ ترتیب میں عناصر کو برقرار رکھنے کی ضرورت ہوتی ہے۔
  • جب آپ کو رینج پر مبنی آپریشنز کی ضرورت ہو یا کسی مخصوص رینج کے اندر عناصر کو موثر طریقے سے تلاش کرنے کی ضرورت ہو۔
  • جب ڈپلیکیٹ عناصر کی اجازت نہیں ہے اور انفرادیت ضروری ہے۔
  • جب آپ خودکار چھانٹنے اور رینج آپریشنز کے فوائد کے لیے میموری کے قدرے زیادہ استعمال پر تجارت کرنے کو تیار ہوں۔

ArrayList کے ساتھ TreeSet کا موازنہ کرنا

ArrayList جاوا میں ایک متحرک صف کا نفاذ ہے۔ TreeSet اور ArrayList کے درمیان اہم فرق یہ ہیں :
  • TreeSet : TreeSet منفرد عناصر کو ترتیب شدہ ترتیب میں ذخیرہ کرتا ہے، ترتیب شدہ مجموعہ کو برقرار رکھنے اور رینج پر مبنی تلاشیں انجام دینے کے لیے موثر آپریشن فراہم کرتا ہے۔ اس میں آپریشنز کے لیے منطقی وقت کی پیچیدگی ہے۔ TreeSet بے ترتیب رسائی یا اندراج کی ترتیب کو برقرار رکھنے کے لیے موزوں نہیں ہے۔
  • ArrayList : ArrayList عناصر کو اندراج کی ترتیب میں ذخیرہ کرتا ہے، اشاریوں کا استعمال کرتے ہوئے عناصر تک تیزی سے بے ترتیب رسائی فراہم کرتا ہے۔ انڈیکس کے ذریعہ عناصر تک رسائی حاصل کرتے وقت اس میں زیادہ تر کارروائیوں کے لئے مستقل وقت کی پیچیدگی ہوتی ہے۔ تاہم، فہرست کے درمیان سے عناصر کو داخل کرنے یا ہٹانے کے لیے اس میں لکیری وقت کی پیچیدگی ہے، کیونکہ اس کے لیے عناصر کو منتقل کرنے کی ضرورت ہوتی ہے۔

ڈیٹا کے دوسرے ڈھانچے پر کب غور کرنا ہے۔

  • اگر ترتیب شدہ ترتیب میں عناصر کو برقرار رکھنے کی ضرورت نہیں ہے، اور آپ کو ایک تیز عنصر تلاش کرنے یا غیر ترتیب شدہ مجموعہ کی ضرورت ہے، تو HashSet ایک بہتر انتخاب ہوسکتا ہے۔
  • اگر آپ کو انڈیکس کے ذریعہ عناصر تک بار بار بے ترتیب رسائی کی ضرورت ہے یا اندراج کی ترتیب کو برقرار رکھنے کی ضرورت ہے تو، ArrayList زیادہ موزوں ہوگی۔
تبصرے
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION