數(shù)據(jù)結(jié)構(gòu)-集合Set

一 什么是集合和映射?

集合是高級(jí)數(shù)據(jù)結(jié)構(gòu)的一種匕争,它們的底層可以用多種方式來實(shí)現(xiàn)避乏,就像之前的棧和隊(duì)列一樣。集合就像一個(gè)容器一樣甘桑,我們這里實(shí)現(xiàn)的集合里邊存儲(chǔ)的數(shù)據(jù)是不能重復(fù)的拍皮,這樣的數(shù)據(jù)結(jié)構(gòu)可以幫助我們更加快速的進(jìn)行統(tǒng)計(jì)。講到這里是不是發(fā)現(xiàn)和我們之前的二分搜索樹非常相似扇住,其實(shí)這一次我們就會(huì)使用二分搜索樹作為集合的底層實(shí)現(xiàn)春缕。

二 二分搜索樹實(shí)現(xiàn)集合Set

1?? 實(shí)現(xiàn)集合Set接口
package com.mufeng.set;

/**
 * Created by wb-yxk397023 on 2018/7/4.
 */
public interface Set<E> {

    /**
     * 向集合中添加元素(實(shí)現(xiàn)去重的操作)
     * @param e
     */
    void add(E e);

    /**
     * 從集合中刪除元素
     * @param e
     */
    void remove(E e);

    /**
     * 查詢集合中是否有相同元素
     * @param e
     * @return
     */
    boolean contains(E e);

    /**
     * 獲取集合中元素的個(gè)數(shù)
     * @return
     */
    int getSize();

    /**
     * 查看集合是否為空
     * @return
     */
    boolean isEmpty();
}
2?? 實(shí)現(xiàn)具體的Set類
package com.mufeng.set;

import com.mufeng.binarySearchTree.BST;

/**
 * Created by wb-yxk397023 on 2018/7/4.
 */
public class BSTSet<E extends Comparable<E>> implements Set<E> {

    /**
     * 引入二分搜索樹
     */
    private BST<E> bst;

    /**
     * 初始化bst
     */
    public BSTSet(){
        bst = new BST<>();
    }
    /**
     * 向集合中添加元素(實(shí)現(xiàn)去重添加)
     * @param e
     */
    @Override
    public void add(E e) {
        bst.add(e);
    }

    /**
     * 從集合中刪除一個(gè)元素
     * @param e
     */
    @Override
    public void remove(E e) {
        bst.remove(e);
    }

    /**
     * 查看集合中是否包含元素e
     * @param e
     * @return
     */
    @Override
    public boolean contains(E e) {
        return bst.contains(e);
    }

    /**
     * 獲取集合中元素的個(gè)數(shù)
     * @return
     */
    @Override
    public int getSize() {
        return bst.size();
    }

    /**
     * 查看集合是否為空
     * @return
     */
    @Override
    public boolean isEmpty() {
        return bst.isEmpty();
    }
}

其實(shí)不難發(fā)現(xiàn),在使用二分搜索樹實(shí)現(xiàn)集合的時(shí)候艘蹋,我們沒有做多余的操作锄贼,因?yàn)槲覀冏约簩?shí)現(xiàn)的二分搜索樹已經(jīng)完全包含了集合的所有特性;

三 測(cè)試

1?? 編寫測(cè)試工具類
package com.mufeng.set;

import java.io.FileInputStream;
import java.util.ArrayList;
import java.util.Scanner;
import java.util.Locale;
import java.io.File;
import java.io.BufferedInputStream;
import java.io.IOException;

/**
 * Created by wb-yxk397023 on 2018/7/4.
 */
public class FileOperation {
    // 讀取文件名稱為filename中的內(nèi)容女阀,并將其中包含的所有詞語放進(jìn)words中
    public static boolean readFile(String filename, ArrayList<String> words){

        if (filename == null || words == null){
            System.out.println("filename is null or words is null");
            return false;
        }

        // 文件讀取
        Scanner scanner;

        try {
            File file = new File(filename);
            if(file.exists()){
                FileInputStream fis = new FileInputStream(file);
                scanner = new Scanner(new BufferedInputStream(fis), "UTF-8");
                scanner.useLocale(Locale.ENGLISH);
            }
            else
                return false;
        }
        catch(IOException ioe){
            System.out.println("Cannot open " + filename);
            return false;
        }

        // 簡(jiǎn)單分詞
        // 這個(gè)分詞方式相對(duì)簡(jiǎn)陋, 沒有考慮很多文本處理中的特殊問題
        // 在這里只做demo展示用
        if (scanner.hasNextLine()) {

            String contents = scanner.useDelimiter("\\A").next();

            int start = firstCharacterIndex(contents, 0);
            for (int i = start + 1; i <= contents.length(); )
                if (i == contents.length() || !Character.isLetter(contents.charAt(i))) {
                    String word = contents.substring(start, i).toLowerCase();
                    words.add(word);
                    start = firstCharacterIndex(contents, i);
                    i = start + 1;
                } else
                    I++;
        }

        return true;
    }

    // 尋找字符串s中宅荤,從start的位置開始的第一個(gè)字母字符的位置
    private static int firstCharacterIndex(String s, int start){

        for( int i = start ; i < s.length() ; i ++ )
            if( Character.isLetter(s.charAt(i)) )
                return I;
        return s.length();
    }
}
2?? 引入測(cè)試文件

a-tale-of-two-cities.txt
pride-and-prejudice.txt

3?? 編寫測(cè)試程序
package com.mufeng;

import com.mufeng.set.BSTSet;
import com.mufeng.set.FileOperation;
import java.util.ArrayList;

public class Main {

    public static void main(String[] args) {
        System.out.println("Pride and Prejudice");

        ArrayList<String> words1 = new ArrayList<>();
        if(FileOperation.readFile("pride-and-prejudice.txt", words1)) {
            System.out.println("Total words: " + words1.size());

            BSTSet<String> set1 = new BSTSet<>();
            for (String word : words1)
                set1.add(word);
            System.out.println("Total different words: " + set1.getSize());
        }

        System.out.println();
        
        System.out.println("A Tale of Two Cities");

        ArrayList<String> words2 = new ArrayList<>();
        if(FileOperation.readFile("a-tale-of-two-cities.txt", words2)){
            System.out.println("Total words: " + words2.size());

            BSTSet<String> set2 = new BSTSet<>();
            for(String word: words2)
                set2.add(word);
            System.out.println("Total different words: " + set2.getSize());
        }
    }
}
測(cè)試結(jié)果

四 鏈表實(shí)現(xiàn)集合Set

package com.mufeng.set;

import com.mufeng.linkedList.LinkedList;

/**
 * Created by wb-yxk397023 on 2018/7/4.
 */
public class LinkedListSet<E> implements Set<E> {

    /**
     * 引入鏈表
     */
    private LinkedList<E> linkedList;

    /**
     * 初始化
     */
    public LinkedListSet(){
        linkedList = new LinkedList<>();
    }

    /**
     * 向集合中添加元素(去重添加)
     * @param e
     */
    @Override
    public void add(E e) {
        // 實(shí)現(xiàn)去重添加元素e
        if (!linkedList.contains(e)){
            linkedList.addFrist(e);
        }
    }

    /**
     * 從集合中刪除元素
     * @param e
     */
    @Override
    public void remove(E e) {
        linkedList.removeElement(e);
    }

    /**
     * 查看集合是否包含元素e
     * @param e
     * @return
     */
    @Override
    public boolean contains(E e) {
        return linkedList.contains(e);
    }

    /**
     * 獲取集合中元素的個(gè)數(shù)
     * @return
     */
    @Override
    public int getSize() {
        return linkedList.getSize();
    }

    /**
     * 查看集合是否為空
     * @return
     */
    @Override
    public boolean isEmpty() {
        return linkedList.isEmpty();
    }
}

五 測(cè)試

package com.mufeng;

import com.mufeng.set.FileOperation;
import com.mufeng.set.LinkedListSet;

import java.util.ArrayList;

public class Main {

    public static void main(String[] args) {
        System.out.println("Pride and Prejudice");

        ArrayList<String> words1 = new ArrayList<>();
        if(FileOperation.readFile("pride-and-prejudice.txt", words1)) {
            System.out.println("Total words: " + words1.size());

            LinkedListSet<String> set1 = new LinkedListSet<>();
            for (String word : words1)
                set1.add(word);
            System.out.println("Total different words: " + set1.getSize());
        }

        System.out.println();


        System.out.println("A Tale of Two Cities");

        ArrayList<String> words2 = new ArrayList<>();
        if(FileOperation.readFile("a-tale-of-two-cities.txt", words2)){
            System.out.println("Total words: " + words2.size());

            LinkedListSet<String> set2 = new LinkedListSet<>();
            for(String word: words2)
                set2.add(word);
            System.out.println("Total different words: " + set2.getSize());
        }
    }
}
測(cè)試結(jié)果

六 兩種實(shí)現(xiàn)方式的性能對(duì)比

1?? 測(cè)試類
package com.mufeng;

import com.mufeng.set.BSTSet;
import com.mufeng.set.FileOperation;
import com.mufeng.set.LinkedListSet;
import com.mufeng.set.Set;

import java.util.ArrayList;

public class Main {

    private static double testSet(Set<String> set, String filename){

        long startTime = System.nanoTime();

        System.out.println(filename);
        ArrayList<String> words = new ArrayList<>();
        if(FileOperation.readFile(filename, words)) {
            System.out.println("Total words: " + words.size());

            for (String word : words)
                set.add(word);
            System.out.println("Total different words: " + set.getSize());
        }
        long endTime = System.nanoTime();

        return (endTime - startTime) / 1000000000.0;
    }

    public static void main(String[] args) {

        String filename = "pride-and-prejudice.txt";

        BSTSet<String> bstSet = new BSTSet<>();
        double time1 = testSet(bstSet, filename);
        System.out.println("BST Set: " + time1 + " s");

        System.out.println();

        LinkedListSet<String> linkedListSet = new LinkedListSet<>();
        double time2 = testSet(linkedListSet, filename);
        System.out.println("Linked List Set: " + time2 + " s");

    }
}
測(cè)試結(jié)果
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市浸策,隨后出現(xiàn)的幾起案子冯键,更是在濱河造成了極大的恐慌,老刑警劉巖庸汗,帶你破解...
    沈念sama閱讀 217,542評(píng)論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件惫确,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡蚯舱,警方通過查閱死者的電腦和手機(jī)改化,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,822評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來枉昏,“玉大人陈肛,你說我怎么就攤上這事⌒至眩” “怎么了句旱?”我有些...
    開封第一講書人閱讀 163,912評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)晰奖。 經(jīng)常有香客問我谈撒,道長(zhǎng),這世上最難降的妖魔是什么匾南? 我笑而不...
    開封第一講書人閱讀 58,449評(píng)論 1 293
  • 正文 為了忘掉前任啃匿,我火速辦了婚禮,結(jié)果婚禮上午衰,老公的妹妹穿的比我還像新娘立宜。我一直安慰自己,他們只是感情好臊岸,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,500評(píng)論 6 392
  • 文/花漫 我一把揭開白布橙数。 她就那樣靜靜地躺著,像睡著了一般帅戒。 火紅的嫁衣襯著肌膚如雪灯帮。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,370評(píng)論 1 302
  • 那天逻住,我揣著相機(jī)與錄音钟哥,去河邊找鬼。 笑死瞎访,一個(gè)胖子當(dāng)著我的面吹牛腻贰,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播扒秸,決...
    沈念sama閱讀 40,193評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼播演,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了伴奥?” 一聲冷哼從身側(cè)響起写烤,我...
    開封第一講書人閱讀 39,074評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎拾徙,沒想到半個(gè)月后洲炊,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,505評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡尼啡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,722評(píng)論 3 335
  • 正文 我和宋清朗相戀三年暂衡,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片玄叠。...
    茶點(diǎn)故事閱讀 39,841評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡古徒,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出读恃,到底是詐尸還是另有隱情隧膘,我是刑警寧澤,帶...
    沈念sama閱讀 35,569評(píng)論 5 345
  • 正文 年R本政府宣布寺惫,位于F島的核電站疹吃,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏西雀。R本人自食惡果不足惜萨驶,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,168評(píng)論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望艇肴。 院中可真熱鬧腔呜,春花似錦叁温、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,783評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至谤草,卻和暖如春跟束,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背丑孩。 一陣腳步聲響...
    開封第一講書人閱讀 32,918評(píng)論 1 269
  • 我被黑心中介騙來泰國(guó)打工冀宴, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人温学。 一個(gè)月前我還...
    沈念sama閱讀 47,962評(píng)論 2 370
  • 正文 我出身青樓略贮,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親枫浙。 傳聞我的和親對(duì)象是個(gè)殘疾皇子刨肃,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,781評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容