国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

Java的 Map以及實現(xiàn)一個簡單的紅黑樹

這篇具有很好參考價值的文章主要介紹了Java的 Map以及實現(xiàn)一個簡單的紅黑樹。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

Map是Java中的一種鍵值對(Key-Value)數(shù)據(jù)結構,它提供了高效的鍵值對的存儲和訪問。在Java中,常見的Map實現(xiàn)類有HashMap、LinkedHashMapTreeMap等。這些實現(xiàn)類在底層使用不同的數(shù)據(jù)結構來存儲鍵值對,以提供不同的性能和特性。

讓我們看看官方介紹Map吧(采用機翻)

Map是將鍵映射到值的對象。map不能包含重復的鍵; 每個鍵最多只能映射到一個值。這個接口取代了Dictionary類,Dictionary類是一個完全抽象的類,而不是接口。

Map接口提供了三個集合視圖,它們允許將映射的內容視為一組鍵、一組值或一組鍵-值映射。映射的順序定義為映射集合視圖上的迭代器返回其元素的順序。一些類似實現(xiàn),比如TreeMap類,對它們的順序做出了特定的保證;其他類,如HashMap類,則不需要。

注意:如果使用可變對象作為映射鍵,必須非常小心。如果對象的值以影響相等比較的方式更改,而該對象是映射中的鍵,則不指定映射的行為。這種禁止的一個特殊情況是,不允許map將自身包含為鍵。雖然允許映射將自身包含為一個值,但建議非常小心。

equals和hashCode方法不再在這樣的映射上得到很好的定義。

所有通用的map實現(xiàn)類都應該提供兩個“標準”構造函數(shù):

  1. 創(chuàng)建空映射的void(無參數(shù))構造函數(shù),
  2. 具有單個map類型參數(shù)的構造函數(shù),它創(chuàng)建具有與其參數(shù)相同的鍵值映射的新映射。

實際上,后一種構造函數(shù)允許用戶復制任何映射,生成所需類的等效映射。沒有辦法強制執(zhí)行這個建議(因為接口不能包含構造函數(shù)),但是JDK中的所有通用映射實現(xiàn)都遵循這個建議。該接口中包含的“破壞性”方法,即修改其操作的映射的方法,被指定為在該映射不支持該操作時拋出UnsupportedOperationException。如果是這種情況,如果調用對映射沒有影響,這些方法可能(但不是必需)拋出UnsupportedOperationException。

例如,在不可修改的映射上調用putAll(Map)方法,如果要“疊加”其映射的映射為空,則可能(但不是必需的)拋出異常。一些映射實現(xiàn)對它們可能包含的鍵和值有限制。例如,有些實現(xiàn)禁止空鍵和空值,有些實現(xiàn)對其鍵的類型有限制。嘗試插入不符合條件的鍵或值將引發(fā)未檢查異常,通常為NullPointerExceptionClassCastException。試圖查詢是否存在不符合條件的鍵或值可能會拋出異常,或者簡單地返回false;有些實現(xiàn)將展示前一種行為,有些將展示后一種行為。更一般地說,嘗試對不符合條件的鍵或值進行操作,其完成后不會導致在映射中插入不符合條件的元素,可能會拋出異常,也可能成功,這取決于實現(xiàn)的選擇。這種異常在該接口的規(guī)范中被標記為“可選的”。

Collections Framework接口中的許多方法都是根據(jù)equals方法定義的。例如,containsKey(Object key)方法的規(guī)范說:“當且僅當此映射包含鍵k的映射使得(key==null ?)K ==null: key.equals(K))。”此規(guī)范不應被解釋為暗示調用Map。帶有非空參數(shù)key的containsKey將導致對任何鍵k調用key.equals(k)。實現(xiàn)可以自由地實現(xiàn)優(yōu)化,從而避免equals調用,例如,首先比較兩個鍵的哈希碼。(Object.hashCode()規(guī)范保證兩個哈希碼不相等的對象不能相等。)更一般地說,只要實現(xiàn)者認為合適,各種集合框架接口的實現(xiàn)可以自由地利用底層對象方法的指定行為。一些執(zhí)行遞歸遍歷map的map操作可能會失敗,對于map直接或間接包含自身的自引用實例可能會出現(xiàn)異常。這包括clone()、equals()、hashCode()和toString()方法。實現(xiàn)可以選擇性地處理自引用場景,但是大多數(shù)當前實現(xiàn)都不這樣做。

Map的特點

  • 鍵唯一性:Map中的是唯一的,每個鍵只能對應一個值。
  • 無序性:Map中的鍵值對是無序的,插入順序不會影響鍵值對的存儲和訪問順序。
  • 鍵和值的映射關系:每個鍵都與一個值相關聯(lián),通過鍵可以獲取對應的值。
  • 允許空鍵和空值:Map允許使用null作為鍵和值。
  • 可變性:Map是可變的數(shù)據(jù)結構,可以動態(tài)地添加、修改和刪除鍵值對。

Java的 Map以及實現(xiàn)一個簡單的紅黑樹,# Java集合,java,開發(fā)語言

Map的實現(xiàn)方式

  • HashMap使用哈希表(Hash Table)實現(xiàn),通過哈希函數(shù)將鍵映射到數(shù)組索引,以實現(xiàn)快速的插入、查找和刪除操作。它提供了O(1)的平均時間復雜度。
  • LinkedHashMap在HashMap的基礎上,使用雙向鏈表維護插入順序,以保持鍵值對的迭代順序。
  • TreeMap使用紅黑樹(Red-Black Tree)實現(xiàn),以保持鍵的有序性。它提供了O(log n)的時間復雜度。

Map的缺點

  • 性能開銷:相比于數(shù)組或列表,Map的性能開銷較大。由于需要維護鍵的唯一性和映射關系,以及可能的哈希沖突等,Map的操作通常比較耗時。
  • 內存占用:Map需要維護額外的數(shù)據(jù)結構來存儲鍵值對的映射關系,這會占用一定的內存空間。
  • 無序性:雖然Map提供了鍵值對的存儲和訪問,但是它們是無序的。如果需要有序性,可能需要使用其他數(shù)據(jù)結構。

示例:

將Map對象轉換為List對象
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

public class MapToListExample {
    public static void main(String[] args) {
        // 創(chuàng)建一個Map對象
        Map<String, Integer> map = Map.of("A", 1, "B", 2, "C", 3);

        // 將Map對象轉換為List對象
        List<Map.Entry<String, Integer>> list = new ArrayList<>(map.entrySet());

        // 打印轉換后的List對象
        for (Map.Entry<String, Integer> entry : list) {
            System.out.println(entry.getKey() + " : " + entry.getValue());
        }
    }
}

將HashMap的鍵值對結構轉換為數(shù)組對象結構

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class HashMapToArrayExample {
    public static void main(String[] args) {
        // 創(chuàng)建一個HashMap對象
        Map<String, Integer> hashMap = new HashMap<>();
        hashMap.put("A", 1);
        hashMap.put("B", 2);
        hashMap.put("C", 3);

        // 將HashMap的鍵值對結構轉換為數(shù)組對象結構
        List<MyObject> array = new ArrayList<>();
        for (Map.Entry<String, Integer> entry : hashMap.entrySet()) {
            MyObject obj = new MyObject(entry.getKey(), entry.getValue());
            array.add(obj);
        }

        // 打印轉換后的數(shù)組對象
        for (MyObject obj : array) {
            System.out.println(obj.getKey() + " : " + obj.getValue());
        }
    }
}

class MyObject {
    private String key;
    private Integer value;

    public MyObject(String key, Integer value) {
        this.key = key;
        this.value = value;
    }

    public String getKey() {
        return key;
    }

    public Integer getValue() {
        return value;
    }
}

實現(xiàn)一個簡易版本的紅黑樹
package com.xh.Map;

/**
 * @author HWZ
 * @date 2024年03月07日 11:01
 * @description
 */
public class RedBlackTree<K extends Comparable<K>, V> {
    private static final boolean RED = true;
    private static final boolean BLACK = false;

    private Node root;

    private class Node {
        private K key;
        private V value;
        private Node left, right;
        private boolean color;

        public Node(K key, V value) {
            this.key = key;
            this.value = value;
            this.color = RED;
        }
    }

    /**
     * 向紅黑樹中插入鍵值對
     * @param key 鍵
     * @param value 值
     */
    public void put(K key, V value) {
        root = put(root, key, value);
        root.color = BLACK;
    }

    private Node put(Node node, K key, V value) {
        if (node == null) {
            return new Node(key, value);
        }

        int cmp = key.compareTo(node.key);
        if (cmp < 0) {
            node.left = put(node.left, key, value);
        } else if (cmp > 0) {
            node.right = put(node.right, key, value);
        } else {
            node.value = value;
        }

        if (isRed(node.right) && !isRed(node.left)) {
            node = rotateLeft(node);
        }
        if (isRed(node.left) && isRed(node.left.left)) {
            node = rotateRight(node);
        }
        if (isRed(node.left) && isRed(node.right)) {
            flipColors(node);
        }

        return node;
    }

    /**
     * 刪除紅黑樹中指定鍵的節(jié)點
     * @param key 鍵
     */
    public void delete(K key) {
        if (!contains(key)) {
            return;
        }

        if (!isRed(root.left) && !isRed(root.right)) {
            root.color = RED;
        }

        root = delete(root, key);
        if (root != null) {
            root.color = BLACK;
        }
    }

    private Node delete(Node node, K key) {
        if (key.compareTo(node.key) < 0) {
            if (!isRed(node.left) && !isRed(node.left.left)) {
                node = moveRedLeft(node);
            }
            node.left = delete(node.left, key);
        } else {
            if (isRed(node.left)) {
                node = rotateRight(node);
            }
            if (key.compareTo(node.key) == 0 && (node.right == null)) {
                return null;
            }
            if (!isRed(node.right) && !isRed(node.right.left)) {
                node = moveRedRight(node);
            }
            if (key.compareTo(node.key) == 0) {
                Node min = findMin(node.right);
                node.key = min.key;
                node.value = min.value;
                node.right = deleteMin(node.right);
            } else {
                node.right = delete(node.right, key);
            }
        }
        return balance(node);
    }

    private Node deleteMin(Node node) {
        if (node.left == null) {
            return null;
        }

        if (!isRed(node.left) && !isRed(node.left.left)) {
            node = moveRedLeft(node);
        }

        node.left = deleteMin(node.left);
        return balance(node);
    }

    /**
     * 判斷紅黑樹中是否包含指定鍵
     * @param key 鍵
     * @return 是否包含指定鍵
     */
    public boolean contains(K key) {
        return get(key) != null;
    }

    /**
     * 根據(jù)鍵查找紅黑樹中的值
     * @param key 鍵
     * @return 值
     */
    public V get(K key) {
        Node node = root;
        while (node != null) {
            int cmp = key.compareTo(node.key);
            if (cmp < 0) {
                node = node.left;
            } else if (cmp > 0) {
                node = node.right;
            } else {
                return node.value;
            }
        }
        return null;
    }

    /**
     * 更新紅黑樹中指定鍵的值
     * @param key 鍵
     * @param value 值
     */
    public void update(K key, V value) {
        if (contains(key)) {
            put(key, value);
        }
    }

    private boolean isRed(Node node) {
        if (node == null) {
            return false;
        }
        return node.color == RED;
    }

    private Node rotateLeft(Node node) {
        if (node == null || node.right == null) {
            return node;
        }
        Node x = node.right;
        node.right = x.left;
        x.left = node;
        x.color = node.color;
        node.color = RED;
        return x;
    }

    private Node rotateRight(Node node) {
        Node x = node.left;
        node.left = x.right;
        x.right = node;
        x.color = node.color;
        node.color = RED;
        return x;
    }

    private void flipColors(Node node) {
        node.color = RED;
        node.left.color = BLACK;
        node.right.color = BLACK;
    }

    private Node moveRedLeft(Node node) {
        flipColors(node);
        if (isRed(node.right.left)) {
            node.right = rotateRight(node.right);
            node = rotateLeft(node);
            flipColors(node);
        }
        return node;
    }

    private Node moveRedRight(Node node) {
        flipColors(node);
        if (isRed(node.left.left)) {
            node = rotateRight(node);
            flipColors(node);
        }
        return node;
    }

    private Node balance(Node node) {
        if (isRed(node)) {
            node = rotateLeft(node);
        }
        if (isRed(node.left) && isRed(node.left.left)) {
            node = rotateRight(node);
        }
        if (isRed(node.left) && isRed(node.right)) {
            flipColors(node);
        }
        return node;
    }

    private Node findMin(Node node) {
        while (node.left != null) {
            node = node.left;
        }
        return node;
    }
}

這個簡易版本的紅黑樹實現(xiàn)包括了插入、刪除、查找和修改操作。紅黑樹的節(jié)點使用內部類Node表示,包含了鍵、值、左子節(jié)點、右子節(jié)點和顏色屬性。

插入操作使用遞歸實現(xiàn),并根據(jù)紅黑樹的性質進行旋轉和顏色翻轉來保持樹的平衡性。刪除操作也使用遞歸實現(xiàn),并根據(jù)不同情況進行旋轉和顏色翻轉來保持樹的平衡性。

查找操作根據(jù)鍵的比較逐級向下搜索,直到找到匹配的鍵或搜索到葉子節(jié)點為止。修改操作先判斷是否包含指定的鍵,如果包含則調用插入操作來更新鍵對應的值。

注意,這只是一個簡易版本的紅黑樹實現(xiàn),并沒有考慮到所有的邊界情況和優(yōu)化。在實際應用中,我們更加建議使用Java標準庫中的TreeMap來實現(xiàn)紅黑樹,它提供了更完善和高效的實現(xiàn)。文章來源地址http://www.zghlxwxcb.cn/news/detail-839277.html

上述紅黑樹代碼的測試:
public class RedBlackTreeTest {
    public static void main(String[] args) {
        RedBlackTree<Integer, String> tree = new RedBlackTree<>();

        // 插入操作
        tree.put(5, "Value 5");
        tree.put(2, "Value 2");
        tree.put(8, "Value 8");
        tree.put(1, "Value 1");
        tree.put(4, "Value 4");
        tree.put(7, "Value 7");
        tree.put(9, "Value 9");

        // 查找操作
        System.out.println(tree.get(4)); // 輸出: Value 4
        System.out.println(tree.get(10)); // 輸出: null

        // 修改操作
        tree.update(4, "New Value 4");
        System.out.println(tree.get(4)); // 輸出: New Value 4

        // 刪除操作
         tree.delete(2);
        System.out.println(tree.contains(2)); // 輸出: false
    }
}

到了這里,關于Java的 Map以及實現(xiàn)一個簡單的紅黑樹的文章就介紹完了。如果您還想了解更多內容,請在右上角搜索TOY模板網以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網!

本文來自互聯(lián)網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。如若轉載,請注明出處: 如若內容造成侵權/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經查實,立即刪除!

領支付寶紅包贊助服務器費用

相關文章

  • 劍指XX游戲(六) - 輕松搞定面試中的紅黑樹問題

    原文地址?http://blog.csdn.net/silangquan/article/details/18655795?utm_source=tuicoolutm_medium=referral 連續(xù)兩次面試都問到了紅黑樹,關鍵兩次都沒有答好,這次就完整地來學習整理一下。 沒有學習過紅黑樹的同學請參考: Introduction to Algorithms Chapter 13 Red-Black Trees Chapter 14 Augmenting Data Structure

    2024年02月08日
    瀏覽(18)
  • Linux面試必備的紅黑樹問題,這可能是zui全的一篇了!

    原文網址:https://zhuanlan.zhihu.com/p/471318214 首先上一個紅黑樹知識點結構圖 1.stl中的set底層用的什么數(shù)據(jù)結構? 2.紅黑樹的數(shù)據(jù)結構怎么定義的? 3.紅黑樹有哪些性質? 4.紅黑樹的各種操作的時間復雜度是多少? 5.紅黑樹相比于BST和AVL樹有什么優(yōu)點? 6.紅黑樹相對于哈希表,在

    2024年02月08日
    瀏覽(18)
  • 【C++】 使用紅黑樹模擬實現(xiàn)STL中的map與set

    【C++】 使用紅黑樹模擬實現(xiàn)STL中的map與set

    前面的文章我們學習了紅黑樹,也提到了C++STL中的map和set的底層其實就是用的紅黑樹來實現(xiàn)的(而map和set的使用我們前面也學過了)。 既然紅黑樹我們也學習過了,那這篇文章我們就用紅黑樹來簡單實現(xiàn)一下STL中的map和set,重點是學習它的框架。 上一篇文章我們實現(xiàn)了紅黑

    2024年02月12日
    瀏覽(23)
  • 紅黑樹的了解以及代碼實現(xiàn)

    紅黑樹的了解以及代碼實現(xiàn)

    ????????紅黑樹是在二叉搜索樹的基礎上 添加顏色 , 通過對任何一條路徑的顏色的限制,確保紅黑樹的任何一條路徑不會超過其他路徑的兩倍 ,是一棵近似平衡的樹。 ? ? ? ? 紅黑樹的節(jié)點不是紅色就是黑色,其節(jié)點的排列除了需要按二插搜索樹的規(guī)則來插入之外,還

    2024年02月03日
    瀏覽(21)
  • AVL樹,紅黑樹,紅黑樹封裝map和set

    AVL樹,紅黑樹,紅黑樹封裝map和set

    二叉搜索樹雖可以縮短查找的效率,但如果 數(shù)據(jù)有序或接近有序二叉搜索樹將退化為單支樹 ,查找元素相當于在順序表中搜索元素, 效率低下 。因此,咱們中國的鄰居俄羅斯的數(shù)學家G.M.Adelson-Velskii和E.M.Landis在1962年發(fā)明了一種解決上述問題的方法: 當向二叉搜索樹中插入

    2023年04月25日
    瀏覽(19)
  • Java學數(shù)據(jù)結構(3)——樹Tree & B樹 & 紅黑樹 & Java標準庫中的集合Set與映射Map & 使用多個映射Map的案例

    Java學數(shù)據(jù)結構(3)——樹Tree & B樹 & 紅黑樹 & Java標準庫中的集合Set與映射Map & 使用多個映射Map的案例

    1.B樹,階M,數(shù)據(jù)樹葉上,根的兒子數(shù)在2和M之間,除根外,非樹葉節(jié)點兒子為M/2和M之間; 2.B樹的插入引起分裂,B樹的刪除,引起合并和領養(yǎng); 3.紅黑樹,根是黑的,紅色節(jié)點的兒子必須是黑的,所有路徑的黑色節(jié)點數(shù)相同; 4.紅黑樹的插入,顏色翻轉,單旋轉,插入節(jié)點定

    2024年02月11日
    瀏覽(34)
  • 【C++】紅黑樹 --- map/set 底層

    【C++】紅黑樹 --- map/set 底層

    紅黑樹,是一種二叉搜索樹,但在每個結點上增加一個存儲位表示結點的顏色,可以是 Red 或 Black . 通過對任何一條從根到葉子的路徑上各個結點著色方式的限制,紅黑樹確保沒有一條路徑會比其他路徑長出兩倍,因而是接近平衡的;如下圖: 每個結點不是紅色就是黑色;

    2024年02月04日
    瀏覽(23)
  • C++【紅黑樹封裝map&&set】

    C++【紅黑樹封裝map&&set】

    我們在開始之前,首先要明白一點,前面我們實現(xiàn)模擬實現(xiàn)紅黑樹以及現(xiàn)在的封裝map和set,我們的目的主要學習它庫中的框架及模板設計和復用,不是要原模原樣的去實現(xiàn)。 先看庫中的代碼,取了核心代碼。我們可以看到kv搞出來value_type,就是相關pair,pair里面的key是const,

    2024年02月07日
    瀏覽(29)
  • 紅黑樹封裝set和map(插入部分)

    紅黑樹封裝set和map(插入部分)

    之前我們實現(xiàn)了紅黑樹的插入的部分,本文主要介紹將之前實現(xiàn)的紅黑樹封裝成map和set。我們是以學習的角度來封裝容器,不用非要把庫中容器所有功能都實現(xiàn)出來。我們主要目的是學習庫中代碼設計技巧和模板復用的思想。 我們在實現(xiàn)之前還是和以前一樣去看看庫中是怎么

    2024年02月07日
    瀏覽(14)
  • 【C++】紅黑樹封裝map和set

    【C++】紅黑樹封裝map和set

    我們知道,map和set的底層是紅黑樹,但是我們這里可能有一個疑問,我們知道,set是K模型的容器,而map是KV模型的容器,那么他們?yōu)槭裁茨芡瑯邮褂眉t黑樹呢?我們來看看STL庫中源碼是怎樣實現(xiàn)的 我們可以看到,stll中map和set頭文件分別包含了三個頭文件,其中stl_tree.h是紅黑

    2024年02月15日
    瀏覽(23)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領取紅包,優(yōu)惠每天領

二維碼1

領取紅包

二維碼2

領紅包