日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 综合教程 >内容正文

综合教程

倍道而行 :堆(heap)

發(fā)布時間:2023/12/15 综合教程 43 生活家
生活随笔 收集整理的這篇文章主要介紹了 倍道而行 :堆(heap) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

概念


先來兩個概念(別頭疼):

普通隊列:先進先出,后進后出

優(yōu)先隊列:出隊順序和入隊順序無關;和優(yōu)先級相關。就好比:我們的電腦操作系統(tǒng)會按照各個進程的優(yōu)先級來安排CPU執(zhí)行哪一個進程。

堆(heap)被稱為一種優(yōu)先隊列,但是堆的本質不是隊列。取出順序就是每次取最大的唄。

下圖就是一個堆:

本質就是一個完全二叉樹。完全二叉樹的定義看圖就可得出:父節(jié)點都大于等于子節(jié)點。且是從上大下,從左至右的排序。

堆的實現(xiàn)


看圖:

仔細看每個數(shù)的下標。數(shù)組是從1開始的。父節(jié)點和子節(jié)點的關系也可以很容易得出。

eg:41是28和16的父節(jié)點,下標分別為2、4、5,滿足圖中的公式。

如題:有10個數(shù),請用代碼將之組成一個堆?

算法思想:每次往里面插入一個數(shù),我們只需要比較插入的數(shù)和其父節(jié)點數(shù)的大小就行。

代碼:

k指的是插入的序號。建議大家這樣理解:
假設現(xiàn)在已經(jīng)構建好了有10個數(shù)的堆,我再往里面插入一個數(shù)為102,即第11個數(shù)。那么k=11.然后與其父節(jié)點(k/2=5),即arr[5]進行比較。若大于父節(jié)點就交換位置,并讓k/2=2,繼續(xù)進行下去,至到和根結點進行比較。
void shiftUp(int k,int arr[]){ while (k>1 && arr[k/2]<arr[k]) { swap(arr[k/2], arr[k]); k /=2; } }

取堆里面的數(shù):每次取都是取第一個位置的數(shù),也就是最大的數(shù)。


如題:現(xiàn)在構建好了一個堆,那么我取走第一個數(shù)后,整個堆就需要進行調整,那該如何?

目前思想:(以本遍博客上面的例子為例,讀者可以對照著看)

本題的:k代表開始的位置為1,j為子節(jié)點的位置(eg:指的是62這個根的左右兩個子節(jié)點)

1.取走62,我就讓15代替62的位置。即,用最末尾的數(shù)字放到根節(jié)點上。
2.比較用15和62的兩個左右節(jié)點進行比較,如果大就不做處理,否則交換位置并且,讓k=j.
繼續(xù)走第二步

void shiftDown(int k,int arr[],int count ){
    while (2*k< count) { //確認有左子節(jié)點
        int j = 2*k;
        if (j+1<count && arr[j+1] > arr[j]) { //如果有右節(jié)點
            j+=1; 
        }
        if (arr[k]>arr[j]) { 如果,比較發(fā)現(xiàn)字節(jié)點沒有父節(jié)點大,就退出
            break;
        }
        swap(arr[k], arr[j]);//否則就交換位置
        k = j;//然后讓k=j,繼續(xù)進行比較。
    }
}

結尾:


堆排序算法還是很簡單的。

建立堆,然后一個一個的取出,那么這就是一個從大到小的一個有序的序列。

但行好事,莫問前程。

總結

以上是生活随笔為你收集整理的倍道而行 :堆(heap)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內容還不錯,歡迎將生活随笔推薦給好友。