集合(基于二分搜索树的集合和基于链表的集合)

集合的典型应用: 

客户统计

词汇量统计

1、基于二分搜索树的集合

定义接口ISet

public interface ISet<E> {
    void add(E e);
    void remove(E e);
    boolean contains(E e);
    int getSize();
    boolean isEmpty();
}

定义基于二分搜索树的集合 

public class BinarySearchTreeSet<E extends  Comparable<E>> implements  ISet<E> {

    private BinarySearchTree<E> bst;

    public BinarySearchTreeSet(){
        bst = new BinarySearchTree<E>();
    }

    public void add(E e) {
        bst.add(e);
    }

    public void remove(E e) {
        bst.remove(e);
    }

    public boolean contains(E e) {
        return bst.contains(e);
    }

    public int getSize() {
        return bst.size();
    }

    public boolean isEmpty() {
        return bst.isEmpty();
    }
}

  

 2、 基于链表的集合

public class LinkedListSet<E> implements  ISet<E> {

    private LinkedList<E> linkedList;

    public LinkedListSet(){
        linkedList= new LinkedList<E>();
    }

    public void add(E e) {
        if(!linkedList.contains(e)){
            linkedList.addFirst(e);
        }

    }

    public void remove(E e) {
        linkedList.removeElement(e);
    }

    public boolean contains(E e) {
        return linkedList.contains(e);
    }

    public int getSize() {
        return linkedList.getSize();
    }

    public boolean isEmpty() {
        return linkedList.isEmpty();
    }
}

  

3、基于二分搜索树结合和链表结合性能对比

public class TwoSetTest {

    private static  double testSet(ISet<String> set){
        long startTime = System.nanoTime();
        String[] arr = {"张三", "李四","王五", "赵六","张三丰","李思明","王老五","赵明"};
        for(int i = 0; i < 5000; i++){
            for(String str : arr){
                set.add(str +i);
            }
        }
        long endTme = System.nanoTime();
        return  (endTme - startTime) / 1000000000.0;
    }

    public static void main(String[] args) {

        BinarySearchTreeSet<String> set2 = new BinarySearchTreeSet<String>();
        double time2 =  testSet(set2);
        System.out.println("二分搜索树Set花费" + time2);

        LinkedListSet<String> set1 = new LinkedListSet<String>();
        double time1 =  testSet(set1);
        System.out.println("链表Set花费" + time1);
        
    }
}

  

输出结果如下:

二分搜索树Set花费0.040670373
链表Set花费7.014404433

可以发现,二分搜索树的Set花费的时间明显小于基于链表的Set

两种集合的时间复杂度比较

  LinkedListSet
BinarySearchTreeSet
增add  O(n)  O(h), 或者平均O(logn) 最差O(n)
查contains  O(n)   O(h) ,或者平均O(logn) 最差O(n)
删remove  O(n)   O(h), 或者平均O(logn) 最差O(n)

h为数的高度。n和h的关系  h = logn , 2^h = n

BinarySearchTreeSet 最差O(n),比如

 最差是O(n),我们可以使用平衡二叉树,这个后面再进行介绍。

4、leetcode集合的使用题目 804 唯一摩尔斯密码词

https://leetcode-cn.com/problems/unique-morse-code-words/

题目描述

国际摩尔斯密码定义一种标准编码方式,将每个字母对应于一个由一系列点和短线组成的字符串, 比如: "a" 对应 ".-", "b" 对应 "-...", "c" 对应 "-.-.", 等等。

为了方便,所有26个英文字母对应摩尔斯密码表如下:

[".-","-...","-.-.","-..",".","..-.","--.","....","..",".---","-.-",".-..","--","-.","---",".--.","--.-",".-.","...","-","..-","...-",".--","-..-","-.--","--.."]
给定一个单词列表,每个单词可以写成每个字母对应摩尔斯密码的组合。例如,"cab" 可以写成 "-.-..--...",(即 "-.-." + ".-" + "-..." 字符串的结合)。我们将这样一个连接过程称作单词翻译。

返回我们可以获得所有词不同单词翻译的数量。

例如:
输入: words = ["gin", "zen", "gig", "msg"]
输出: 2
解释: 
各单词翻译如下:
"gin" -> "--...-."
"zen" -> "--...-."
"gig" -> "--...--."
"msg" -> "--...--."

共有 2 种不同翻译, "--...-." 和 "--...--.".

  

解决方法:

    public int uniqueMorseRepresentations(String[] words) {

        TreeSet<String> treeSet = new TreeSet<String>();
        String[] codes = {".-","-...","-.-.","-..",".","..-.","--.","....","..",".---","-.-",".-..","--","-.","---",".--.","--.-",".-.","...","-","..-","...-",".--","-..-","-.--","--.."};
        for(String word : words){
            StringBuilder res = new StringBuilder();
            for(int i = 0; i < word.length(); i++){
                res.append(codes[word.charAt(i) - 'a']);
            }
            treeSet.add(res.toString());
        }
        return treeSet.size();

    }

  

5、有序集合和无序集合

有序集合中的元素具有顺序性,如基于搜索树的实现

无序集合中的元素没有顺序性,基于哈希表的实现

6、多重集合

集合中的元素可以重复。

作者:Work Hard Work Smart
出处:http://www.cnblogs.com/linlf03/
欢迎任何形式的转载,未经作者同意,请保留此段声明!

原文地址:https://www.cnblogs.com/linlf03/p/14398223.html