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


    集合的典型应用: 

    客户统计

    词汇量统计

    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/
    欢迎任何形式的转载,未经作者同意,请保留此段声明!

  • 相关阅读:
    解决linux下打开windows下压缩文件乱码的问题
    vim & emacs 强制修改 root 权限的文件
    在ubuntu下,给 svn diff 一点颜色
    sql优化(一)
    sql优化(二) 索引(一)
    Java反射与思想!
    JDK5.0枚举 泛型 注释
    忘羡的Day9!
    来博客的第二天!
    来博客第一天
  • 原文地址:https://www.cnblogs.com/linlf03/p/14398223.html
Copyright © 2020-2023  润新知