堆排序(排升序为啥建大堆,排降序为啥建小堆)
簡介:
??之前對(duì)堆排序認(rèn)識(shí)的不是很透徹,今天回過頭來再把堆排序的知識(shí)整理整理!以及排升序?yàn)槭裁匆ù蠖?#xff0c;排降序要建小堆。
正文:
??首先我們要知道:
??①堆的邏輯是一顆完全二叉樹;
??②它使用的是順序存儲(chǔ)(也就是數(shù)組);
??③它的作用:一般都是用于找最值。
排序也就是對(duì)數(shù)組的元素按照大小規(guī)則進(jìn)行擺放。
堆排序的過程:
1、建堆
2、對(duì)建好的堆進(jìn)行向下調(diào)整。
可能有人會(huì)疑問?堆已經(jīng)建立好了,為什么還要向下調(diào)整?
來看看下面的解釋:
我們先給定一個(gè)數(shù)組arr[ ] = { 7, 6, 3, 5, 4, 1, 2 }; 將其排成一個(gè)大堆。如下圖:
??當(dāng)我們建好堆之后,我們發(fā)現(xiàn)這個(gè)堆層序遍歷下來是一個(gè)降序的。那么要將它變成一個(gè)升序的順序,就要將它逆序。
??也就是交換堆頂和最后一個(gè)元素的位置,然后從堆頂開始向下調(diào)整,每交換一個(gè)位置,就多一個(gè)數(shù)據(jù)已經(jīng)排好升序。
??可能看到這還很迷糊。沒關(guān)系,繼續(xù)看下面的圖。
我們可以看到,排升序的話,使用大堆是非常方便的,我們每次向下調(diào)整都可以得到剩余數(shù)據(jù)的最大值,即堆頂元素。然后放到最后,使用分治的思想,每調(diào)整一次,要排序的數(shù)據(jù)就少一個(gè)。當(dāng)交換到最后一個(gè)結(jié)點(diǎn)時(shí),數(shù)組已經(jīng)排好序了。
因?yàn)槭菑亩秧斶x擇第一個(gè)元素與最后一個(gè)元素交換,所以堆排序?qū)嵸|(zhì)上還是選擇排序。
那么有人會(huì)疑惑為什么不使用小堆排升序呢?
我們?cè)傧胂?#xff1a;首先使用堆排序主要是用堆頂元素,如果使用小堆排升序,此時(shí)堆頂?shù)脑厥亲钚〉?#xff0c;當(dāng)我們?nèi)〕龆秧斣貢r(shí),此時(shí)小根堆的性質(zhì)就變了,那么下次就找不到第二小的元素了,還要重新建堆。所以不能使用小堆排升序。有興趣的可以自己來畫圖走一走。
堆排序的代碼如下:
void Swap(int *a, int *b) {int tmp = *a;*a = *b;*b = tmp; } //建大堆 void AdjustDown(int arr[], int size, int root){int left = 2 * root + 1;int right = 2 * root + 2;int max;//沒有左孩子if (left >= size){return;}//右孩子存在且大于左孩子if (right < size && arr[right] > arr[left]){max = right;}else{max = left;}if (arr[root] >= arr[max]){return;}Swap(arr + root, arr + max);AdjustDown(arr, size, max); } void CreateHeap(int arr[], int size){for (int i = (size - 1 - 1) / 2; i >= 0; i--){AdjustDown(arr, size, i);} } void HeapSort(int arr[], int size){CreateHeap(arr, size);for (int i = 0; i < size; i++){Swap(arr, arr + size - i - 1);AdjustDown(arr, size - i - 1, 0);} }總結(jié)
以上是生活随笔為你收集整理的堆排序(排升序为啥建大堆,排降序为啥建小堆)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 查看linux命名空间的指令,linux
- 下一篇: 运用GoogleSketchUp创作城市