📜  Java中的树集

📅  最后修改于: 2022-05-13 01:54:42.279000             🧑  作者: Mango

Java中的树集

TreeSet 是Java中 SortedSet 接口的最重要实现之一,它使用树进行存储。无论是否提供显式比较器,元素的顺序都由一个集合使用它们的自然顺序来维护。这必须与equals一致才能正确实现Set接口。

它也可以通过在集合创建时提供的 Comparator 进行排序,具体取决于使用的构造函数。 TreeSet 通过继承 AbstractSet 类实现了一个 NavigableSet 接口。

Set-TreeSet-SortedSet-In-Java-Collection

从上图中可以明显看出,navigable set 扩展了 sorted set 接口。由于集合不保留插入顺序,因此可导航集合接口提供了在集合中导航的实现。实现可导航集的类是 TreeSet,它是自平衡树的实现。因此,这个界面为我们提供了一种在这棵树中导航的方法。

TreeSet 如何在内部工作?

TreeSet 基本上是一个自平衡二叉搜索树的实现,如红黑树。因此,添加、删除和搜索等操作需要 O(log(N)) 时间。原因是在自平衡树中,确保所有操作的树的高度始终为 O(log(N))。因此,这被认为是最有效的数据结构之一,以便存储大量排序数据并对其执行操作。但是,以排序顺序打印 N 个元素等操作需要 O(N) 时间。

现在让我们在继续之前讨论同步树集。 TreeSet 的实现是不同步的。这意味着如果多个线程同时访问一个树集,并且至少有一个线程修改了该集,则它必须在外部同步。这通常是通过同步一些自然封装集合的对象来完成的。如果不存在这样的对象,则应使用 Collections.synchronizedSortedSet 方法“包装”该集合。这最好在创建时完成,以防止对集合的意外不同步访问。可以如下图实现:

TreeSet ts = new TreeSet(); 
Set syncSet = Collections.synchronziedSet(ts); 

TreeSet 类的构造函数如下:

为了创建 TreeSet,我们需要创建 TreeSet 类的对象。 TreeSet 类由各种构造函数组成,这些构造函数允许创建 TreeSet。以下是此类中可用的构造函数:

  • TreeSet():此构造函数用于构建一个空的 TreeSet 对象,其中元素将以默认的自然排序顺序存储。

语法:如果我们希望创建一个名为 ts 的空 TreeSet,则可以将其创建为:

TreeSet ts = new TreeSet(); 
  • TreeSet(Comparator):此构造函数用于构建一个空的 TreeSet 对象,其中的元素将需要排序顺序的外部规范。

语法:如果我们希望创建一个名称为 ts 且具有外部排序现象的空 TreeSet,则可以将其创建为:

TreeSet ts = new TreeSet(Comparator comp); 
  • TreeSet(Collection):此构造函数用于构建一个 TreeSet 对象,该对象包含给定集合中的所有元素,其中元素将以默认的自然排序顺序存储。简而言之,当需要从任何 Collection 对象到 TreeSet 对象的任何转换时,都会使用此构造函数。

语法:如果我们希望创建一个名称为 ts 的 TreeSet,那么可以按如下方式创建它:

TreeSet t = new TreeSet(Collection col);  
  • TreeSet(SortedSet):此构造函数用于构建一个 TreeSet 对象,该对象包含给定 sortedset 中的所有元素,其中元素将以默认的自然排序顺序存储。简而言之,这个构造函数用于将 SortedSet 对象转换为 TreeSet 对象。

语法:如果我们希望创建一个名称为 ts 的 TreeSet,那么可以按如下方式创建它:

TreeSet t = new TreeSet(SortedSet s);

TreeSet 类中的方法在下面以表格格式描述,稍后我们将在实现部分展示这些方法。

TreeSet 实现了 SortedSet,因此它可以使用 Collection、Set 和 SortedSet 接口中的所有方法。以下是 Treeset 接口中的方法。在下表中,“?”表示该方法适用于任何类型的对象,包括用户定义的对象。

MethodDescription
add(Object o)This method will add the specified element according to the same sorting order mentioned during the creation of the TreeSet. Duplicate entries will not get added.
addAll(Collection c)This method will add all elements of the specified Collection to the set. Elements in the Collection should be homogeneous otherwise ClassCastException will be thrown. Duplicate Entries of Collection will not be added to TreeSet.
ceiling?(E e)This method returns the least element in this set greater than or equal to the given element, or null if there is no such element.
clear()This method will remove all the elements.
clone()The method is used to return a shallow copy of the set, which is just a simple copied set.
Comparator comparator()This method will return the Comparator used to sort elements in TreeSet or it will return null if the default natural sorting order is used.
contains(Object o)This method will return true if a given element is present in TreeSet else it will return false.
descendingIterator?()This method returns an iterator over the elements in this set in descending order.
descendingSet?()This method returns a reverse order view of the elements contained in this set.
first()This method will return the first element in TreeSet if TreeSet is not null else it will throw NoSuchElementException.
floor?(E e)This method returns the greatest element in this set less than or equal to the given element, or null if there is no such element.
headSet(Object toElement)This method will return elements of TreeSet which are less than the specified element.
higher?(E e)This method returns the least element in this set strictly greater than the given element, or null if there is no such element.
isEmpty()This method is used to return true if this set contains no elements or is empty and false for the opposite case.
Iterator iterator()Returns an iterator for iterating over the elements of the set.
last()This method will return the last element in TreeSet if TreeSet is not null else it will throw NoSuchElementException.
lower?(E e)This method returns the greatest element in this set strictly less than the given element, or null if there is no such element.
pollFirst?()This method retrieves and removes the first (lowest) element, or returns null if this set is empty.
pollLast?()This method retrieves and removes the last (highest) element, or returns null if this set is empty.
remove(Object o)This method is used to return a specific element from the set.
size()This method is used to return the size of the set or the number of elements present in the set.
spliterator()This method creates a late-binding and fail-fast Spliterator over the elements in this set.
subSet(Object fromElement, Object toElement)This method will return elements ranging from fromElement to toElement. fromElement is inclusive and toElement is exclusive.
tailSet(Object fromElement)This method will return elements of TreeSet which are greater than or equal to the specified element.

插图:以下实现演示了如何创建和使用 TreeSet。

Java
// Java program to Illustrate Working of  TreeSet
 
// Importing required utility classes
import java.util.*;
 
// Main class
class GFG {
 
    // Main driver method
    public static void main(String[] args)
    {
        // Creating a Set interface with reference to
        // TreeSet
        Set ts1 = new TreeSet<>();
 
        // Elements are added using add() method
        ts1.add("A");
        ts1.add("B");
        ts1.add("C");
 
        // Duplicates will not get insert
        ts1.add("C");
 
        // Elements get stored in default natural
        // Sorting Order(Ascending)
        System.out.println(ts1);
    }
}


Java
// Java code to Illustrate Addition of Elements to TreeSet
 
// Importing utility classes
import java.util.*;
 
// Main class
class GFG {
 
    // Main driver method
    public static void main(String[] args)
    {
        // Creating a Set interface with
        // reference to TreeSet class
        // Declaring object of string type
        Set ts = new TreeSet<>();
 
        // Elements are added using add() method
        ts.add("Geek");
        ts.add("For");
        ts.add("Geeks");
 
        // Print all elements inside object
        System.out.println(ts);
    }
}


Java
// Java code to Illustrate Working of TreeSet by
// Accessing the Element of TreeSet
 
// Importing utility classes
import java.util.*;
 
// Main class
class GFG {
 
    // Main driver method
    public static void main(String[] args)
    {
        // Creating a NavigableSet object  with
      // reference to TreeSet class
        NavigableSet ts = new TreeSet<>();
 
        // Elements are added using add() method
        ts.add("Geek");
        ts.add("For");
        ts.add("Geeks");
 
         // Printing the elements inside the TreeSet object
        System.out.println("Tree Set is " + ts);
 
        String check = "Geeks";
 
        // Check if the above string exists in
        // the treeset or not
        System.out.println("Contains " + check + " "
                           + ts.contains(check));
 
        // Print the first element in
        // the TreeSet
        System.out.println("First Value " + ts.first());
 
        // Print the last element in
        // the TreeSet
        System.out.println("Last Value " + ts.last());
 
        String val = "Geek";
 
        // Find the values just greater
        // and smaller than the above string
        System.out.println("Higher " + ts.higher(val));
        System.out.println("Lower " + ts.lower(val));
    }
}


Java
// Java Program to Illustrate Removal of Elements
// in a TreeSet
 
// Importing utility classes
import java.util.*;
 
// Main class
class GFG {
 
    // Main driver method
    public static void main(String[] args)
    {
        // Creating an object of NavigableSet
        // with reference to TreeSet class
        // Declaring object of string type
        NavigableSet ts = new TreeSet<>();
 
        // Elements are added
        // using add() method
        ts.add("Geek");
        ts.add("For");
        ts.add("Geeks");
        ts.add("A");
        ts.add("B");
        ts.add("Z");
 
        // Print and display initial elements of TreeSet
        System.out.println("Initial TreeSet " + ts);
 
        // Removing a specific existing element inserted
        // above
        ts.remove("B");
 
        // Printing the updated TreeSet
        System.out.println("After removing element " + ts);
 
        // Now removing the first element
        // using pollFirst() method
        ts.pollFirst();
 
        // Again printing the updated TreeSet
        System.out.println("After removing first " + ts);
 
        // Removing the last element
        // using pollLast() method
        ts.pollLast();
 
        // Lastly printing the elements of TreeSet remaining
        // to figure out pollLast() method
        System.out.println("After removing last " + ts);
    }
}


Java
// Java Program to Illustrate Working of TreeSet
 
// Importing utility classes
import java.util.*;
 
// Main class
class GFG {
 
    // Main driver method
    public static void main(String[] args)
    {
        // Creating an object of Set with reference to
        // TreeSet class
 
        // Note: You can refer above media if geek
        // is confused in programs why we are not
        // directly creating TreeSet object
        Set ts = new TreeSet<>();
 
        // Adding elements in above object
        // using add() method
        ts.add("Geek");
        ts.add("For");
        ts.add("Geeks");
        ts.add("A");
        ts.add("B");
        ts.add("Z");
 
        // Now we will be using for each loop in order
        // to iterate through the TreeSet
        for (String value : ts)
 
            // Printing the values inside the object
            System.out.print(value + ", ");
 
        System.out.println();
    }
}


Java
// Java code to illustrate What if Heterogeneous
// Objects are Inserted
 
// Importing all utility classes
import java.util.*;
 
// Main class
class GFG {
 
    // Main driver method
    public static void main(String[] args)
    {
 
        // Object creation
        Set ts = new TreeSet<>();
 
        // Adding elements to above object
        // using add() method
        ts.add(new StringBuffer("A"));
        ts.add(new StringBuffer("Z"));
        ts.add(new StringBuffer("L"));
        ts.add(new StringBuffer("B"));
        ts.add(new StringBuffer("O"));
        ts.add(new StringBuffer(1));
 
        // Note: StringBuffer implements Comparable
        // interface
 
        // Printing the elements
        System.out.println(ts);
    }
}


输出:
[A, B, C]

执行:

在这里,我们将对 TreeSet 对象执行各种操作,以熟悉Java中 TreeSet 的方法和概念。让我们看看如何在 TreeSet 上执行一些常用的操作。它们列出如下:

  • 添加元素
  • 访问元素
  • 移除元素
  • 遍历元素

现在让我们稍后在干净的Java程序的帮助下逐个讨论每个操作。

操作 1:添加元素

为了向 TreeSet 添加元素,我们可以使用 add() 方法。但是,插入顺序不会保留在 TreeSet 中。在内部,对于每个元素,值都会按升序进行比较和排序。我们需要注意,不允许重复元素,所有重复元素都将被忽略。而且,TreeSet 不接受 Null 值。

例子

Java

// Java code to Illustrate Addition of Elements to TreeSet
 
// Importing utility classes
import java.util.*;
 
// Main class
class GFG {
 
    // Main driver method
    public static void main(String[] args)
    {
        // Creating a Set interface with
        // reference to TreeSet class
        // Declaring object of string type
        Set ts = new TreeSet<>();
 
        // Elements are added using add() method
        ts.add("Geek");
        ts.add("For");
        ts.add("Geeks");
 
        // Print all elements inside object
        System.out.println(ts);
    }
}
输出:
[For, Geek, Geeks]

操作 2:访问元素

添加元素后,如果我们希望访问元素,可以使用内置方法,如 contains()、first()、last() 等。

例子

Java

// Java code to Illustrate Working of TreeSet by
// Accessing the Element of TreeSet
 
// Importing utility classes
import java.util.*;
 
// Main class
class GFG {
 
    // Main driver method
    public static void main(String[] args)
    {
        // Creating a NavigableSet object  with
      // reference to TreeSet class
        NavigableSet ts = new TreeSet<>();
 
        // Elements are added using add() method
        ts.add("Geek");
        ts.add("For");
        ts.add("Geeks");
 
         // Printing the elements inside the TreeSet object
        System.out.println("Tree Set is " + ts);
 
        String check = "Geeks";
 
        // Check if the above string exists in
        // the treeset or not
        System.out.println("Contains " + check + " "
                           + ts.contains(check));
 
        // Print the first element in
        // the TreeSet
        System.out.println("First Value " + ts.first());
 
        // Print the last element in
        // the TreeSet
        System.out.println("Last Value " + ts.last());
 
        String val = "Geek";
 
        // Find the values just greater
        // and smaller than the above string
        System.out.println("Higher " + ts.higher(val));
        System.out.println("Lower " + ts.lower(val));
    }
}
输出:
Tree Set is [For, Geek, Geeks]
Contains Geeks true
First Value For
Last Value Geeks
Higher Geeks
Lower For

操作 3:删除值

可以使用 remove() 方法从 TreeSet 中删除这些值。有多种其他方法可用于删除第一个值或最后一个值。

例子

Java

// Java Program to Illustrate Removal of Elements
// in a TreeSet
 
// Importing utility classes
import java.util.*;
 
// Main class
class GFG {
 
    // Main driver method
    public static void main(String[] args)
    {
        // Creating an object of NavigableSet
        // with reference to TreeSet class
        // Declaring object of string type
        NavigableSet ts = new TreeSet<>();
 
        // Elements are added
        // using add() method
        ts.add("Geek");
        ts.add("For");
        ts.add("Geeks");
        ts.add("A");
        ts.add("B");
        ts.add("Z");
 
        // Print and display initial elements of TreeSet
        System.out.println("Initial TreeSet " + ts);
 
        // Removing a specific existing element inserted
        // above
        ts.remove("B");
 
        // Printing the updated TreeSet
        System.out.println("After removing element " + ts);
 
        // Now removing the first element
        // using pollFirst() method
        ts.pollFirst();
 
        // Again printing the updated TreeSet
        System.out.println("After removing first " + ts);
 
        // Removing the last element
        // using pollLast() method
        ts.pollLast();
 
        // Lastly printing the elements of TreeSet remaining
        // to figure out pollLast() method
        System.out.println("After removing last " + ts);
    }
}
输出:
Initial TreeSet [A, B, For, Geek, Geeks, Z]
After removing element [A, For, Geek, Geeks, Z]
After removing first [For, Geek, Geeks, Z]
After removing last [For, Geek, Geeks]

操作 4:遍历 TreeSet

有多种方法可以遍历 TreeSet。最著名的一种是使用增强的 for 循环。和极客,你会用这种方法迭代元素,同时在 TreeSet 上练习问题,因为这在涉及树、地图和图形问题时最常用。

例子

Java

// Java Program to Illustrate Working of TreeSet
 
// Importing utility classes
import java.util.*;
 
// Main class
class GFG {
 
    // Main driver method
    public static void main(String[] args)
    {
        // Creating an object of Set with reference to
        // TreeSet class
 
        // Note: You can refer above media if geek
        // is confused in programs why we are not
        // directly creating TreeSet object
        Set ts = new TreeSet<>();
 
        // Adding elements in above object
        // using add() method
        ts.add("Geek");
        ts.add("For");
        ts.add("Geeks");
        ts.add("A");
        ts.add("B");
        ts.add("Z");
 
        // Now we will be using for each loop in order
        // to iterate through the TreeSet
        for (String value : ts)
 
            // Printing the values inside the object
            System.out.print(value + ", ");
 
        System.out.println();
    }
}
输出:
A, B, For, Geek, Geeks, Z,

树集的特点:

  1. TreeSet 实现了 SortedSet 接口。因此,不允许重复值。
  2. TreeSet 中的对象按排序和升序存储。
  3. TreeSet 不保留元素的插入顺序,但元素按键排序。
  4. 如果我们依赖于默认的自然排序顺序,则插入树中的对象应该是同类且可比较的。 TreeSet 不允许插入异构对象。如果我们尝试添加异构对象,它将在运行时抛出一个 classCastException。
  5. TreeSet 只能接受可比较的泛型类型。
    例如,StringBuffer 类实现了 Comparable 接口

Java

// Java code to illustrate What if Heterogeneous
// Objects are Inserted
 
// Importing all utility classes
import java.util.*;
 
// Main class
class GFG {
 
    // Main driver method
    public static void main(String[] args)
    {
 
        // Object creation
        Set ts = new TreeSet<>();
 
        // Adding elements to above object
        // using add() method
        ts.add(new StringBuffer("A"));
        ts.add(new StringBuffer("Z"));
        ts.add(new StringBuffer("L"));
        ts.add(new StringBuffer("B"));
        ts.add(new StringBuffer("O"));
        ts.add(new StringBuffer(1));
 
        // Note: StringBuffer implements Comparable
        // interface
 
        // Printing the elements
        System.out.println(ts);
    }
}
输出
[, A, B, L, O, Z]