成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

基于數組或鏈表實現Map

開發 后端
本篇主要是通過數組和鏈表兩種方式實現,之后提供二叉樹,紅黑樹,散列表的版本實現。通過自己手寫各個版本的Map實現,掌握每種數據結構的優缺點,可以在實際的工作中根據需要選擇適合的Map。

[[388024]]

本文轉載自微信公眾號「貝塔學JAVA」,作者Silently9527。轉載本文請聯系貝塔學JAVA公眾號。

前言

JAVA中的Map主要就是將一個鍵和一個值聯系起來。雖然JAVA中已經提供了很多Map的實現,為了學習并掌握常用的數據結構,從本篇開始我將自己實現Map的功能,本篇主要是通過數組和鏈表兩種方式實現,之后提供二叉樹,紅黑樹,散列表的版本實現。通過自己手寫各個版本的Map實現,掌握每種數據結構的優缺點,可以在實際的工作中根據需要選擇適合的Map。

Map API的定義

在開始之前,我們需要先定義出Map的接口定義,后續的版本都會基于此接口實現

  1. public interface Map<K, V> { 
  2.     void put(K key, V value); 
  3.  
  4.     V get(K key); 
  5.  
  6.     void delete(K key); 
  7.      
  8.     int size(); 
  9.  
  10.     Iterable<K> keys(); 
  11.  
  12.     default boolean contains(K key) { 
  13.         return get(key) != null
  14.     } 
  15.  
  16.     default boolean isEmpty() { 
  17.         return size() == 0; 
  18.     } 

這個接口是最簡單的一個Map定義,相信這些方法對于java程序員來說不會陌生;

基于鏈表實現Map

基于鏈表實現首先我們需要定義一個Node節點,表示我們需要存儲的key、vlaue

  1. class Node { 
  2.     K key
  3.     V value; 
  4.     Node next
  5.  
  6.     public Node(K key, V value, Node next) { 
  7.         this.key = key
  8.         this.value = value; 
  9.         this.next = next
  10.     } 
  11.  

get方法的實現思路是遍歷鏈表,然后比較每個Node中的key是否相等,如果相等就返回value,否則返回null

  1. @Override 
  2. public V get(K key) { 
  3.     return searchNode(key).map(node -> node.value).orElse(null); 
  4.  
  5. public Optional<Node> searchNode(K key) { 
  6.     for (Node node = root; node != null; node = node.next) { 
  7.         if (node.key.equals(key)) { 
  8.             return Optional.of(node); 
  9.         } 
  10.     } 
  11.     return Optional.empty(); 

put方法的實現思路也是遍歷鏈表,然后比較每個Node的key值是否相等,如果相等那么覆蓋掉value,如果未查找到有key相等的node,那么就新建一個Node放到鏈表的開頭

  1. @Override 
  2. public void put(K key, V value) { 
  3.     Optional<Node> optionalNode = searchNode(key); 
  4.  
  5.     if (optionalNode.isPresent()) { 
  6.         optionalNode.get().value = value; 
  7.         return
  8.     } 
  9.     this.root = new Node(key, value, root); 

delete方法實現同樣也需要遍歷鏈表,因為我們的是單向鏈表,刪除某個節點有兩種思路,第一種,在遍歷鏈表的時候記錄下當前節點的上一個節點,把上一個節點的next指向當前節點next;第二種,當遍歷到需要刪除的節點時,把需要刪除節點的next的key、value完全復制到需要刪除的節點,把next指針指向next.next,比如:first - > A -> B -> C -> D -> E -> F -> G -> NULL,要刪除 C 節點,就把D節點完全復制到c中,然后C -> E,變相刪除了C

  1. @Override 
  2. public void delete(K key) { 
  3. // 第一種實現: 
  4. //        for (Node node = first, preNode = null; node != null; preNode = node, node = node.next) { 
  5. //            if (node.key.equals(key)) { 
  6. //                if (Objects.isNull(preNode)) { 
  7. //                    first = first.next
  8. //                } else { 
  9. //                    preNode.next = node.next
  10. //                } 
  11. //            } 
  12. //        } 
  13.  
  14. // 第二中實現: 
  15.     for (Node node = first; node != null; node = node.next) { 
  16.         if (node.key.equals(key)) { 
  17.             Node next = node.next
  18.             node.key = next.key
  19.             node.value =next.value; 
  20.             node.next = next.next
  21.         } 
  22.     } 

分析上面基于鏈表實現的map,每次的put、get、delete都需要遍歷整個鏈表,非常的低效,無法處理大量的數據,時間復雜度為O(N)

基于數組實現Map

基于鏈表的實現非常低效,因為每次操作都需要遍歷鏈表,假如我們的數據是有序的,那么查找的時候我們可以使用二分查找法,那么get方法會加快很多

為了體現出我們的Map是有序的,我們需要重新定義一個有序的Map

  1. public interface SortedMap<K extends Comparable<K>, V> extends Map<K, V> { 
  2.     int rank(K key); 

該定義要求key必須實現接口Comparable,rank方法如果key值存在就返回對應在數組中的下標,如果不存在就返回小于key鍵的數量

  • 在基于數組的實現中,我們會定義兩個數組變量分部存放keys、values;
  • rank方法的實現:由于我們整個數組都是有序的,我們可以二分查找法(可以查看《老哥是時候來復習下數據結構與算法了》),如果存在就返回所在數組的下表,如果不存在就返回0
  1. @Override 
  2. public int rank(K key) { 
  3.     int lo = 0, hi = size - 1; 
  4.     while (lo <= hi) { 
  5.         int mid = (hi - lo) / 2 + lo; 
  6.         int compare = key.compareTo(keys[mid]); 
  7.         if (compare > 0) { 
  8.             lo = mid + 1; 
  9.         } else if (compare < 0) { 
  10.             hi = mid - 1; 
  11.         } else { 
  12.             return mid; 
  13.         } 
  14.     } 
  15.     return lo; 

get方法實現:基于rank方法,判斷返回的keys[index]與key進行比較,如果相等返回values[index],不相等就返回null

  1. @Override 
  2. public V get(K key) { 
  3.     int index = this.rank(key); 
  4.     if (index < size && key.compareTo(keys[index]) == 0) { 
  5.         return values[index]; 
  6.     } 
  7.     return null

put方法實現:基于rank方法,判斷返回的keys[index]與key進行比較,如果相等直接修改values[index]的值,如果不相等表示不存在該key,需要插入并且移動數組

  1. @Override 
  2. public void put(K key, V value) { 
  3.     int index = this.rank(key); 
  4.     if (index < size && key.compareTo(keys[index]) == 0) { 
  5.         values[index] = value; 
  6.         return
  7.     } 
  8.  
  9.     for (int j = size; j > index; j--) { 
  10.         this.keys[j] = this.keys[j--]; 
  11.         this.values[j] = this.values[j--]; 
  12.     } 
  13.     keys[index] = key
  14.     values[index] = value; 
  15.     size++; 

delete方法實現:通過rank方法判斷該key是否存在,如果不存在就直接返回,如果存在需要移動數組

  1. @Override 
  2. public void delete(K key) { 
  3.     int index = this.rank(key); 
  4.     if (Objects.isNull(keys[index]) || key.compareTo(keys[index]) != 0) { 
  5.         return
  6.     } 
  7.     for (int j = index; j < size - 1; j++) { 
  8.         keys[j] = keys[j + 1]; 
  9.         values[j] = values[j + 1]; 
  10.     } 
  11.     keys[size - 1] = null
  12.     values[size - 1] = null
  13.     size--; 

基于數組實現的Map,雖然get方法采用的二分查找法,很快O(logN),但是在處理大量數據的情況下效率依然很低,因為put方法還是太慢;下篇我們將基于二叉樹來實現Map,繼續改進提升效率

 

文中所有源碼已放入到了github倉庫https://github.com/silently9527/JavaCore

 

責任編輯:武曉燕 來源: 貝塔學JAVA
相關推薦

2009-11-25 10:31:35

PHP數組實現單鏈表

2023-12-28 10:39:57

數組節點數據結構

2023-12-22 08:56:01

Java編程語言鏈表

2021-04-13 08:12:33

拉鏈式Map探測式

2023-03-01 07:37:10

數組鏈表性能

2020-02-07 11:07:53

數組鏈表單鏈表

2025-06-04 08:40:00

Go語言鏈表

2022-05-07 09:47:07

Babylon.js微軟元宇宙

2020-12-22 14:11:45

JS forEach()map()

2022-04-20 11:14:55

Python列表數組

2021-11-02 09:05:25

Redis

2022-06-16 07:50:35

數據結構鏈表

2022-03-10 17:02:51

Rust單鏈表數據結構

2019-08-14 10:20:32

算法數組鏈表

2022-09-08 09:42:26

JavaScripMapObject

2023-11-23 06:50:08

括號

2023-10-10 08:39:25

Java 7Java 8

2023-12-22 13:58:00

C++鏈表開發

2021-05-07 08:20:52

前端開發技術熱點

2010-02-06 09:46:46

C++單向鏈表
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 欧美精品a∨在线观看不卡 国产精品久久国产精品 | 99精品观看 | 亚洲国产一区二区视频 | 日韩在线一区二区三区 | 亚洲成人精 | 五月天综合网 | 欧美日韩大片 | 99热精品久久 | 欧美日韩高清一区 | 国产精品mv在线观看 | 一区二区三区在线播放 | 在线观看第一区 | 精品久久精品 | 日韩一区在线观看视频 | 一区二区视频 | 久草在线 | 久草热8精品视频在线观看 午夜伦4480yy私人影院 | 亚洲精品美女 | 羞羞色影院 | 久久久久久国产精品 | 午夜资源| 91视频进入 | 伊人超碰 | 久久99精品久久久久久 | 成人免费视频7777777 | 色婷婷国产精品 | 免费黄色片在线观看 | 日韩欧美不卡 | a免费观看 | 午夜影院中文字幕 | 国产麻豆乱码精品一区二区三区 | 天天操综合网站 | 天天插天天狠天天透 | 亚洲精品乱码8久久久久久日本 | 国产精品久久一区二区三区 | 国产精品成人一区二区 | 欧美xxxx网站| 久久大香| 亚洲aⅴ一区二区 | 最新一级毛片 | 中文字幕 亚洲一区 |