20162320劉先潤大二第9周學習總結

學號20162320 《程序設計與數據結構》第8周學習總結

教材學習內容總結

1、堆

堆是一棵徹底二叉樹,其中每一個元素大於等於其全部子結點的值。準確的說這是最大堆(maxheap)的定義,堆還能夠是最小堆(minheap),即每一個元素都小於等於它的孩子html

堆有三種基本操做node

  • 1.向堆中添加一個新元素
      策略:將元素添加爲新的葉結點,同時保持樹是徹底樹,而後將該元素向根的方向移動,與它的父結點對換,直到其中的元素大小關係知足要求爲止。
  • 2.找到最大元素
  • 3.刪除最大元素
      策略:由堆的特性得知,最大元素在根上,因此刪除最大元素就是要刪除根結點,而後將餘下的兩個分開的子樹從新構造爲堆。git

    利用最後的葉結點來取代根,而後將其向下移動到合適的位置。
    算法

2、堆的排序

 堆排序是先將一組元素一項項地插入到堆中,而後一次刪除一個,由於元素最早從堆中刪除(在最大堆中),從堆中獲得的元素序列將是有序序列,並且是降序的,相似地,一個最小堆可用來獲得升序的排序結果。
 算法思路:每次將堆的堆頂記錄輸出;同時調整剩餘的記錄,使他們從新排成一個堆。重複以上過程。
 1)將初始待排序關鍵字序列(R1,R2....Rn)構建成大頂堆,此堆爲初始的無須區;
  2)將堆頂元素R[1]與最後一個元素R[n]交換,此時獲得新的無序區(R1,R2,......Rn-1)和新的有序區(Rn),且知足R[1,2...n-1]<=R[n];
  3)因爲交換後新的堆頂R[1]可能違反堆的性質,所以須要對當前無序區(R1,R2,......Rn-1)調整爲新堆,而後再次將R[1]與無序區最後一個元素交換,獲得新的無序區(R1,R2....Rn-2)和新的有序區(Rn-1,Rn)。不斷重複此過程直到有序區的元素個數爲n-1,則整個排序過程完成。(轉)api

public int[] heapSort(int[] array){
         array = buildMaxHeap(array); 
         for(int i=array.length-1;i>1;i--){  
             int temp = array[0]; 
             array[0] = array[i];
             array[i] = temp;
             adjustDownToUp(array, 0,i);  
         }
         return array;
     }

代碼實現思路:首先初始建堆,array[0]爲第一趟值最大的元素, 將堆頂元素和堆低元素交換,即獲得當前最大元素正確的排序位置,最後將剩餘的元素整理成堆。數據結構

3、優先隊列

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

優先隊列不是FIFO隊列,它根據優先級排序元素,而不是根據它們進入隊列的次序排序。學習

可用多個隊列來實現優先隊列,具備相同優先級的項保存在一個隊列中。對於這個問題的更好的解決方案是使用堆。若是按優先級進行排序,就能看出優先隊列和堆之間存在的天然關係,但要注意的是,具備相同優先級的項採用先進先出的原則,並無自動應用到堆中。測試


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

  • 問題1: 一個有n個結點的堆的插入和刪除操做,時間複雜度是多少?爲何?
    解答:假設該二叉樹總共有x層,當該二叉樹爲滿二叉樹的時候,插入和刪除耗費的時間是最長的,那麼則有:
    2^x - 1 = n;在最壞的狀況下,咱們插入一個元素是從第一層遍歷到第n層,那麼進行的操做次數是樹的深度,而樹的深度x = log(2)(n+1)(表示以2爲底,以n+1爲真數的對數),忽略常數,那麼咱們就求得插入時的最壞時間複雜度則爲O(logn)級別。
  • 問題2:堆與二叉查找樹的區別是什麼?
    解答:具備n個結點的二叉查找樹和堆都是約束了元素之間關係的二叉樹。
      (1)二叉查找樹的結點大於它的左子結點,並小於等於它的右子結點,而(最大)堆中的結點大於等於它的兩個子結點。
      (2)二叉排序樹的深度取決於給定集合的初始排列順序,在最優狀況的深度爲log n(表示以2爲底的對數),最壞狀況下其深度爲n;而堆的深度是爲堆所對應的徹底二叉樹的深度log n 。
      (3)二叉排序樹是爲了實現動態查找而設計的數據結構,它是面向查找操做的,在二叉排序樹中查找一個結點的平均時間複雜度是O(log n);堆是爲了實現排序而設計的一種數據結構,它不是面向查找操做的,於是在堆中查找一個結點須要進行遍歷,其平均時間複雜度是O(n)。

代碼學習中的問題及解決

  • 問題1:完成做業PP18.1,實現程序設計項目中的getMax()方法
    解答:
    ```public void add (T element) {
    HeapNode node = new HeapNode (element);
    HeapNode newParent = null;
    if (root == null) root = node;
    else {
    newParent = ((HeapNode )root).getParentAdd(last);
    if (newParent.left == null)
    newParent.setLeft(node);
    else
    newParent.setRight(node);
    }
    node.setParent(newParent);
    last = node;
    ((HeapNode )root).heapifyAdd(last);
    }
在LinkedMaxHeap類中已經給出了add的方法,能夠知道add方法中引用HeapNode中排序的方法,將元素與其的左右子結點進行比較,若子結點大於父結點,則交換兩者。因此創建測試用例中添加大小順序不一樣的數入堆中就已經排好序,已知最大堆中根結點是最大元素,因此getMax()能夠直接返回根結點。`return root.getElement();`
- 問題2:完成PP18.5,實現堆排序算法

public static class HeapSort {
private int[] buildMaxHeap(int[] array) {
//從最後一個節點array.length-1的父節點(array.length-1-1)/2開始,直到根節點0,反覆調整堆
for (int i = (array.length - 2) / 2; i >= 0; i--) {
adjustDownToUp(array, i, array.length);
}
return array;
}ui

private void adjustDownToUp(int[] array, int k, int length) {
        int temp = array[k];
        for (int i = 2 * k + 1; i < length - 1; i = 2 * i + 1) {
            if (i < length && array[i] < array[i + 1]) {
                i++;
            }
            if (temp >= array[i]) {
                break;
            } else {
                array[k] = array[i];
                k = i;
            }
        }
        array[k] = temp;
    }

    public int[] heapSort(int[] array) {
        array = buildMaxHeap(array);
        for (int i = array.length - 1; i > 1; i--) {
            int temp = array[0];
            array[0] = array[i];
            array[i] = temp;
            adjustDownToUp(array, 0, i);
        }
        return array;
    }

    public void toString(int[] array) {
        for (int i : array) {
            System.out.print(i + " ");
        }
    }
}
解答:首先初始創建最大堆,array[0]爲第一趟值最大的元素, 將堆頂元素和堆低元素交換,即獲得當前最大元素正確的排序位置,最後將剩餘的元素整理成堆。
- 1)將存放在array[0,...,n-1]中的n個元素建成初始堆;
- 2)將堆頂元素與堆底元素進行交換,則序列的最大值即已放到正確的位置;
- 3)但此時堆被破壞,將堆頂元素向下調整使其繼續保持大根堆的性質,再重複第23步,直到堆中僅剩下一個元素爲止。


---

## [代碼託管](https://git.oschina.net/pdds2017/LXR20162320.git)
![](http://images2017.cnblogs.com/blog/1062815/201711/1062815-20171106205555934-2054422197.png)

(statistics.sh腳本的運行結果截圖)

---





## 上週考試錯題總結
- 錯題1:

Which of the following best describes a balanced tree?
A .A balanced trees has all nodes at exactly the same level.
B .A balanced tree has no nodes at exactly the same level.
C .A balanced tree has half of the nodes at one level and half the nodes at another level.
D .A balanced tree has all of the nodes within one level of each other.
E .none of the above correctly describe a balanced tree.
解答:D,我選的是E,我認爲ABCD四個選項描述平衡樹的概念都不完整或片面。好比說答案A,儘管樹的節點在同一層次上是平衡的,但並非全部的平衡樹都有這個屬性。全部A錯誤。相對其餘選項只有D是正肯定義了平衡樹。 - 錯題2:In a postorder traversal, the root is the last element visited in the tree.
A .true
B .false
```
解答:B,這個題目答案應該是給錯了,由於答案給的是在後序遍歷中根是最後訪問的一個元素,這應該和A選項符合。


結對及互評

點評過的同窗博客和代碼


其餘(感悟、思考等,可選)

You have to fight to reach your dream. You have to sacrifice and work hard for it. 爲了實現夢想,你必須奮鬥;你必須作出犧牲,必須爲之努力。調整心態,繼續前行,將來加油。


學習進度條

代碼行數(新增/累積) 博客量(新增/累積) 學習時間(新增/累積) 重要成長
目標 5000行 30篇 400小時
第一週 188 1/1 25 算法分析
第二週 70/258 1/2 15/40 《構建之法》7-9章
第三週 474/732 1/3 20/60 查找和排序
第四五六週 1313/2045 4/7 12/72 棧和隊列
第七週 890/2935 1/8 14/86
第八週 913/3848 1/9 20/106 二叉查找樹
第九周 890/3738 1/10 13/119
第十週
  • 計劃學習時間: 20+小時
  • 實際學習時間: 25小時

(有空多看看現代軟件工程 課件 軟件工程師能力自我評價表)

參考資料

相關文章
相關標籤/搜索