JavaScript数据结构与算法(3)集合

素颜马尾好姑娘i 2022-01-30 07:25 345阅读 0赞

主要参考:
https://www.cnblogs.com/xiaohuochai/p/8176248.html
《学习JavaScript数据结构与算法》

1.集合介绍

一个集合示例:

  1. {1,2,3,4,5}

其实集合set内部是键值对方式:

在这里插入图片描述
集合这种键值对方式和字典很相似,集合是以[值,值]的形式存储元素,字典则是以[键,值]的形式来存储元素。

2.创建集合

声明一些集合可用的方法:
add(value):向集合添加一个新的项。
remove(value):从集合移除一个值。
has(value):如果值在集合中,返回true,否则返回false。
clear():移除集合中的所有项。
size():返回集合所包含元素的数量。与数组的length属性类似。
values():返回一个包含集合中所有值的数组。

代码实现如下:

  1. function Set(){
  2. var items = {};
  3. //has(value)值是否在集合中,而且has方法会被下面调用
  4. this.has = function(value){
  5. return items.hasOwnProperty(value);
  6. }
  7. //add(value)添加值
  8. this.add = function(value){
  9. if(!this.has(value)){
  10. items[value] = value;
  11. return true; //表示执行到此结束,返回true,不然执行下面,返回false
  12. }
  13. return false;
  14. }
  15. //remove(value)
  16. this.remove = function(value){
  17. if(has(value)){
  18. delete items[value]; //delete 操作符用于删除对象{}/数组[]的某个属性;如果没有指向这个属性的引用,那它最终会被释放。
  19. return true;
  20. }
  21. }
  22. //clear(),移除集合中所有值,把一个空对象重新赋值给它
  23. this.clear = function(){
  24. items = {};
  25. }
  26. //size,一种方法是add或remove时length控制,下面是第二种方法
  27. this.size = function(){
  28. return Object.keys(items).length;
  29. }
  30. //sizeLegacy第三种方法,遍历items对象的每一个属性,记录属性的个数并返回这个数字。
  31. this.sizeLegacy = function(){
  32. var count = 0;
  33. for(var prop in items){
  34. if(items.hasOwnProperty(prop)){
  35. ++count;
  36. }
  37. }
  38. return count;
  39. }
  40. //values 返回一个包含集合中所有值的数组,第一种方法,通过Object.keys()返回一个索引数组。
  41. this.values = function(){
  42. let values = [];
  43. let keys = Object.keys(items);
  44. for(let i=0;i<keys.length;i++){
  45. values.push(items[keys[i]]); //因为items是以对象形式,所以是[]形式
  46. }
  47. return values;
  48. }
  49. //values第二种方法,for in遍历可遍历对象,for in返回的是对象的每一个下标,还要记得使用hasOwenProperty()
  50. this.valuesLegacy = function(){
  51. let values1 = [];
  52. for(let key in items){
  53. if(items.hasOwnProperty(key)){
  54. values.push(items[keys])
  55. }
  56. }
  57. return values1;
  58. }
  59. }
  60. //测试Set类
  61. var set = new Set();
  62. set.add(1);
  63. console.log(set.values()); //输出["1"]
  64. console.log(set.has(1)); //输出true
  65. console.log(set.size()); //输出1
  66. set.add(2);
  67. console.log(set.values()); //输出["1", "2"]
  68. console.log(set.has(2)); //true
  69. console.log(set.size()); //2
  70. set.remove(1);
  71. console.log(set.values()); //输出["2"]
  72. set.remove(2);
  73. console.log(set.values()); //输出[]

3.集合操作

对集合可以进行如下操作
1、并集:对于给定的两个集合,返回一个包含两个集合中所有元素的新集合
2、交集:对于给定的两个集合,返回一个包含两个集合中共有元素的新集合
3、差集:对于给定的两个集合,返回一个包含所有存在于第一个集合且不存在于第二个集合的元素的新集合
4、子集:验证一个给定集合是否是另一集合的子集

并集:

  1. this.union = function(otherSet){
  2. //这里面用到了上面声明的new Set()、values()、add()
  3. //新的Set合集
  4. let unionSet = new Set();
  5. let values = this.values(); //this,获取当前示例的values(),即集合的数组形式
  6. for(let i=0;i<values.length;i++){
  7. unionSet.add(values[i]);
  8. }
  9. let values1 = otherSet.values();
  10. for(let i=0;i<values1.length;i++){
  11. unionSet.add(values1[i]);
  12. }
  13. return unionSet;
  14. }

交集:

  1. this.intersection = function(otherSet){
  2. let intersection = new Set();
  3. let values = this.values();
  4. for(let i=0;i<values.length;i++){
  5. if(otherSet.has(values[i])){
  6. intersection.add(values[i]);
  7. }
  8. }
  9. return intersection;
  10. }

差集:

  1. this.intersection = function(otherSet){
  2. let intersectionSet = new Set(); //{1}
  3. let values = this.values();
  4. for (let i=0; i<values.length; i++){ //{2}
  5. if (!otherSet.has(values[i])){ //{3}
  6. intersectionSet.add(values[i]); //{4}
  7. }
  8. }
  9. return intersectionSet;
  10. }

子集:

  1. this.subset = function(otherSet){
  2. if (this.size() > otherSet.size()){ //{1}
  3. return false;
  4. } else {
  5. let values = this.values();
  6. for (let i=0; i<values.length; i++){ //{2}
  7. if (!otherSet.has(values[i])){ //{3}
  8. return false; //{4}
  9. }
  10. }
  11. return true; //{5}
  12. }
  13. };

4.完整代码

  1. function Set() {
  2. let items = {};
  3. this.add = function(value){
  4. if (!this.has(value)){
  5. items[value] = value;
  6. return true;
  7. }
  8. return false;
  9. };
  10. this.delete = function(value){
  11. if (this.has(value)){
  12. delete items[value];
  13. return true;
  14. }
  15. return false;
  16. };
  17. this.has = function(value){
  18. return items.hasOwnProperty(value);
  19. //return value in items;
  20. };
  21. this.clear = function(){
  22. items = {};
  23. };
  24. /**
  25. * Modern browsers function
  26. * IE9+, FF4+, Chrome5+, Opera12+, Safari5+
  27. * @returns {Number}
  28. */
  29. this.size = function(){
  30. return Object.keys(items).length;
  31. };
  32. /**
  33. * cross browser compatibility - legacy browsers
  34. * for modern browsers use size function
  35. * @returns {number}
  36. */
  37. this.sizeLegacy = function(){
  38. let count = 0;
  39. for(let key in items) {
  40. if(items.hasOwnProperty(key))
  41. ++count;
  42. }
  43. return count;
  44. };
  45. /**
  46. * Modern browsers function
  47. * IE9+, FF4+, Chrome5+, Opera12+, Safari5+
  48. * @returns {Array}
  49. */
  50. this.values = function(){
  51. let values = [];
  52. for (let i=0, keys=Object.keys(items); i<keys.length; i++) {
  53. values.push(items[keys[i]]);
  54. }
  55. return values;
  56. };
  57. this.valuesLegacy = function(){
  58. let values = [];
  59. for(let key in items) {
  60. if(items.hasOwnProperty(key)) {
  61. values.push(items[key]);
  62. }
  63. }
  64. return values;
  65. };
  66. this.getItems = function(){
  67. return items;
  68. };
  69. this.union = function(otherSet){
  70. let unionSet = new Set(); //{1}
  71. let values = this.values(); //{2}
  72. for (let i=0; i<values.length; i++){
  73. unionSet.add(values[i]);
  74. }
  75. values = otherSet.values(); //{3}
  76. for (let i=0; i<values.length; i++){
  77. unionSet.add(values[i]);
  78. }
  79. return unionSet;
  80. };
  81. this.intersection = function(otherSet){
  82. let intersectionSet = new Set(); //{1}
  83. let values = this.values();
  84. for (let i=0; i<values.length; i++){ //{2}
  85. if (otherSet.has(values[i])){ //{3}
  86. intersectionSet.add(values[i]); //{4}
  87. }
  88. }
  89. return intersectionSet;
  90. };
  91. this.difference = function(otherSet){
  92. let differenceSet = new Set(); //{1}
  93. let values = this.values();
  94. for (let i=0; i<values.length; i++){ //{2}
  95. if (!otherSet.has(values[i])){ //{3}
  96. differenceSet.add(values[i]); //{4}
  97. }
  98. }
  99. return differenceSet;
  100. };
  101. this.subset = function(otherSet){
  102. if (this.size() > otherSet.size()){ //{1}
  103. return false;
  104. } else {
  105. let values = this.values();
  106. for (let i=0; i<values.length; i++){ //{2}
  107. if (!otherSet.has(values[i])){ //{3}
  108. return false; //{4}
  109. }
  110. }
  111. return true;
  112. }
  113. };
  114. }

ES6版本代码:

  1. let Set2 = (function () {
  2. const items = new WeakMap();
  3. class Set2 {
  4. constructor () {
  5. items.set(this, {});
  6. }
  7. add(value){
  8. if (!this.has(value)){
  9. let items_ = items.get(this);
  10. items_[value] = value;
  11. return true;
  12. }
  13. return false;
  14. }
  15. delete(value){
  16. if (this.has(value)){
  17. let items_ = items.get(this);
  18. delete items_[value];
  19. return true;
  20. }
  21. return false;
  22. }
  23. has(value){
  24. let items_ = items.get(this);
  25. return items_.hasOwnProperty(value);
  26. }
  27. clear(){
  28. items.set(this, {});
  29. }
  30. size(){
  31. let items_ = items.get(this);
  32. return Object.keys(items_).length;
  33. }
  34. values(){
  35. let values = [];
  36. let items_ = items.get(this);
  37. for (let i=0, keys=Object.keys(items_); i<keys.length; i++) {
  38. values.push(items_[keys[i]]);
  39. }
  40. return values;
  41. }
  42. getItems(){
  43. return items.get(this);
  44. }
  45. union(otherSet){
  46. let unionSet = new Set();
  47. let values = this.values();
  48. for (let i=0; i<values.length; i++){
  49. unionSet.add(values[i]);
  50. }
  51. values = otherSet.values();
  52. for (let i=0; i<values.length; i++){
  53. unionSet.add(values[i]);
  54. }
  55. return unionSet;
  56. }
  57. intersection(otherSet){
  58. let intersectionSet = new Set();
  59. let values = this.values();
  60. for (let i=0; i<values.length; i++){
  61. if (otherSet.has(values[i])){
  62. intersectionSet.add(values[i]);
  63. }
  64. }
  65. return intersectionSet;
  66. }
  67. difference(otherSet){
  68. let differenceSet = new Set();
  69. let values = this.values();
  70. for (let i=0; i<values.length; i++){
  71. if (!otherSet.has(values[i])){
  72. differenceSet.add(values[i]);
  73. }
  74. }
  75. return differenceSet;
  76. };
  77. subset(otherSet){
  78. if (this.size() > otherSet.size()){
  79. return false;
  80. } else {
  81. let values = this.values();
  82. for (let i=0; i<values.length; i++){
  83. if (!otherSet.has(values[i])){
  84. return false;
  85. }
  86. }
  87. return true;
  88. }
  89. };
  90. }
  91. return Set2;
  92. })();

5.ES6中集合

ECMAScript 2015新增了Set类。我们可以基于ES6的Set开发我们的Set类

和我们的Set不同,ES6的Set的values方法返回Iterator,而不是值构成的数组。另一个区别是,我们实现的size方法返回set中存储的值的个数,而ES6的Set则有一个size属性:

  1. let set = new Set([1,2,3,2,4,5,6,7])
  2. set.has(1)
  3. true
  4. set.size
  5. 8

在这里插入图片描述

可以用delete方法删除set中的元素:

  1. set.delete(1)
  2. true

clear方法会重置set数据结构,这跟我们实现的功能一样

  1. set.clear()
  2. undefined
  3. set
  4. Set(0) {}

ES6中的集合

  1. let set = new Set();
  2. //--------- Union ----------
  3. let unionAb = new Set();
  4. for (let x of setA) unionAb.add(x);
  5. for (let x of setB) unionAb.add(x);
  6. //--------- Intersection ----------
  7. let intersection = function(setA, setB){
  8. let intersectionSet = new Set();
  9. for (let x of setA){
  10. if (setB.has(x)){
  11. intersectionSet.add(x);
  12. }
  13. }
  14. return intersectionSet;
  15. };
  16. let intersectionAB = intersection(setA, setB);
  17. //alternative - works on FF only
  18. //intersectionAb = new Set([x for (x of setA) if (setB.has(x))]);
  19. //--------- Difference ----------
  20. let difference = function(setA, setB){
  21. let differenceSet = new Set();
  22. for (let x of setA){
  23. if (!setB.has(x)){
  24. differenceSet.add(x);
  25. }
  26. }
  27. return differenceSet;
  28. };
  29. let differenceAB = difference(setA, setB);
  30. //alternative - works on FF only
  31. //differenceAB = new Set([x for (x of setA) if (!setB.has(x))]);

更详细可以参考上面链接和书籍。

发表评论

表情:
评论列表 (有 0 条评论,345人围观)

还没有评论,来说两句吧...

相关阅读

    相关 算法数据结构集合

    重点知识 1. 在各种查找方法中,平均查找长度与结点个数n无关的查找方法是哈希查找。 2. 动态查找表和静态查找表的重要区别在于前者包含有插入和删除运算,而后者不包含这