《演算法導論》學習總結 第二部分1堆排序

2021-05-26 20:51:37 字數 1500 閱讀 5797

堆排序是個很漂亮的演算法啊,第一部分講到了插入排序,歸併排序,並實現。這裡有2個概念:原地排序(在排序輸入陣列時,只有常數個元素被放到陣列以外的空間中去);穩定排序(就是相等的兩個數,排序前的順序與排序後的麼順序相同)

說到這個,就扯下吧,穩定排序有:氣泡排序、插入排序、歸併排序、基數排序。

不穩定排序有:選擇排序、快速排序、希爾排序(shell)、堆排序。其中,插入排序,歸併排序,堆排序和快速排序都是比較排序(shell看做週期插入)。

這裡還提到的順序統計學(p72)。描述:在乙個由n個數構成的集合上,第i個順序統計是集合中第i小的數。

如圖是乙個堆,首先,引入parent[i]和left[i]以及right[i]分別表示i的父節點和左右子節點。堆排序的核心三步:1)讓a[i]在最大堆中下降,使以i為根的子樹成為大頂堆;2)建堆,將當前數組建為乙個大頂or小頂堆,注意的就是建堆的時候,從length/2到0,由於根都在length/2範圍,且大值影響小值,所以得遞減的減(練習6.3-2);3)進行堆排序。

堆排序的核心,是通過建堆,以大頂堆為例,將最大元素放到根位置,也就是v[0],再通過輸出v0與最後乙個元素的交換,再對剩下元素繼續建堆,不斷得到當前最大值,過程可以看做遞迴。於是可以得到這三個步驟的

實現如下:

void maxheapify(vector&v ,int i ) }

void buildheap(vector&v)

void heapsort(vector&v)

}

關於這個heapsort過程,由於偽**中有陣列a的size-1過程,但對v我們需要儲存所有值並輸出,這裡引入臨時陣列temp,通過temp的pop_back實現size-1,盡可能貼合偽**,將排序結果通過v的clear和push_back重新新增,儲存排序結果。問題只是v是從大到小排序,當然,偽**中陣列從1到length,如果考慮貼近使left=2*i而不是2*i+1的話,可以
v.insert(v.begin(),int_max);
在0的位置插入個值,但是不去使用。不過這樣意義不大。

另外,不要忽略建堆過程中的偽**:heap-size[a]

對於size-1 的另一種解決辦法,是傳參的時候,實現的**如下:

void maxheapify(vector&v ,int i , int size)//這裡size,則是當前大小 }

void buildheap(vector&v)

void heapsort(vector&v)

}

當然,對於第一步的調整過程,我們也可以消除遞迴如下所示:

void maxheapify(vector&v ,int i , int size)

v[i] = temp;

}

上面這個,不用遞迴的,也是嚴蔚敏資料結構的書上的方法。

先總結這些吧,堆排序測試了下,速度僅次於快排,不得不說,還是很給力的。下面是優先順序佇列。

keep going 。。。

演算法導論 第二部分引言

待排資料通常是記錄資料集合的一部分,每個記錄包含乙個關鍵字,也就是排序問題中要用到的值,記錄的剩餘部分由衛星資料組成,通常與關鍵字一同訪問。衛星資料量大時,重排其引用或指標陣列。排序演算法在空間占用上分為原址的和非原址的 演算法執行過程中僅需要常數個空間的話,則成為原址的 演算法最壞情況執行時間 平...

Web API 第二部分

web api 第二部分 元素偏移量 offset element.offsettop element.offsetleft element.offsetwidth 可以得到元素的大小 寬度和高度 是包含padding border width element.offsetheight elemen...

redux 第二部分

redux 的使用方法,為什麼使用 action.js 檔案,進行優化 將其分開,然後我們通過工廠函式的每次返回不同的物件,由於引數是固定的,每次返回的都是事件型別和事件資料,所以我們可以使用乙個函式,通過其返回值來返回乙個物件,讓後傳遞給 action 我們的 reducer 函式有兩個引數,引數...