2018-2019-20172321 《Java軟件結構與數據結構》第八週學習總結

2018-2019-20172321 《Java軟件結構與數據結構》第八週學習總結

教材學習內容總結

第12章 優先隊列與堆

1、概述

    • 堆的前提就是他首先是一個徹底二叉樹,其次就是知足要約束元素之間的關係。(對於堆中的每個結點,該結點都小於或等於(大於或等於)它的左右孩子。)
  • 優先隊列
    • 在前幾周的學習中咱們瞭解了隊列的知識點,最主要的就是FIFO原則,可是優先隊列就與咱們原先學習的隊列相比就多了一個規則,就是優先級高的就算後入對也要比優先級低的元素先出隊,只有在優先級相同的時候纔會遵循FIFO的原則;

2、堆的操做

  • addElement操做
    將給定的元素添加到堆中的恰當位置,維持該堆的徹底性屬性和有序屬性。html

    若是元素不是Comparable類型的,則會拋出異常。這是爲了讓元素可比較,能夠維持堆的有序屬性。java

public void addElement(T obj) {
        if (count == tree.length)
            expandCapacity();

        tree[count] = obj;
        count++;
        modCount++;

        if (count > 1)
            heapifyAdd();
    }
    private void heapifyAdd() {
        T temp;
        int next = count - 1;

        temp = tree[next];

        while ((next != 0) &&
                (((Comparable) temp).compareTo(tree[(next - 1) / 2]) < 0)) {

            tree[next] = tree[(next - 1) / 2];
            next = (next - 1) / 2;
        }

        tree[next] = temp;
    }
  • removeMin操做
    刪除堆的最小元素:刪除堆的最小元素而且返回。node

    最小元素位於根結點,刪除掉根結點,爲了維持樹的徹底性,要找一個元素來替代它,那麼只有一個能替換根的合法元素,且它是存儲在樹中最末一片葉子上的元素。最末的葉子是h層上最右邊的葉子。git

public T removeMin() throws EmptyCollectionException {
        if (isEmpty())
            throw new EmptyCollectionException("ArrayHeap");

        T minElement = tree[0];
        tree[0] = tree[count - 1];
        heapifyRemove();
        count--;
        modCount--;

        return minElement;
    }

    /**
     * Reorders this heap to maintain the ordering property
     * after the minimum element has been removed.
     */
    private void heapifyRemove() {
        T temp;
        int node = 0;
        int left = 1;
        int right = 2;
        int next;

        if ((tree[left] == null) && (tree[right] == null))
            next = count;
        else if (tree[right] == null)
            next = left;
        else if (((Comparable) tree[left]).compareTo(tree[right]) < 0)
            next = left;
        else
            next = right;
        temp = tree[node];

        while ((next < count) &&
                (((Comparable) tree[next]).compareTo(temp) < 0)) {
            tree[node] = tree[next];
            node = next;
            left = 2 * node + 1;
            right = 2 * (node + 1);
            if ((tree[left] == null) && (tree[right] == null))
                next = count;
            else if (tree[right] == null)
                next = left;
            else if (((Comparable) tree[left]).compareTo(tree[right]) < 0)
                next = left;
            else
                next = right;
        }
        tree[node] = temp;
    }
  • findMin操做
    直接的返回根中的元素就能夠
public T findMin() throws EmptyCollectionException {
        if (isEmpty())
            throw new EmptyCollectionException("ArrayHeap");

        return tree[0];
    }·

3、優先級隊列

  • 遵循兩個排序規則:
    • 具備更高優先級的項目在先。
    • 具備相同優先級的項目使用先進先出方法來肯定順序。
  • 雖然最小堆根本就不是一個隊列,可是它卻提供了一個高效的優先級隊列實現。api

    4、用鏈表實現堆

  • addElement操做
  • 達到3個目的:在恰當位置處添加一個新的元素;對堆進行重排序以維持排序屬性;將lastNode指針從新設定爲指向新的最末結點
  • 其使用了兩個私有方法
    • getNextParentAdd:它返回一個指向某結點的引用,該結點爲插入結點的雙親
    • heapifyAdd:完成對堆的任何重排序,從那片新葉子開始向上處理至根處數組

      添加元素對於複雜度(複雜度爲:2*logn + 1 +logn,即o(logn)):數據結構

  • removeMin 操做
  • 達到3個目的:用存儲在最末結點處的元素替換存儲在根處的元素;對堆重排序;返回初始的根元素。
  • 其使用了兩個私有方法
    • getNewLastNode:它返回一個指向某一結點的引用,該結點是新的最末結點
    • heapifyRemove:進行重排序(從根向下)學習

      刪除根元素對於複雜度(複雜度爲:2*logn + logn + 1,即o(logn))this

  • findMin操做
  • 該元素在堆根處,只需返回根處便可.net

    複雜度爲o(1)

    5、用數組實現堆

  • addElement操做:
    • 在恰當位置處添加新結點。
    • 對堆進行重排序以維持其排序屬性。
    • 將count值遞增1。

      時間複雜度爲 1 + log ,爲 O(logn)。

  • removeMin操做
    • 用存儲在最末元素處的元素替換存儲在根處的元素。
    • 對堆進行重排序。
    • 返回初始的根元素,並將count值減1。

      時間複雜度爲 1 + log ,爲 O(logn)。

  • findMin操做
    • 指向索引爲0

      時間複雜度爲O(1)。

      6、使用堆:堆排序

  • a.將無需序列構建成一個堆,根據升序降序需求選擇大頂堆或小頂堆;
  • b.將堆頂元素與末尾元素交換,將最大元素"沉"到數組末端;
  • c.從新調整結構,使其知足堆定義,而後繼續交換堆頂元素與當前末尾元素,反覆執行調整+交換步驟,直到整個序列有序。
  • 例如

教材學習中的問題和解決過程

  • 問題1:對於優先隊列的定義不太理解
  • 問題1解決方案:
    • 書中定義:

      優先隊列是一個服從兩個有序規則的集合。首先,具備更高優先級的項排在前面。其次,具備相同優先級的項按先進先出的規則排列。

  • 我的對於優先隊列定義的理解:
    • 優先隊列,顧名思義,首先它是一個隊列,可是它強調了「優先」二字,因此,已經不能算是通常意義上的隊列了,它的「優先」意指取隊首元素時,有必定的選擇性,即根據元素的屬性選擇某一項值最優的出隊。在生活中,優先隊列的例子挺常見的,好比在排隊乘電梯時,老師優先上電梯,同窗們按照排隊的順序乘梯。
  • 問題2:優先隊列與堆有什麼關係?
  • 問題2解決方案:
    • 優先隊列的實現能夠用多個隊列來實現,具備相同優先級的項保存在一個隊列中。可是,因爲堆的「每一個元素都要大於或小於它的全部孩子」的特性,而且堆排序是「先將一組元素一項一項插入到堆中,而後一次刪除一個」,所以能夠利用堆來實現優先隊列。

代碼調試中的問題和解決過程

  • 問題1:在單步跟蹤LinkedMaxHeap的過程當中,有個add方法:
public void addElement(T obj) {
        HeapNode<T> node = new HeapNode<T>(obj);

        if (root == null)
            root = node;
        else {
            HeapNode<T> nextParent = getNextParentAdd();
            if (nextParent.getLeft() == null)
                nextParent.setLeft(node);
            else
                nextParent.setRight(node);

            node.setParent(nextParent);
        }
        lastNode = node;
        modCount++;

        if (size() > 1)
            heapifyAdd();
    }

其中有段代碼: node.setParent(nextParent); 在add方法中已經明確代表nextParent.setLeft(node);
那設置node結點的父節點是newParent有什麼意義?

  • 問題1解決方案:解決這個問題要結合HeapNode的代碼。在HeapNode的代碼中有個HeapNode的變量parent,在裏面的不少方法裏面,都有用到這個變量,書上也有說:「有到父節點的引用,這樣就能夠沿樹中的路徑移動。」所以setParent方法是在堆中必要的

代碼託管

上週考試錯題總結

  • 當時看書沒認真看,不知道怎麼想的就選錯了

  • 記錯了,隱約記得一個選項見過,結果記混了

  • 看題不認真,沒注意到題寫的左孩子小於

結對及互評

  • 本週結對學習狀況
  • 結對學習內容
    • 認真學習了十二章的內容
    • 討論了堆的添加和刪除等操做
    • 研究了藍墨雲做業

學習進度條

代碼行數(新增/累積) 博客量(新增/累積) 學習時間(新增/累積)
目標 5000行 30篇 400小時
第一週 0/0 1/1 8/8
第二週 671/671 1/2 17/25
第三週 345/1016 1/3 15/40
第四周 405/1421 2/5 23/63
第五週 1202/2623 1/5 20/83
第六週 1741/4364 1/6 20/103
第七週 400/4764 1/7 20/123
第八週 521/5285 2/9 24/147

參考資料

相關文章
相關標籤/搜索