中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

JDK的TreeMap怎么實現

發布時間:2021-12-31 16:00:30 來源:億速云 閱讀:139 作者:iii 欄目:編程語言

這篇文章主要講解了“JDK的TreeMap怎么實現”,文中的講解內容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“JDK的TreeMap怎么實現”吧!

TreeMap的實現也是利用的紅黑樹,我們來看代碼:

在TreeMap中包含著一個根結點:

  1. private transient Entry<K,V> root = null;

這個Entry代碼如下:

  1. static final class Entry<K,V> implements Map.Entry<K,V> {

  2.         K key;

  3.         V value;

  4.         //指向小兒子

  5.         Entry<K,V> left = null;

  6.         //指向大兒子

  7.         Entry<K,V> right = null;

  8.          //指向父親

  9.         Entry<K,V> parent;

  10.         //顏色默認為黑色

  11.         boolean color = BLACK;


  12.         Entry(K key, V value, Entry<K,V> parent) {

  13.             this.key = key;

  14.             this.value = value;

  15.             this.parent = parent;

  16.         }


  17.         public K getKey() {

  18.             return key;

  19.         }



  20.         public V getValue() {

  21.             return value;

  22.         }



  23.         public V setValue(V value) {

  24.             V oldValue = this.value;

  25.             this.value = value;

  26.             return oldValue;

  27.         }


  28.         public boolean equals(Object o) {

  29.             if (!(o instanceof Map.Entry))

  30.                 return false;

  31.             Map.Entry<?,?> e = (Map.Entry<?,?>)o;


  32.             return valEquals(key,e.getKey()) && valEquals(value,e.getValue());

  33.         }


  34.         public int hashCode() {

  35.             int keyHash = (key==null ? 0 : key.hashCode());

  36.             int valueHash = (value==null ? 0 : value.hashCode());

  37.             return keyHash ^ valueHash;

  38.         }


  39.         public String toString() {

  40.             return key + "=" + value;

  41.         }

  42.     }

廢話不多說,我們來看一下他的插入實現:

  1.  public V put(K key, V value) {

  2.         Entry<K,V> t = root;

  3.         //如果樹是空樹

  4.         if (t == null) {

  5.             //那么樹根節點就是節點

  6.             root = new Entry<K,V>(key, value, null);

  7.             size = 1;

  8.             modCount++;

  9.             return null;

  10.         }

  11.         int cmp;

  12.         Entry<K,V> parent;

  13.         //否則利用提供的比較器進行比較

  14.         Comparator<? super K> cpr = comparator;

  15.         if (cpr != null) {

  16.             do {

  17.                 parent = t; 


  18.                 cmp = cpr.compare(key, t.key);

  19.                 //如果比當前節點小,

  20.                 if (cmp < 0)

  21.                     //往小兒子遞歸

  22.                     t = t.left;

  23.                 else if (cmp > 0)

  24.                     //往大兒子遞歸

  25.                     t = t.right;

  26.                 else

  27.                     //如果已經有這個key,那么修改key,并且什么都可以 不修改了

  28.                     return t.setValue(value);

  29.             } while (t != null); //知道找到葉子節點;

  30.         }

  31.         else {

  32.             if (key == null)

  33.                 throw new NullPointerException();

  34.             //如果沒有提供外部的比較器,那么就利用內置的比較器

  35.             Comparable<? super K> k = (Comparable<? super K>) key;

  36.             do {

  37.                 parent = t;

  38.                 cmp = k.compareTo(t.key);

  39.                 if (cmp < 0)

  40.                     t = t.left;

  41.                 else if (cmp > 0)

  42.                     t = t.right;

  43.                 else

  44.                     return t.setValue(value);

  45.             } while (t != null);

  46.         }

  47.         //生成一個葉子節點,準備進行加入

  48.         Entry<K,V> e = new Entry<K,V>(key, value, parent);

  49.         //利用最后的判斷,將這個節點變成該葉子節點的兒子;

  50.         if (cmp < 0)

  51.             parent.left = e;

  52.         else

  53.             parent.right = e;

  54.         //由于有可能破壞了紅黑樹的規則,現在進行調整;

  55.         fixAfterInsertion(e);

  56.         size++;

  57.         modCount++;

  58.         return null;

  59.     }



  1. private void fixAfterInsertion(Entry<K,V> x) {

  2.         //首先將該新增節點染紅,葉子節點(null)是黑色的;

  3.         x.color = RED;

  4.         //如果他的父親是紅色的,那么沖突開始;

  5.         while (x != null && x != root && x.parent.color == RED) {

  6.             //如果是左子數;

  7.             if (parentOf(x) == leftOf(parentOf(parentOf(x)))) {

  8.                 Entry<K,V> y = rightOf(parentOf(parentOf(x)));

  9.                 //如果其兄弟是紅色的,那么根據上一節的分析,將兩兄弟都變成黑色,其父節點變紅,這樣黑色節點的數目沒有發生變化,而我們距離跟更近一步;

  10.                 if (colorOf(y) == RED) {

  11.                     setColor(parentOf(x), BLACK);

  12.                     setColor(y, BLACK);

  13.                     setColor(parentOf(parentOf(x)), RED);

  14.                     x = parentOf(parentOf(x));

  15.                 } else {

  16.                  //兄弟為黑色


  17.                     if (x == rightOf(parentOf(x))) {

  18.                         x = parentOf(x);

  19.                         rotateLeft(x);

  20.                     }

  21.                     setColor(parentOf(x), BLACK);

  22.                     setColor(parentOf(parentOf(x)), RED);

  23.                     rotateRight(parentOf(parentOf(x)));

  24.                 }

  25.                //如果是右子數,正好與上面相反;

  26.             } else {

  27.                 Entry<K,V> y = leftOf(parentOf(parentOf(x)));

  28.                 if (colorOf(y) == RED) {

  29.                     setColor(parentOf(x), BLACK);

  30.                     setColor(y, BLACK);

  31.                     setColor(parentOf(parentOf(x)), RED);

  32.                     x = parentOf(parentOf(x));

  33.                 } else {

  34.                     if (x == leftOf(parentOf(x))) {

  35.                         x = parentOf(x);

  36.                         rotateRight(x);

  37.                     }

  38.                     setColor(parentOf(x), BLACK);

  39.                     setColor(parentOf(parentOf(x)), RED);

  40.                     rotateLeft(parentOf(parentOf(x)));

  41.                 }

  42.             }

  43.         }

  44.         //沖突會一直追溯到跟,把跟染黑,不違背根節點是黑色的特性,并且使得所有的樹枝的黑色節點因此加1,沖突解決;

  45.         root.color = BLACK;

  46.     }


看完了增加,我們再來看看刪除

  1.   public V remove(Object key) {

  2.         //查找到該節點

  3.         Entry<K,V> p = getEntry(key);

  4.         //不存在則結束

  5.         if (p == null)

  6.             return null;


  7.         V oldValue = p.value;

  8.         //刪除

  9.         deleteEntry(p);

  10.         //返回原值

  11.         return oldValue;

  12.     }

查找該節點:

  1. final Entry<K,V> getEntry(Object key) {

  2.         if (comparator != null)

  3.             //利用外部比較器

  4.             return getEntryUsingComparator(key);

  5.         if (key == null)

  6.             throw new NullPointerException();

  7.         //內置比較器

  8.     Comparable<? super K> k = (Comparable<? super K>) key;

  9.         Entry<K,V> p = root;

  10.         while (p != null) {

  11.             int cmp = k.compareTo(p.key);

  12.             if (cmp < 0)

  13.                 p = p.left;

  14.             else if (cmp > 0)

  15.                 p = p.right;

  16.             else

  17.                 return p;

  18.         }

  19.         return null;

  20.     }

外部比較器查找節點:

  1.     final Entry<K,V> getEntryUsingComparator(Object key) {

  2.     K k = (K) key;

  3.         Comparator<? super K> cpr = comparator;

  4.         if (cpr != null) {

  5.             Entry<K,V> p = root;

  6.             while (p != null) {

  7.                 int cmp = cpr.compare(k, p.key);

  8.                 if (cmp < 0)

  9.                     p = p.left;

  10.                 else if (cmp > 0)

  11.                     p = p.right;

  12.                 else

  13.                     return p;

  14.             }

  15.         }

  16.         return null;

  17.     }

刪除操作:

  1.   private void deleteEntry(Entry<K,V> p) {

  2.         modCount++;

  3.         size--;

  4.         //如果刪除的節點有兩個子節點;

  5.         if (p.left != null && p.right != null) {

  6.             Entry<K,V> s = successor (p);

  7.             p.key = s.key;

  8.             p.value = s.value;

  9.             p = s;

  10.         } 


  11.         //兩個子節點的刪除轉化為了一個子節點的刪除

  12.        //進行一個子節點的刪除操作;

  13.         Entry<K,V> replacement = (p.left != null ? p.left : p.right);


  14.        //如果有一個以上的節點;重新接上樹枝; 

  15.         if (replacement != null) {


  16.             replacement.parent = p.parent;

  17.             if (p.parent == null)

  18.                 root = replacement;

  19.             else if (p == p.parent.left)

  20.                 p.parent.left  = replacement;

  21.             else

  22.                 p.parent.right = replacement;


  23.             p.left = p.right = p.parent = null;

  24.             //如果刪除位置的新節點是黑色的,那么會少一個黑節點,調整

  25.             if (p.color == BLACK)

  26.             //調整新的節點,即刪除節點的子節點;

  27.                 fixAfterDeletion(replacement);

  28.         } else if (p.parent == null) { // return if we are the only node.

  29.             root = null;

  30.         } else {  

  31.             //如果沒有子節點

  32.             //紅色的節點要可以直接刪除,黑色的話,必須要經過調整;

  33.             if (p.color == BLACK)

  34.                 fixAfterDeletion(p);

  35.            //刪除操作;

  36.             if (p.parent != null) {

  37.                 if (p == p.parent.left)

  38.                     p.parent.left = null;

  39.                 else if (p == p.parent.right)

  40.                     p.parent.right = null;

  41.                 p.parent = null;

  42.             }

  43.         }

  44.     }

刪除后的調整:

  1. private void fixAfterDeletion(Entry<K,V> x) {

  2.         // 如果節點是黑色的;那么要經過調整,如果是紅色的,可以直接修改成為黑色的,結束循環;

  3.         while (x != root && colorOf(x) == BLACK)

  4.             // 判斷被刪除節點是左子樹;

  5.             if (x == leftOf(parentOf(x))) {

  6.                 // 獲得兄弟節點;

  7.                 Entry<K,V> sib = rightOf(parentOf(x));

  8.                 //兄弟節點是紅色的


  9.                 if (colorOf(sib) == RED) {

  10.                     setColor(sib, BLACK);

  11.                     setColor(parentOf(x), RED);

  12.                     //開始旋轉

  13.                     rotateLeft(parentOf(x));

  14.                     // 得到旋轉后的新的兄弟節點;這個時候是黑色的

  15.                     sib = rightOf(parentOf(x));

  16.                 }

  17.                 //判斷侄子的顏色;如果兩個都是黑色的


  18.                 if (colorOf(leftOf(sib))  == BLACK &&

  19.                     colorOf(rightOf(sib)) == BLACK) {

  20.                     setColor(sib, RED);

  21.                     x = parentOf(x);

  22.                 } else {

  23.                     // 只有一個是黑色的

  24.                    // 如果是黑色的那個侄子位置不對,那么經過一次轉換;

  25.                     if (colorOf(rightOf(sib)) == BLACK) {

  26.                         setColor(leftOf(sib), BLACK);

  27.                         setColor(sib, RED);

  28.                         rotateRight(sib);

  29.                         sib = rightOf(parentOf(x));

  30.                     }

  31.                     setColor(sib, colorOf(parentOf(x)));

  32.                     setColor(parentOf(x), BLACK);

  33.                     setColor(rightOf(sib), BLACK);

  34.                     rotateLeft(parentOf(x));

  35.                     x = root;

  36.                 }

  37.             } else {

  38.                 Entry<K,V> sib = leftOf(parentOf(x));


  39.                 if (colorOf(sib) == RED) {

  40.                     setColor(sib, BLACK);

  41.                     setColor(parentOf(x), RED);

  42.                     rotateRight(parentOf(x));

  43.                     sib = leftOf(parentOf(x));

  44.                 }


  45.                 if (colorOf(rightOf(sib)) == BLACK &&

  46.                     colorOf(leftOf(sib)) == BLACK) {

  47.                     setColor(sib, RED);

  48.                     x = parentOf(x);

  49.                 } else {

  50.                     if (colorOf(leftOf(sib)) == BLACK) {

  51.                         setColor(rightOf(sib), BLACK);

  52.                         setColor(sib, RED);

  53.                         rotateLeft(sib);

  54.                         sib = leftOf(parentOf(x));

  55.                     }

  56.                     setColor(sib, colorOf(parentOf(x)));

  57.                     setColor(parentOf(x), BLACK);

  58.                     setColor(leftOf(sib), BLACK);

  59.                     rotateRight(parentOf(x));

  60.                     x = root;

  61.                 }

  62.             }

  63.         }

  64.         //如果該節點不是黑色的,或者是根節點,那么把他染黑;

  65.         setColor(x, BLACK);

  66.     }

  1.  static <K,V> TreeMap.Entry<K,V> successor(Entry<K,V> t) {

  2.         //如果為null,則返回

  3.         if (t == null)

  4.             return null;

  5.         //如果大兒子存在,那么沿著這條路下去,找到其這個枝條中最小的節點

  6.         else if (t.right != null) {

  7.             Entry<K,V> p = t.right;

  8.             while (p.left != null)

  9.                 p = p.left;

  10.             return p;

  11.         } else {

  12.         //如果右邊子樹是空的,那么找到其長輩節點中間第一個大于他的

  13.             Entry<K,V> p = t.parent;

  14.             Entry<K,V> ch = t;

  15.             while (p != null && ch == p.right) {

  16.                 ch = p;

  17.                 p = p.parent;

  18.             }

  19.             return p;

  20.         }

  21.     }

我們再來看一下我們在獲取其集合的時候的順序:

  1.    static final class KeySet<E> extends AbstractSet<E> implements NavigableSet<E> {

  2.         private final NavigableMap<E, Object> m;

  3.         KeySet(NavigableMap<E,Object> map) { m = map; }


  4.         public Iterator<E> iterator() {

  5.             if (m instanceof TreeMap)

  6.                 return ((TreeMap<E,Object>)m).keyIterator();

  7.             else

  8.                 return (Iterator<E>)(((TreeMap.NavigableSubMap)m).keyIterator());

  9.         }


  10.         public Iterator<E> descendingIterator() {

  11.             if (m instanceof TreeMap)

  12.                 return ((TreeMap<E,Object>)m).descendingKeyIterator();

  13.             else

  14.                 return (Iterator<E>)(((TreeMap.NavigableSubMap)m).descendingKeyIterator());

  15.         }


  16.         public int size() { return m.size(); }

  17.         public boolean isEmpty() { return m.isEmpty(); }

  18.         public boolean contains(Object o) { return m.containsKey(o); }

  19.         public void clear() { m.clear(); }

  20.         public E lower(E e) { return m.lowerKey(e); }

  21.         public E floor(E e) { return m.floorKey(e); }

  22.         public E ceiling(E e) { return m.ceilingKey(e); }

  23.         public E higher(E e) { return m.higherKey(e); }

  24.         public E first() { return m.firstKey(); }

  25.         public E last() { return m.lastKey(); }

  26.         public Comparator<? super E> comparator() { return m.comparator(); }

  27.         public E pollFirst() {

  28.             Map.Entry<E,Object> e = m.pollFirstEntry();

  29.             return e == nullnull : e.getKey();

  30.         }

  31.         public E pollLast() {

  32.             Map.Entry<E,Object> e = m.pollLastEntry();

  33.             return e == nullnull : e.getKey();

  34.         }

  35.         public boolean remove(Object o) {

  36.             int oldSize = size();

  37.             m.remove(o);

  38.             return size() != oldSize;

  39.         }

  40.         public NavigableSet<E> subSet(E fromElement, boolean fromInclusive,

  41.                                       E toElement,   boolean toInclusive) {

  42.             return new TreeSet<E>(m.subMap(fromElement, fromInclusive,

  43.                                            toElement,   toInclusive));

  44.         }

  45.         public NavigableSet<E> headSet(E toElement, boolean inclusive) {

  46.             return new TreeSet<E>(m.headMap(toElement, inclusive));

  47.         }

  48.         public NavigableSet<E> tailSet(E fromElement, boolean inclusive) {

  49.             return new TreeSet<E>(m.tailMap(fromElement, inclusive));

  50.         }

  51.         public SortedSet<E> subSet(E fromElement, E toElement) {

  52.             return subSet(fromElement, true, toElement, false);

  53.         }

  54.         public SortedSet<E> headSet(E toElement) {

  55.             return headSet(toElement, false);

  56.         }

  57.         public SortedSet<E> tailSet(E fromElement) {

  58.             return tailSet(fromElement, true);

  59.         }

  60.         public NavigableSet<E> descendingSet() {

  61.             return new TreeSet(m.descendingMap());

  62.         }

  63.     }

這個是返回的set,他的查找排序是利用的迭代模式委托給了迭代器,我們看看他的迭代器實現:

  1.  final class KeyIterator extends PrivateEntryIterator<K> {

  2.         KeyIterator(Entry<K,V> first) {

  3.             super(first);

  4.         }

  5.         public K next() {

  6.             return nextEntry().key;

  7.         }

  8.     }

其中獲取下一個nextEntry是:

  1. final Entry<K,V> nextEntry() {

  2.             Entry<K,V> e = next;

  3.             if (e == null)

  4.                 throw new NoSuchElementException();

  5.             if (modCount != expectedModCount)

  6.                 throw new ConcurrentModificationException();

  7.             next = successor(e);

  8.             lastReturned = e;

  9.             return e;

  10.         }

利用的successvor(),在開始的分析中我們知道,successor的查找,是通過了樹的中序遍歷的

感謝各位的閱讀,以上就是“JDK的TreeMap怎么實現”的內容了,經過本文的學習后,相信大家對JDK的TreeMap怎么實現這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關知識點的文章,歡迎關注!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

莫力| 山阳县| 西昌市| 武邑县| 通河县| 望都县| 秭归县| 永新县| 临漳县| 罗城| 景谷| 鹤峰县| 景洪市| 合肥市| 阿克苏市| 文成县| 敦煌市| 博野县| 定南县| 永清县| 兴文县| 蒙城县| 高密市| 治多县| 景东| 平凉市| 云南省| 岳普湖县| 陵水| 常德市| 谷城县| 象山县| 晋城| 张掖市| 博爱县| 滕州市| 延寿县| 庄浪县| 海阳市| 长武县| 南康市|