主頁 > 軟體設計 > 從2-3-4樹模型到紅黑樹實作

從2-3-4樹模型到紅黑樹實作

2020-09-14 13:20:36 軟體設計

從2-3-4樹模型到紅黑樹實作

目錄

  • 從2-3-4樹模型到紅黑樹實作
    • 前言
    • 2-3-4樹
      • 查找
      • 插入
      • 樹的生長
      • 洗掉
        • 洗掉最大key
        • 洗掉最小key
        • 洗掉任意key
    • 左傾紅黑樹
      • 查找
      • 插入
      • 洗掉
        • 洗掉最大Key
        • 洗掉最小Key
        • 洗掉任意Key
    • 總結
    • 參考文獻

前言

紅黑樹,是一個高效的二叉查找樹,其定義特性保證了樹的路徑長度在黑色節點上完美平衡,使得其查找效率接近于完美平衡的二叉樹,

但是紅黑樹的實作邏輯很復雜,各種旋轉,顏色變化,直接針對其分析,大多數都是死記硬背各種例子,不太容易有個直觀的理解,實際上,紅黑樹是實作手段,是其他概念模型為了方便在二叉樹上實作進而定義的節點顏色這個資訊,如果從概念模型入手,再一一對應,就容易理解的多了,而紅黑樹能夠對應的模型有2-3樹,2-3-4樹等,下面我們會以2-3-4樹作為概念模型,對紅黑樹進行分析,

2-3-4樹

2-3-4樹是對完美平衡二叉樹的擴展,其定義為:

  • 在一個節點中,可以存在1-3個key
  • 2-節點,擁有1個key和2個子節點,
  • 3-節點,擁有2個key和3個子節點,
  • 4-節點,擁有3個key和4個子節點,
  • 子節點為空的節點稱為葉子節點,
  • 任意從根節點到葉子節點的路徑擁有相同的長度,即路徑上的鏈接數相同,

下圖就是一個2-3-4樹:

查找

2-3-4樹的查找很簡單,類似于二叉樹,步驟如下:

  • 將查找key和節點內的key逐一對比,
  • 如果命中,則回傳節點內key的對應值,
  • 如果節點內的key都不命中,則沿著合適的鏈接到下一節點重復該程序直到找到或者無后續節點,

舉個例子,如果我們要在上面的2-3-4樹中查詢11,其步驟如下:

插入

2-3-4樹的插入,不會發生在中間節點,只會在葉子節點上進行插入,

在葉子節點上新增key,會使得2-節點變為3-節點,3-節點變為4-節點,而原本的4-節點就沒有空間可以插入key了,為了解決這個問題,可以將4-節點中間的key推送給其父節點,剩下的2個key形成2個2-節點,效果如下

通過將4-的葉子節點拆分,產生了新的葉子節點可供key插入,同時將中間key送入父節點,該操作不會破壞樹的平衡性和高度,但如果葉子節點的父節點也是4-節點,這個操作就無法進行了,為了解決這個問題,有兩種思路:

  • 自底向上,從4-葉子節點開始分裂,如果分類后其父節點也是4-節點,繼續向上分裂,直到到達根節點,如果根節點也是4-節點,分裂后樹的高度+1,
  • 自頂向下,從根節點到插入所在的葉子節點路徑上,遇到4-節點就將其分裂,

兩種方法都能解決問題,不過自頂向下不需要遞回,實作起來更簡單,通過這種處理方式,確保了1)最后到達的葉子節點必然是2-或者3-節點,搜索路徑上不存在4-節點,

樹的生長

2-3-4樹是向上生長的,這句話可以從根節點的分裂理解:如果根節點是一個4-節點,當新增key時,根節點會分裂,將中間的key推入父節點,根節點沒有父節點,因此中間的key就會成為新的根節點,如下所示:

整顆樹的生長可以看成是葉子節點不斷的新增key,并且在成為4-節點后被下一次的新增動作分解為2個2-節點,同時將一個key送入父節點,隨著這個程序的不斷進行,不斷有key從葉子節點向根節點匯聚,直到根節點成為4-節點并在下一次新增時被分類,進而讓樹升高1,

洗掉

洗掉是整個操作中最為復雜的部分,因為洗掉可能發生在任意節點上,并且洗掉后可能破壞2-3-4樹的完美平衡,在這里,我們先來處理一些簡單的情況,最后再思考可以推而廣之的策略,

洗掉最大key

在2-3-4樹中,洗掉最大key必然是最右邊的葉子節點上,如果葉子節點是3-節點或者4-節點,只需要將其中最大的key洗掉即可,不會對樹的平衡性造成影響,但如果洗掉的key在2-節點上,情況就變得麻煩,因為洗掉2-節點,導致樹的平衡被破壞,為了避免這個情況的發生,不能讓洗掉發生在2-節點上,

為了讓洗掉不落在2-節點上,可以將2-型別的葉子節點(最終要洗掉的那個),從其兄弟節點“借”一個key進行融合變成3-節點;也可以將父節點的key和兄弟節點的key融合,變成一個4-節點,主要保證變化程序中樹的平衡性不被破壞即可,變換完成之后的節點型別是3-或4-,自然就可以成功洗掉了,變化的可能情況有:

變化的策略是:

  1. 將父節點的key,自身的key,兄弟節點的key的合并后形成一個邏輯節點,
  2. 變化一:新節點為4-節點的情況下,父節點還有key,則新節點替換目標節點;
  3. 變化二:新節點為5-節點的情況下,最小key還給兄弟節點,次小key還給父節點,剩余2個key設定到目標節點,
  4. 變化三:新節點為6-節點的情況下,最小key還給兄弟節點,次小key還給父節點,剩余3個key設定到目標節點,

向下的搜索,最終達到需要洗掉key的葉子節點,葉子節點的兄弟節點無法控制,而如果能保證目標key所在的葉子節點的父節點不是2-節點,就可以安全洗掉key而不會破壞樹的結構,因此,在自頂向下的程序中,非根節點如果為2-節點,則通過變化成為非2-節點,這個轉化,僅僅針對搜索路徑的下一個節點而言,因此可能出現節點1被轉化為非2-節點后,其子節點是2-節點,子節點轉化為非2-節點時將父節點(節點1)恢復成2-節點,轉化的最終目的是為了保證葉子節點的父節點是非2-節點即可,只不過為了達成這個保證,整個轉化行為需要從根節點一直進行下去,因此如果在葉子節點的時候執行轉化可能會導致子樹高度減1,這種變化會影響到全域樹的平衡,就需要回圈向上迭代到根節點,比較復雜,而從根節點開始一路轉化下去,則容易理解和實作,也不會影響樹的平衡,

通過執行這種變化,在葉子節點中,就可以安全洗掉key

洗掉最小key

最小key的洗掉思路和操作方式和洗掉最大key相似,只不過搜索路徑的方向是最左而已,其節點變化策略也是相似的,具體的變化有以下幾種:

變化的策略是:

  1. 將父節點的key,自身的key,兄弟節點的key的合并后形成一個邏輯節點,
  2. 變化一:新節點為4-節點的情況下,父節點還有key,則新節點替換目標節點;
  3. 變化二:新節點為5-節點的情況下,最大key還給兄弟節點,次大key還給父節點,剩余2個key設定到目標節點,
  4. 變化三:新節點為6-節點的情況下,最大key還給兄弟節點,次大key還給父節點,剩余3個key設定到目標節點,

洗掉任意key

洗掉任一key就變得比較麻煩,key可能出現在中間節點上,洗掉的話,樹的結構就被破壞了,這里,我們可以采用一個取巧的思路:如果洗掉的key是樹的中間節點,將該key替換為其中序遍歷的后繼key;該后繼key是洗掉key的節點的右子樹的最小key

key的替換對樹無影響;而將替換key洗掉,則轉換為洗掉對應子樹最小Key的問,洗掉最小Key,需要從根節點自頂向下變化2-節點才能保證葉子節點中key的成功洗掉,因此,洗掉任一Key的具體處理思路可以總結為:

  1. 從根節點開始自頂向下搜索,非根節點如果為2-節點,則通過變化成為非2-節點,
  2. 搜索發現目標key,將其替換為中序搜索后繼key,
  3. 洗掉步驟2節點的右子樹最小key,

左傾紅黑樹

2-3-4樹是一種概念模型,直接按照這個概念模型用代碼實作則比較復雜,主要的復雜有:

  • 維持3種節點型別,
  • 多種節點型別之間需要互相轉換,
  • 在樹中移動需要進行多次比較,如果節點不是2-節點的話,

因此在表現形式上,我們將2-3-4樹換另外一種形式來展現,進行以下變換:

  • 將2-3-4樹用二叉樹的形式表現,
  • 節點之間的鏈接區分為紅色和黑色,紅色鏈接用于將節點鏈接起來視作3-節點和4-節點,

這種轉換的關鍵點在于:

  • 轉換后的二叉樹可以使用二叉樹的搜索方式,
  • 轉換后的二叉樹和2-3-4樹處于一致關系,改變的只是表現形式,

不過由于3-節點兩種表現形式,增大了復雜性,因此對變換要求增加一條:紅色鏈接只能為左連接,通過三個約束后,轉換得到二叉樹我們稱之為左傾斜紅黑樹,其關鍵特性有:

  • 可以使用二叉樹搜索方式,
  • 與2-3-4樹保持一一對應,
  • 紅黑樹是黑色鏈接完美平衡的,也就是從根節點到葉子節點的任意路徑上,黑色鏈接的數量一致,

其對應方式如下:

可以看到,如果將紅色鏈接放平,就和2-3-4樹在展現上一致了,2-3-4樹是完美平衡的,其對應的左傾斜紅黑樹是黑色鏈接完美平衡,因為紅色鏈接是用于3-節點和4-節點的;而黑色鏈接就對應2-3-4樹中的鏈接,

左傾斜紅黑樹的轉換中不允許2種形式:

  • 右傾斜的紅色鏈接,
  • 兩個連續的紅鏈接在一個搜索路徑中(從根到葉子節點的路徑)

形象的說以下幾種不允許:

禁止的情況,減少了需要考慮的情形,為后續的編碼實作降低了難度,對于上述定義的左傾斜紅黑樹,使用資料結構來表達的話,在原本的二叉樹的節點中,增加一個屬性color,用于表示指向該節點的鏈接的顏色,

public class RedBlackTree
{
    private static final boolean RED   = true;
    private static final boolean BLACK = false;

    private       Node root;            // root of the BST
    private       int  heightBLACK;      // black height of tree

    private class Node
    {
        `key`   `key`;                  // `key`
        Value value;              // associated data
        Node  left, right;         // left and right subtrees
        boolean color;            // color of parent link
        private int    N;            // number of nodes in tree rooted here
        private int    height;       // height of tree rooted here

        Node(`key` `key`, Value value)
        {
            this.`key` = `key`;
            this.value = https://www.cnblogs.com/jfire/p/value;
            this.color = RED;
            this.N = 1;
            this.height = 1;
        }
    }
}

查找

紅黑樹的查找和二叉樹的一致,但是會更加快速,因為紅黑樹是黑色平衡的,搜索長度得到了控制,

插入

在介紹插入實作之前,首先要介紹紅黑樹中的兩種旋轉操作:

  • 右旋:將一個左傾斜的紅鏈接轉化為右鏈接,
  • 左旋:將一個右傾斜的紅鏈接轉化為左連接,

這兩個操作的重要性在于其變化是區域的,不影響黑色連接的平衡性,其變化如下:

紅黑樹的插入和二叉樹插入是相同的,只不過新增的鏈接是紅色的,因為紅黑樹的概念模型是2-3-4樹,2-3-4樹新增節點是在葉子節點上,并且新增后必然成為3-節點或者4-節點,所以新增鏈接均為紅色,

在新增完畢后,根據紅鏈接具體情況,進行旋轉處理,以保持左傾斜紅黑樹的要求,可能出現的情況有:

  • 在2-節點上新增key,表現在紅黑樹上,就是一個黑色的節點新增左連接或者右連接
  • 在3-節點上新增key,表現在紅黑樹上,就是被紅鏈接相連的兩個節點上3個可新增連接的地方新增紅鏈接,

2-節點的情況如下所示:

3-節點的情況如下所示:

左旋和右旋的方法如下:

private Node rotateLeft(Node h)//將節點的右紅鏈接轉化為左鏈接,并且回傳原本節點的子樹轉化后新的子樹的根節點
    {
        Node x = h.right;
        h.right = x.left;
        x.left = setN(h);
        x.color = x.left.color;
        x.left.color = RED;
        return setN(x);//該方法用于計算節點x的子樹內的節點數量以及高度
    }

    private Node rotateRight(Node h)//將節點的左紅鏈接轉化為右鏈接,并且回傳原本節點的子樹轉化后新的子樹的根節點
    {
        Node x = h.left;
        h.left = x.right;
        x.right = setN(h);
        x.color = x.right.color;
        x.right.color = RED;
        return setN(x);
    }

在2-3-4樹的節點插入中,為了避免葉子節點是4-節點導致沒有空間插入,所以從根節點到葉子節點的搜索路徑中,采用自頂向下的4-節點分解策略,而在紅黑樹中,對4-節點的分解動作是通過對節點的顏色變化完成的,如下圖所示:

翻轉的程序很簡單,就是將節點,節點的左右孩子節點的顏色都進行調整即可,顏色翻轉的代碼如下

private void colorFlip(Node h)
    {
        h.color = !h.color;
        h.left.color = !h.left.color;
        h.right.color = !h.right.color;
    }

4-節點的分解帶來的效果是將紅色鏈接向上層移動,這個移動可能產生一個紅色的右鏈接,此時需要通過左旋來修正;或者產生2個連續的紅鏈接,此時需要將其右旋,形成一個符合定義的4-節點,

總結來說,插入的程序首先是自頂向下,遇到4-節點就進行分解,直到到達葉子節點插入新的key;由于向下程序的4-節點可能產生右傾斜的紅鏈接,或者連續的2個紅鏈接,因此需要從葉子節點處向上到達根節點,修復產生的這些問題,處理方式主要是:

  • 右傾斜的紅鏈接左旋,
  • 連續的紅鏈接,通過右旋來達到符合定義的4-節點,

按照上述的總結,我們可以將新增節點的方法實作為

private Node insert(Node h, `key` `key`, Value value)//將KV對插入以h節點為根節點的樹,并且回傳插入后該樹的根節點
    {
        if (h == null)//尋找到空白鏈接,回傳新的節點,該節點為紅色鏈接指向的節點,
        {
            return new Node(`key`, value);
        }
        if (isRed(h.left) && isRed(h.right))//自頂向下的程序中,分裂4-節點,
        {
            colorFlip(h);
        }
        if (eq(`key`, h.`key`))
        {
            h.value = https://www.cnblogs.com/jfire/p/value;
        }
        else if (less(`key`, h.`key`))
        {
            h.left = insert(h.left, `key`, value);
        }
        else
        {
            h.right = insert(h.right, `key`, value);
        }
        if (isRed(h.right))//右傾斜的紅色鏈接,進行左旋,
        {
            h = rotateLeft(h);
        }
        if (isRed(h.left) && isRed(h.left.left))//連續的紅色鏈接,右旋變化為符合定義的4-節點
        {
            h = rotateRight(h);
        }
        return setN(h);
    }

洗掉

和概念模型相同的方法,我們首先嘗試實作洗掉最大key和洗掉最小key,之后通過替換key位置來實作洗掉任意Key功能,

洗掉最大Key

和概念模型相同,洗掉要發生在非2-節點上才能保證樹的平衡不被破壞,這就意味著洗掉一定要發生在一個被紅色鏈接相連的節點上,概念模型當中,在自頂向下搜索程序需要保證中間節點不是2-節點來使得葉子節點必然可以轉化為非2-節點進行安全洗掉;反應在紅黑樹中,搜索路徑的下一個節點,必須要被紅色鏈接相連,如果不是的話,則要進行變化,具體的手段包括:

  • 當前節點有左傾斜紅色鏈接時,將其進行右旋,右旋可以從概念模型上理解,可以認為搜索路徑是進行到3-節點或4-節點,并且從小key搜索到大key
  • 搜索路徑的下一節點為2-節點,轉化為非-2節點,這個轉化程序,參考概念模型中的做法,將當前節點的key,右子節點的key,左子節點的key先合并,產生紅鏈接相連的邏輯節點,之后按照概念模型的拆分方式進行拆分,

針對步驟二,我們做下具體的分析,

當前節點不是2-節點,且3-節點的紅色左連接被轉化為右鏈接,因此在下一個節點為2-節點的情況下,當前節點必然是被右傾斜紅鏈接指向,所示初始狀態可能如下:

對于情況一,我們只需要對節點20進行顏色翻轉,就可以讓其后繼節點變為紅色,也就是鏈接變紅,即可,這種轉換對應概念模型中的變化1,

對于情況二,比較復雜,首先我們需要對節點20進行顏色翻轉,此時節點10和20在一行路徑上,對節點20的左連接右旋,右旋之后節點10變為新的根節點,對齊進行顏色翻轉,整個程序如下

這種轉換對應概念模型中的變化2,

情況三和情況二可以采用完全相同的變化步驟,轉換方式對應概念模型中的變化3,如下圖所示:

綜合情況一、二、三,我們可以將變換的代碼撰寫為

private Node moveRedRight(Node h)
    {
        colorFlip(h);//先翻轉
        if (isRed(h.left.left))//此時為情況二或者三
        {
            h = rotateRight(h);
            colorFlip(h);
        }
        return h;
    }

結合紅鏈接右旋和轉換2-節點,我們可以將洗掉最大key的代碼撰寫如下:

public void deleteMax()
    {
        root = deleteMax(root);
        root.color = BLACK;//如果根節點右子節點為2-節點,翻轉root節點會導致其顏色變紅,不符合定義,因此洗掉完成后,將顏色恢復為顏色,
    }
private Node deleteMax(Node h)//洗掉h節點為根節點的子樹中的最大節點,并且回傳洗掉后的子樹的根節點
    {
        if (isRed(h.left))
        {
            h = rotateRight(h);
        }
        if (h.right == null)//沒有右子樹了,洗掉該節點
        {
            return null;
        }
        if (!isRed(h.right) && !isRed(h.right.left))//右子節點為2-節點,進行變化程序,
        {
            h = moveRedRight(h);
        }
        h.right = deleteMax(h.right);
        return fixUp(h);
    }
    private Node fixUp(Node h) //修正可能存在的例外鏈接情況,
    {
        if (isRed(h.right))
        {
            h = rotateLeft(h);
        }
        if (isRed(h.left) && isRed(h.left.left))
        {
            h = rotateRight(h);
        }
        if (isRed(h.left) && isRed(h.right))
        {
            colorFlip(h);
        }
        return setN(h);
    }

這個實作中引入了一個之前未曾提到的方法fixUp,因為在洗掉的程序自頂向下的變換會產生一些不符合定義的鏈接情況:比如右傾斜的紅鏈接,比如連續的紅鏈接,在洗掉完畢后,需要沿著之前的搜索路徑,自底向上,進行例外鏈接修復,

洗掉最小Key

洗掉最小Key的思路和洗掉最大Key的思路非常接近,只不過在于搜索的方向不同,是沿著左子節點一直向下搜索,相比于洗掉最大Key,洗掉最小Key在搜索路徑向下的程序中不需要對紅鏈接方向進行旋轉,當搜索路徑的下一節點存在2-節點時轉化為非2-節點,可能存在的初始情況如下圖:

情況一很簡單,只需要對節點20進行顏色翻轉,該變換對應概念樹中的變化1,

對于情況二,先對節點20進行翻轉,再對節點30的左連接右旋,再對節點20的右鏈接左旋,最后對頂點進行翻轉,流程如下圖所示:

該變換對應概念模型中的變化2,

對于情況三則更復雜一些,其對應概念模型中的變化3,流程如下

和洗掉最大key不同的地方在于情況三無法復用情況2的操作,否則會產生一個右傾斜的紅鏈接,不過即使是右傾斜紅鏈接,仍然是黑色平衡,但是與左傾斜紅黑樹定義不吻合,所以情況三使用了更多的步驟來產生符合定義的紅黑樹,

結合上述程序,我們可以將洗掉最小Key的代碼撰寫如下

public void deleteMin()
    {
        root = deleteMin(root);
        root.color = BLACK;
    }

    private Node deleteMin(Node h)
    {
        if (h.left == null)
        {
            return null;
        }
        if (!isRed(h.left) && !isRed(h.left.left))
        {
            h = moveRedLeft(h);
        }
        h.left = deleteMin(h.left);
        return fixUp(h);
    }
private Node moveRedLeft(Node h)
    {
        colorFlip(h);
        if (isRed(h.right.left))
        {
            if (isRed(h.right.right))
            {
                h.right = rotateRight(h.right);
                h = rotateLeft(h);
                h = rotateLeft(h);
                h.left = rotateRight(h.left);
                colorFlip(h);
            }
            else
            {
                h.right = rotateRight(h.right);
                h = rotateLeft(h);
                colorFlip(h);
            }

        }
        return h;
    }

洗掉任意Key

和概念模型的洗掉操作相似,自頂向下搜索,按照key的比較結果,可能向左右任意方向前進,如果下一步是一個2-節點,則參照洗掉最大最小key中的變化方式進行變化,在確定key所在的節點后,將該key值替換為中序遍歷的后繼節點,繼而洗掉該節點右子樹的最小節點,代碼如下

public void delete(Key key)
    {
        root = delete(root, key);
        root.color = BLACK;
}
 private Node delete(Node h, Key key)
    {
        if (less(key, h.key))
        {
            if (!isRed(h.left) && !isRed(h.left.left))
            {
                h = moveRedLeft(h);
            }
            h.left = delete(h.left, key);
        }
        else
        {
            if (isRed(h.left))
            {
                h = rotateRight(h);
            }
            if (eq(key, h.key) && (h.right == null))
            {
                return null;
            }
            if (!isRed(h.right) && !isRed(h.right.left))
            {
                h = moveRedRight(h);
            }
            if (eq(key, h.key))
            {
                h.value = https://www.cnblogs.com/jfire/p/get(h.right, min(h.right));
                h.key = min(h.right);
                h.right = deleteMin(h.right);
            }
            else
            {
                h.right = delete(h.right, key);
            }
        }
        return fixUp(h);
    }

總結

紅黑樹作為概念樹的實際實作,其代碼很復雜,要求的變化方式也很多,從概念樹的映射來說,2-3樹,2-3-4樹都可以映射到紅黑樹上,而左傾斜紅黑樹,使用遞回方式實作的代碼,無疑是很好理解,代碼量也較少的,而JDK中TreeMap采用概念模型也是2-3-4樹,不過并不限制右傾斜,總體而言,紅黑樹有太多變種,了解其原理最為重要,實作上,能使用即可,深究的話,意義不大,

參考文獻

《Left-Leaning Red-Black Trees》(Princeton University)


文章原創首發于公眾號:林斌說Java,轉載請注明來源,謝謝,
更多高質量原創文章,歡迎掃碼關注

轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/35282.html

標籤:架構設計

上一篇:圖解 Spring:HTTP 請求的處理流程與機制【5】

下一篇:JSP+Servlet 實作:理財產品資訊管理系統

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 面試突擊第一季,第二季,第三季

    第一季必考 https://www.bilibili.com/video/BV1FE411y79Y?from=search&seid=15921726601957489746 第二季分布式 https://www.bilibili.com/video/BV13f4y127ee/?spm_id_fro ......

    uj5u.com 2020-09-10 05:35:24 more
  • 第三單元作業總結

    1.前言 這應該是本學期最后一次寫作業總結了吧。總體來說,對作業的節奏也差不多掌握了,作業做起來的效率也更高了。雖然和之前的作業一樣,作業中都要用到新的知識,但是相比之前,更加懂得了如何利用工具以及資料。雖然之間卡過殼,但總體而言,這幾次作業還算完成的比較好。 2.作業程序總結 相比前兩個單元,此單 ......

    uj5u.com 2020-09-10 05:35:41 more
  • 北航OO(2020)第四單元博客作業暨課程總結博客

    北航OO(2020)第四單元博客作業暨課程總結博客 本單元作業的架構設計 在本單元中,由于UML圖具有比較清晰的樹形結構,因此我對其中需要進行查詢操作的元素進行了包裝,在樹的父節點中存盤所有孩子的參考。考慮到性能問題,我采用了快取機制,一次查詢后盡可能快取已經遍歷過的資訊,以減少遍歷次數。 本單元我 ......

    uj5u.com 2020-09-10 05:35:48 more
  • BUAA_OO_第四單元

    一、UML決議器設計 ? 先看下題目:第四單元實作一個基于JDK 8帶有效性檢查的UML(Unified Modeling Language)類圖,順序圖,狀態圖分析器 MyUmlInteraction,實際上我們要建立一個有向圖模型,UML中的物件(元素)可能與同級元素連接,也可與低級元素相連形成 ......

    uj5u.com 2020-09-10 05:35:54 more
  • 6.1邏輯運算子

    邏輯運算子 1. && 短路與 運算式1 && 運算式2 01.運算式1為true并且運算式2也為true 整體回傳為true 02.運算式1為false,將不會執行運算式2 整體回傳為false 03.只要有一個運算式為false 整體回傳為false 2. || 短路或 運算式1 || 運算式2 ......

    uj5u.com 2020-09-10 05:35:56 more
  • BUAAOO 第四單元 & 課程總結

    1. 第四單元:StarUml檔案決議 本單元采用了圖模型決議UML。 UML檔案可以抽象為圖、子圖、邊的邏輯結構。 在實作中,圖的節點包括類、介面、屬性,子圖包括狀態圖、順序圖等。 采用了三次遍歷UML元素的方法建圖,第一遍遍歷建點,第二、三次遍歷設定屬性、連邊,實作圖物件的初始化。這里借鑒了一些 ......

    uj5u.com 2020-09-10 05:36:06 more
  • 談談我對C# 多型的理解

    面向物件三要素:封裝、繼承、多型。 封裝和繼承,這兩個比較好理解,但要理解多型的話,可就稍微有點難度了。今天,我們就來講講多型的理解。 我們應該經常會看到面試題目:請談談對多型的理解。 其實呢,多型非常簡單,就一句話:呼叫同一種方法產生了不同的結果。 具體實作方式有三種。 一、多載 多載很簡單。 p ......

    uj5u.com 2020-09-10 05:36:09 more
  • Python 資料驅動工具:DDT

    背景 python 的unittest 沒有自帶資料驅動功能。 所以如果使用unittest,同時又想使用資料驅動,那么就可以使用DDT來完成。 DDT是 “Data-Driven Tests”的縮寫。 資料:http://ddt.readthedocs.io/en/latest/ 使用方法 dd. ......

    uj5u.com 2020-09-10 05:36:13 more
  • Python里面的xlrd模塊詳解

    那我就一下面積個問題對xlrd模塊進行學習一下: 1.什么是xlrd模塊? 2.為什么使用xlrd模塊? 3.怎樣使用xlrd模塊? 1.什么是xlrd模塊? ?python操作excel主要用到xlrd和xlwt這兩個庫,即xlrd是讀excel,xlwt是寫excel的庫。 今天就先來說一下xl ......

    uj5u.com 2020-09-10 05:36:28 more
  • 當我們創建HashMap時,底層到底做了什么?

    jdk1.7中的底層實作程序(底層基于陣列+鏈表) 在我們new HashMap()時,底層創建了默認長度為16的一維陣列Entry[ ] table。當我們呼叫map.put(key1,value1)方法向HashMap里添加資料的時候: 首先,呼叫key1所在類的hashCode()計算key1 ......

    uj5u.com 2020-09-10 05:36:38 more
最新发布
  • 【中介者設計模式詳解】C/Java/JS/Go/Python/TS不同語言實作

    * 中介者模式是一種行為型設計模式,它可以用來減少類之間的直接依賴關系,
    * 將物件之間的通信封裝到一個中介者物件中,從而使得各個物件之間的關系更加松散。
    * 在中介者模式中,物件之間不再直接相互互動,而是通過中介者來中轉訊息。 ......

    uj5u.com 2023-04-20 08:20:47 more
  • 露天煤礦現場調研和交流案例分享

    他們集團的資訊化公司及研究院在一個礦區正在做智能礦山的統一平臺的 試點,專案投資大概1億,包括了礦山的各方面的內容,顯示得我們這次交流有點多余。他們2年前開始做智能礦山的規劃,有很多煤礦行業專家的加持,他們的描述是非常完美,但是去年底應該上線的平臺,現在還沒有看到影子。他們確實有很多場景需求,但是被... ......

    uj5u.com 2023-04-20 08:20:25 more
  • 《社區人員管理》實戰案例設計&個人案例分享

    設計是一個讓人夢想成真程序,開始編碼、測驗、除錯之前進行需求分析和架構設計,才能保證關鍵方面都做正確 ......

    uj5u.com 2023-04-20 08:20:17 more
  • 軟體架構生態化-多角色交付的探索實踐

    作為一個技術架構師,不僅僅要緊跟行業技術趨勢,還要結合研發團隊現狀及痛點,探索新的交付方案。在日常中,你是否遇到如下問題 “ 業務需求排期長研發是瓶頸;非研發角色感受不到研發技改提效的變化;引入ISV 團隊又擔心質量和安全,培訓周期長“等等,基于此我們探索了一種新的技術體系及交付方案來解決如上問題。 ......

    uj5u.com 2023-04-20 08:20:10 more
  • 【中介者設計模式詳解】C/Java/JS/Go/Python/TS不同語言實作

    * 中介者模式是一種行為型設計模式,它可以用來減少類之間的直接依賴關系,
    * 將物件之間的通信封裝到一個中介者物件中,從而使得各個物件之間的關系更加松散。
    * 在中介者模式中,物件之間不再直接相互互動,而是通過中介者來中轉訊息。 ......

    uj5u.com 2023-04-20 08:19:44 more
  • 露天煤礦現場調研和交流案例分享

    他們集團的資訊化公司及研究院在一個礦區正在做智能礦山的統一平臺的 試點,專案投資大概1億,包括了礦山的各方面的內容,顯示得我們這次交流有點多余。他們2年前開始做智能礦山的規劃,有很多煤礦行業專家的加持,他們的描述是非常完美,但是去年底應該上線的平臺,現在還沒有看到影子。他們確實有很多場景需求,但是被... ......

    uj5u.com 2023-04-20 08:19:07 more
  • 《社區人員管理》實戰案例設計&個人案例分享

    設計是一個讓人夢想成真程序,開始編碼、測驗、除錯之前進行需求分析和架構設計,才能保證關鍵方面都做正確 ......

    uj5u.com 2023-04-20 08:18:57 more
  • 軟體架構生態化-多角色交付的探索實踐

    作為一個技術架構師,不僅僅要緊跟行業技術趨勢,還要結合研發團隊現狀及痛點,探索新的交付方案。在日常中,你是否遇到如下問題 “ 業務需求排期長研發是瓶頸;非研發角色感受不到研發技改提效的變化;引入ISV 團隊又擔心質量和安全,培訓周期長“等等,基于此我們探索了一種新的技術體系及交付方案來解決如上問題。 ......

    uj5u.com 2023-04-20 08:18:49 more
  • 05單件模式

    #經典的單件模式 public class Singleton { private static Singleton uniqueInstance; //一個靜態變數持有Singleton類的唯一實體。 // 其他有用的實體變數寫在這里 //構造器宣告為私有,只有Singleton可以實體化這個類! ......

    uj5u.com 2023-04-19 08:42:51 more
  • 【架構與設計】常見微服務分層架構的區別和落地實踐

    軟體工程的方方面面都遵循一個最基本的道理:沒有銀彈,架構分層模型更是如此,每一種都有各自優缺點,所以請根據不同的業務場景,并遵循簡單、可演進這兩個重要的架構原則選擇合適的架構分層模型即可。 ......

    uj5u.com 2023-04-19 08:42:41 more