數據結構-集合

集合( set)是一種包含不一樣元素的數據結構. 集合中的元素稱爲成員. 集合的兩個最重要的特性是: 首先, 集合中的成員是無序的; 其次, 集合中不容許相同成員存在. 集合在計算機科學中扮演了很是重要的角色, 然而在不少編程語言中, 並不把集合當成一種數據類型. 當你想要建立一個數據結構, 用來保存一些獨一無二的元素時, 好比一段文本中用到的單詞, 集合就變得很是有用.
ES6中已加入集合 Set

集合的定義、操做和屬性

集合是由一組無序但彼此之間又有必定相關性的成員構成的, 每一個成員在集合中只能出現一次.編程

集合的定義

下面是一些使用集合必須瞭解的定義.數組

  • 不包含任何成員的集合稱爲 空集_, _全集 則是包含一切可能成員的集合.
  • 若是兩個集合的成員徹底相同, 則稱兩個集合相等.
  • 若是一個集合中全部的成員都屬於另一個集合, 則前一集合稱爲後一集合的子集.

對集合的操做

對集合的基本操做有下面幾種:數據結構

  • 並集 : 將兩個集合中的成員進行合併, 獲得一個新的集合.
  • 交集 : 兩個集合中共同存在的成員組成一個新的集合.
  • 補集 : 屬於一個集合而不屬於另外一個集合的成員組成的集合.

Set類的實現

Set類的實現基於數組, 數組用來存儲數據.編程語言

window.log = console.log.bind(console)

class Set {
    constructor() {
        this._dataStore = [];
    }
    add(data) {
        if(!this._dataStore.includes(data)) {
            this._dataStore.push(data);
            return true;
        };
        return false;
    }
    remove(data) {
        const pos = this._dataStore.indexOf(data);
        if(pos > -1) {
            this._dataStore.splice(pos, 1);
            return true;
        };
        return false;
    }
    show() {
        return this._dataStore;
    }
};

add()方法: 由於集合中不能包含相同的元素, 因此, 使用add()方法將數據存儲到數組前, 先要確保數組中不存在該數據. 咱們使用indexof()檢查新加入的元素在數組是否存在. 若是找到, 該方法返回該元素在數組中的位置; 若是沒找到, 該方法返回-1. 若是數組中還未包含該元素, add()方法將新加入的元素保存在數組中並返回true; 反之返回false. 將add()方法的返回值定義爲布爾類型, 能夠明確告訴咱們是否將一個元素成功加入到了集合中. 這裏使用ES6中的includes()也是能夠的.測試

remove()方法和add()方法的工做原理相似. 首先檢查待刪除元素是否在數組中, 如何在, 則使用數組的splice()方法刪除該元素並返回true; 反之返回false, 表示集合中不存在這樣的一個元素.this

show()顯示集合中的成員.
測試程序:code

const s = new Set();
s.add('a');
s.add('b');
s.add('c');
s.add('d');
s.add('e');
s.add('f');
log(s.show());
if(s.add('f')) {
    log('f: 添加成功')
} else {
    log('已存在f, 添加失敗')
}

輸出:rem

(6) ["a", "b", "c", "d", "e", "f"]
已存在f, 添加失敗

更多集合操做

定義union()subset()difference()方法會更有意思. union()方法執行並集操做, 將兩個集合合併成一個. 該方法首先將第一個集合裏的成員悉數加入一個臨時集合, 而後檢查第二個集合中的成員, 看它們是否也同時屬於第一個集合. 若是屬於, 則跳過該成員, 不然就將該成員加入臨時集合.io

在定義union()方法前, 先定一個輔助方法contains(), 該方法檢查一個成員是否屬於該集合.console

contains(data) {
    return this._dataStore.includes(data);
}
// 並集
union(set) {
    const tempSet = new Set();
    this._dataStore.forEach(i => {
        tempSet.add(i);
    });
    set._dataStore.forEach(i => {
        if(!tempSet.contains(i)) {
            tempSet._dataStore.push(i)
        }
    });

    return tempSet;
}

執行程序:

const s = new Set();
s.add('a');
s.add('b');
s.add('c');
s.add('d');
s.add('e');
s.add('f');
log(s.show());

const s1 = new Set();
s1.add('a');
s1.add('f');
s1.add('g');

let res = new Set();
res = s.union(s1);
log(res.show());

//輸出:
// (6) ["a", "b", "c", "d", "e", "f"]
// (7) ["a", "b", "c", "d", "e", "f", "g"]

使用intersect()方法求兩個集合的交集. 該方法定義起來相對簡單. 每當發現第一個集合的成員也屬於第二個集合時, 便將該成員加入一個心機和, 這個心機和即爲方法的返回值.

// 交集
intersect(set) {
    const tempSet = new Set();
    this._dataStore.forEach(i => {
        if(set.contains(i)) {
            tempSet.add(i)
        };
    });

    return tempSet;
}

下一個要定義的操做是subset()判斷子集. subset()方法首先要肯定該集合的長度是否小於帶比較集合.
若是該集合比帶比較集合還要大, 那麼該集合確定不會是待比較集合的一個子集.
當集合的長度小於待比較集合時, 再判斷該集合內的成員是否都屬於待比較集合. 若是有任意一個成員不屬於待比較集合, 則返回false, 程序終止. 若是一直比較完該集合的最後一個元素, 全部元素都屬於待比較集合, 那麼該集合就是待比較集合的一個子集, 該方法返回true.
在判斷每一個元素是否屬於待比較集合前, 該方法先使用size()方法對比兩個集合的大小.

size() {
    return this._dataStore.length;
}
subSet(set) {
    if(this.size() > set.size()) {
        return false;
    };
    for(let i = 0; i < this._dataStore.length; i++) {
        if(!set.contains(this._dataStore[i])) {
            return false;
        };
    };
    return true;
}

最後一個操做是difference()補集, 該方法返回一個新集合, 該集合包含的是那些屬於第一個集合但不屬於第二個集合的成員.

difference(set) {
    const tempSet = new Set();
    this._dataStore.forEach(i => {
        if(!set.contains(i)) {
            tempSet.add(i);
        };
    });

    return tempSet;
}
相關文章
相關標籤/搜索