JavaScript 入门基础之自己实现一个类似 Set 的数据结构

基本的数据结构

function Set() {
    // collection 变量用来存储集合中的元素
    var collection = [];
    // 当集合中存在 element 元素时返回 true 否则返回 false
    this.has = function(element) {
        return (collection.indexOf(element) !== -1);
    };
    // 该方法会返回集合内所有元素
    this.values = function() {
        return collection;
    };
}

添加一个 add 方法。 由于 set 集合当中不存在重复元素。因此在添加之前,首先需要进行判断该元素是否存在。

this.add = function (element) {
  if (!this.has(element)) {
    collection.push(element);
    return true;
  }
  return false;
};

添加一个 remove 方法。判断该元素是否在集合中。若存在,则删除

this.remove = function (element) {
  if (this.has(element)) {
    for (let i = 0; i < collection.length; i++) {
      if (collection[i] === element) {
        collection.splice(i, 1)
        return true
      }
    }
  } else {
    return false
  }
}

//-------
this.remove = function (element) {
  if (this.has(element)) {
    var index = collection.indexOf(element);
    collection.splice(index, 1);
    return true;
  }
  return false;
};

添加一个 size 方法。返回集合中元素的个数

this.size = function() {
  return collection.length
}

添加一个求两个集合的并集

this.union = function (set) {
  const newSet = new Set();
  this.values().forEach(value => {
    newSet.add(value);
  })
  set.values().forEach(value => {
    newSet.add(value);
  })
  return newSet;
}
this.union = function (anotherSet) {
  const newSet = new Set();
  const addToSet = el => newSet.add(el);
  this.values().forEach(addToSet);
  anotherSet.values().forEach(addToSet);
  return newSet;
}

添加一个方法,求两个集合的交集

this.intersection = function (otherSet) {
  var intersectionSet = new Set();
  var firstSet = this.values();
  firstSet.forEach(function (e) {
    if (otherSet.has(e)) {
      intersectionSet.add(e);
    }
  });
  return intersectionSet;
};

参考答案解法

this.intersection = function (set) {
  const newSet = new Set();
  let largeSet;
  let smallSet;
  if (this.dictionary.length > set.length) {
    largeSet = this;
    smallSet = set;
  } else {
    largeSet = set;
    smallSet = this;
  }
  smallSet.values().forEach(value => {
    if (largeSet.dictionary[value]) {
      newSet.add(value);
    }
  })
  return newSet;
}

添加一个 difference 方法。求两个集合的差异

this.difference = function (otherSet) {
  let differenceSet = new Set()
  let firstSet = this.values()
  firstSet.forEach(function (e) {
    if (!otherSet.has(e)) {
      differenceSet.add(e)
    }
  })
  return differenceSet
}

添加一个 subset 方法。求某个集合是否为另一个集合的子集。

this.subset = function (otherSet) {
  let firstSet = this.values()
  firstSet.forEach(function (e) {
    if (otherSet.has(e)) {
      return true
    }
    return false
  })
}

当然 ES6 的 set 数据结构的内部实现肯定比这个要更加完善,也更加高效。


Map 是一种存储键值对的数据结构。在 JavaScript 中,对象就是 Map 的一种表现形式。Map 是一种十分通用和高效的数据查询结构,我们可以在 Map 中通过 key(键)快速地获取对应的 value(值)。

var Map = function() {
  this.collection = {}
}

add方法接收keyvalue作为参数,并把键值对添加到 Map 中

this.add = (key, value) => {
    this.collection[key] = value
  }

remove方法接收一个key值并移除对应的键值对

this.remove = (key) => {
    if (this.has(key)) {
      delete this.collection[key];
    }
  }

get方法接收key值,并返回对应的value

this.get = (key) => { 
    if (this.has(key)) {
      return this.collection[key];
    } else {
      return undefined;
    }
  }

has方法根据值的存在情况返回相应的boolean

 this.has = (key) => {
    return this.collection.hasOwnProperty(key)
  }

values方法以数组形式返回 Map 中所有的 value

this.values = () => {  
    return [...Object.values(this.collection)]
  }

size方法返回 Map 中元素的个数

this.size = () => {
    return Object.entries(this.collection).length
  }

clear清空 Map。

 this.clear = () => {
    this.collection = {}
  }

哈希表接收一个 key 作为参数,并以特定的方式把 key 转换为一串数字。该数字串会与 value 值建立对应关系,并存储到表中。如果你想获取该 key 值,hashing 函数会接收 key 作为参数,并经过计算后得到与存储时的 key 相同的数字串,然后通过该数字串获取对应的 value。这种查询方式非常高效,平均时间复杂度为 O(n)。

试想一下,假如两个不同的 key 值通过同一个 hash 函数产生了相同的值怎么办?我们称这种情况为 collision(冲突)。解决冲突的一种方式是将键值对存入该 index 中。在查询时,你需要遍历一下这个 index 上存储的所有数据,找出你需要的那一条。一个好的 hash 函数应维持较低的冲突发生率,以保证查询效率。

var called = 0;
var hash = (string) => {
  called++;
  var hash = 0;
  for (var i = 0; i < string.length; i++) { hash += string.charCodeAt(i); }
  return hash;
};
var HashTable = function () {
  this.collection = {}
}

add 方法接收一个键值对参数并把它存储到哈希表中

this.add = function (key, val) {
    var theHash = hash(key);
    if (!this.collection.hasOwnProperty(theHash)) {
      this.collection[theHash] = {};
    }
    this.collection[theHash][key] = val;
  }

remove 方法接收一个 key 为参数并移除对应的键值对

this.remove = function (key) {
    var hashedObj = this.collection[hash(key)];
    if (hashedObj.hasOwnProperty(key)) {
      delete hashedObj[key];
    }
    if (!Object.keys(hashedObj).length) {
      delete this.collection[hash(key)];
    }
  }

lookup 方法接收一个 key 为参数并返回对应的 value 值,如果 key 值不存在就返回 null。

this.lookup = function (key) {
    var theHash = hash(key);
    if (this.collection.hasOwnProperty(theHash)) {
      return this.collection[theHash][key];
    }
    return null
  }

希望各位小伙伴自己实现一下。
在这里插入图片描述

当然有的人会说,就这。。。。
在这里插入图片描述

确实,笔者的文章都很普通。不是那种特别高深的文章,也没啥干货可以分享。只不过是把自己学习过程中的一点收货分享出来。
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值