当使用Hash实现时,无序。
使用Tree实现时,有序。

3.Set and Map (集合与映射)

// 都可以使用链表和树实现,只要设置 Node 中增加key, Value 即可

Set:不允许出现重复元素

  • set实际上是一个接口, 实现了 Collection
  • image.png

主要有以下几个方法:

  1. // 获取元素个数
  2. int size()
  3. // 查看 Set 是否为空
  4. boolean isEmpty()
  5. // 查看 Set 是否包含元素
  6. boolean contains(Object o)
  7. // 添加元素
  8. void add(E e)
  9. // 删除元素
  10. void remove(Object o)

HashSet实现:

public class HashSet extends AbstractSet implements Set, Cloneable, java.io.Serializable

  1. Set<Integer> set = new HashSet<>();// 创建Set,为 AbstractSet<E> 的子类
  2. private transient HashMap<E,Object> map; // 底层由HashMap实现

LinkedList实现:

  1. // 直接调用了 链表自己实现的方法
  2. public class LinkedListSet <E extends Comparable<E>> implements Set<E>{
  3. private LinkedList<E> list;
  4. public LinkedListSet(){
  5. list = null;
  6. }
  7. // 获取元素个数
  8. public int size(){
  9. return list.getSize();
  10. }
  11. // 查看 Set 是否为空
  12. public boolean isEmpty(){
  13. return list.isEmpty();
  14. }
  15. // 查看 Set 是否包含元素
  16. public boolean contains(E value){
  17. return list.contains(value) != null;
  18. }
  19. // 添加元素
  20. public void add(E e){
  21. if(!list.contains(e)){
  22. list.addFirst(e);
  23. }
  24. }
  25. // 删除元素
  26. public void remove(E e){
  27. remove(e);
  28. }
  29. }

BST实现:

  1. // 对于BST实现的 Set
  2. // 由于只有一个val, 所以实际操作和BST 相同
  3. public class BSTSet <E extends Comparable<E>> implements Set<E>{
  4. private BSTSet<E> bstset;
  5. public BSTSet(){
  6. bstset = null;
  7. }
  8. // 获取元素个数
  9. public int size(){
  10. return bstset.getSize();
  11. }
  12. // 查看 Set 是否为空
  13. public boolean isEmpty(){
  14. return bstset.isEmpty();
  15. }
  16. // 查看 Set 是否包含元素
  17. public boolean contains(E value){
  18. return bst.contains(value) != null;
  19. }
  20. // 添加元素
  21. public void add(E e){
  22. if(!bst.contains(e)){
  23. bst.add(e);
  24. }
  25. }
  26. // 删除元素
  27. public void remove(E e){
  28. bst.remove(e);
  29. }
  30. }

image.png

Map(键值对):

Map实际上也是接口:
image.png

  1. Map<K,V>;
  2. // 主要的方法
  3. // 添加元素
  4. void add(K key , V value);
  5. V remove(K key);// 删除 对应 key
  6. boolean contains(K key); // 查看是否存在 key
  7. V get(K key);// 获取 key对应值
  8. void set(K key, V newValue); // 更新值
  9. int getSize();
  10. boolean isEmpty();

LinkedList 实现 Map

  1. // 在 Node 中分别存入 Map, Value
  2. public class LinkedList<K,V> implements Map<K,V>{
  3. private class Node{
  4. public K key;
  5. public V value;
  6. public Node next;
  7. public Node(K key, V value, Node next){
  8. this.key = key;
  9. this.value = value;
  10. this.next = next;
  11. }
  12. // 放入值可为 null, 但是需要有一个 key 对应
  13. public Node(K key){
  14. this(key, null, null);
  15. }
  16. }
  17. private Node dummyHead;
  18. private int size;
  19. public LinkedListMap() {
  20. dummyHead = new Node(null,null,null);
  21. size = 0;
  22. }
  23. @Override
  24. public int getSize(){
  25. return size;
  26. }
  27. @Override
  28. public boolean isEmpty(){
  29. return size == 0;
  30. }
  31. public Node getNode(K key){
  32. Node res = dummyHead.next;
  33. while(res!=null){
  34. if(res.key.equals(key)){
  35. return res;
  36. }
  37. res = res.next;
  38. }
  39. return null;
  40. }
  41. @Override
  42. public void add(K key, V val){
  43. // 如果不存在 key, 直接加到头部(直接查找是否有对应Node)
  44. // 如果存在,改变value
  45. Node res = getNode(key);
  46. if(res == null){
  47. dummyHead.next = new Node(key, value, dummyHead.next);
  48. size++;
  49. }else{
  50. res.value = val;
  51. }
  52. }
  53. @Override
  54. public void set(K key, V val){
  55. Node node = getNode(key);
  56. if(node == null){
  57. throw new IllegalArgumentException("map don't contains key");
  58. }
  59. node.value = val;
  60. }
  61. @Override
  62. public V remove(K key){
  63. Node node = getNode(key);
  64. if(node == null){
  65. throw new IllegalArgumentException("map don't contains key");
  66. }
  67. Node head = dummyhead;
  68. for(int i = 0; i < size; i++){
  69. if(head.next.key.equals(key)){
  70. break;
  71. }
  72. head = head.next;
  73. }
  74. head.next = node.next;
  75. node.next = null;
  76. size--;
  77. return node.value;
  78. }
  79. @Override
  80. public boolean contains(K key){
  81. return getNode(key) != null;
  82. }
  83. @Override
  84. public V get(K key){
  85. Node node = getNode(key);
  86. if(node == null){
  87. throw new IllegalArgumentException("map don't contains key");
  88. }
  89. return node == null ? null : node.value;
  90. }
  91. }

BST(二分搜索树)实现Map

  1. // 根据 key 存在排序
  2. // 二分搜索树,左子节点val < 父节点 val < 右子节点 val
  3. public class BSTMap <K extend Comparable<K>, V> implements Map<K ,V>{
  4. private class Node{
  5. public K key;
  6. public V value;
  7. public Node left, right;
  8. public Node(K key, V value. Node left, Node right){
  9. this.key = key;
  10. this.value = value;
  11. this.left = left;
  12. this.left = right;
  13. }
  14. // 放入值可为 null, 但是需要有一个 key 对应
  15. public Node(K key){
  16. this(key, null, null, null);
  17. }
  18. }
  19. private Node root;
  20. private int size;
  21. public BSTMap(){
  22. root = null;
  23. size = 0;
  24. }
  25. @Override
  26. public int getSize(){
  27. return size;
  28. }
  29. @Override
  30. public boolean isEmpty(){
  31. return size == 0;
  32. }
  33. @Override
  34. public V get(K key){
  35. Node res = getNode(key);
  36. return res == null ? null : res.value;
  37. }
  38. @Override
  39. public boolean contains(K key){
  40. return getNode(key) != null;
  41. }
  42. // 使用递归方式
  43. public Node getNode(K key){
  44. return getNode(root, key);
  45. }
  46. private Node getNode(Node node, K key){
  47. if(node == null){
  48. return null;
  49. }
  50. if(node.key.compareTo(key) < 0){
  51. return getNode(node.left, key);
  52. }else if(node.key.compareTo(key) > 0){
  53. return getNode(node.right, key);
  54. }
  55. return node;
  56. }
  57. @Override
  58. public void add(K key, V value){
  59. Node res = getNode(key);
  60. if(res == null){
  61. root = add(root, key, value);
  62. size++;
  63. }else{
  64. res.value = value;
  65. }
  66. }
  67. private Node add(Node node, K key, V value){
  68. if(node == null){
  69. return new Node(key, value, null, null);
  70. }
  71. if(node.key.compareTo(key) > 0){
  72. node.right = add(node.right, key, value);
  73. }else{
  74. node.left = add(node.left, key, value);
  75. }
  76. return node;
  77. }
  78. @Override
  79. // 二分搜索树,删除某一结点后,采用前缀或者后缀
  80. // 前缀, 把左子树中最大值交换
  81. // 后缀,把右子树中最小值交换
  82. public V remove(K key){
  83. Node res = getNode(key);
  84. if(res == null){
  85. throw new IllegalArgumentException("map don't contains key");
  86. }
  87. root = remove(root, key);
  88. return res.value;
  89. }
  90. // 获取Node下 最大值
  91. // 当仅有root 节点的时候,最大值为 root
  92. public Node findMax(Node node){
  93. // 获取左子树中最右那个Node
  94. Node res = node;
  95. while(res.right != null){
  96. res = res.right;
  97. }
  98. return res;
  99. }
  100. // 删除Node下最大值,即删除最右的子节点
  101. public Node removeMax(Node node){
  102. Node res = node;
  103. while(node.right != null){
  104. node = node.right;
  105. }
  106. node = null;
  107. size--;
  108. return node;
  109. }
  110. // 若节点是否为叶子节点
  111. // 若非叶子节点,这里使用前缀法,获取左子树中最大值,进行交换
  112. private Node remove(Node node, K key){
  113. if(node.key.compare(key) < 0){
  114. node.left = remove(node.left, key);
  115. return node;
  116. }else if(node.key.compareTo(key) > 0){
  117. node.right = remove(node.right, key);
  118. return node;
  119. }else{
  120. // 为叶子节点
  121. if(node.left == null){
  122. Node accessor = node.right;
  123. node.right = null;
  124. size--;
  125. return accessor;
  126. }else if(node.right == null){
  127. Node accessor = node.left;
  128. node.left = null;
  129. size--;
  130. return accessor;
  131. }else{
  132. // 左右子节点均存在
  133. Node accessor = findMax(node);
  134. accessor.right = node.right;
  135. accessor.left = removeMax(node.left);
  136. node.left = null;
  137. node.right = null;
  138. return accessor;
  139. }
  140. }
  141. }
  142. @Override
  143. public void set(K key, V newValue){
  144. if(!contains(key)){
  145. throw new IllegalArgumentException("map don't contains key");
  146. }
  147. Node res = getNode(key);
  148. res.value = newValue;
  149. }
  150. }

image.png