【資料結構】優先隊列和堆

來源:互聯網
上載者:User

標籤:style   blog   color   使用   資料   io   

優先隊列(priority queue)

對於一般的隊列是在隊列的尾部添加資料,在頭部刪除,以便先進先出。

而優先隊列中的每個元素都有一個優先順序,每次將一個元素放入隊列中,而每次出隊時都是將優先順序最大的那個元素出隊,稱為高進先出(largest-in,first-out)。

優先隊列必須實現以下幾個操作

1.入隊(push):將一個元素放入隊列中。

2.出隊(pop):將優先順序最高的元素從隊列中刪除。

要實現上面的操作可以維護一個有序的鏈表。每次插入資料時維護整個鏈表有序,即使用插入法,每次出隊的操作只需要刪除鏈表最前面的元素。

這麼做的話入隊操作的複雜度是O(n),出隊是O(1),綜合複雜度為O(n)。

接下來要介紹的是O(logn) 的資料結構——二元堆積。

給定一棵完全二叉樹,該樹的每個節點的優先順序大於該節點的所有孩子節點的優先順序。易知,根節點將是優先順序最高的節點。

要用二元堆積來實現優先隊列,必須完成的兩個操作:

1.入隊(push):對於一棵空的二元堆積,只需要將入堆的元素加入根節點即可。對於一般情況,我們將該元素直接加入完全二叉樹的一個位置,該位置是指將這個位置加入該完全二叉樹,這個樹仍然是完全二叉樹的那個點。之後將這個元素和他的父節點比較,若優先順序大於該父節點,則與父節點交換位置,再將新插入的這個元素再和它的新父節點比較,直到它沒有父節點或有一個父節點優先順序大於它為止。

2.出隊(pop):要拿出該完全二叉樹的根節點,之後要維護剩下的節點滿足二元堆積的性質。

在講這個操作之前,我們先定義一個新的操作——假設某節點的左右兩棵子樹都滿足堆的性質,要將整個樹也變成一個堆。我們把該操作稱為篩選(sift)。對於篩選演算法我們需要將根節點和兩個子節點比較,若根節點的優先順序最大,則已經調整完成,否則將兩個子節點中較大的那個和根節點進行交換,此時根節點將是最大的元素了,然後跟蹤被交換的那個孩子節點的位置,繼續做如上的調整,直到調整結束。

對於出隊操作,刪除根節點的元素,並將該二元堆積的最後一個元素(所謂最後一個元素是指將該元素從完全二叉樹刪除,該二叉樹仍然是完全二叉樹的那個元素)放到根節點的位置,然後對該樹進行篩選操作。

 

一般的來講,堆可以輕易地用數組實現,假設數組編號為1的元素是根節點,那麼2和3分別是它的左右節點。對於一個數組編號為i(i>=1)的節點,他的左右節點分別為i*2和i*2+1。

要將一個數組中的n個元素(編號從1到n)直接變成堆,可以用以下操作:for(i=n/2;i>=1;i--) sift(以編號為i的節點為根節點)。這是因為超過n/2的那些節點都是葉子節點,滿足堆的性質,其他節點從下往上依次進行sift操作就完成的堆的建立。

 1 #include<stdio.h> 2 /*r[0].fix為堆的長度*/ 3 typedef int elemtype; 4 typedef struct node 5 { 6     elemtype data; 7     int fix; 8 }HeapNode; 9 HeapNode out(HeapNode r[],int s)/*r[s]出堆*/10 {11     int i,j;12     HeapNode item;13     item=r[s];/*資料暫存*/14     r[s]=r[r[0].fix];/*最後一個資料放入要出堆的元素的位置上*/15     r[0].fix--;/*長度減一*/16     sift(r,s,r[0]);17     return item;18 }19 void in(HeapNode r[],HeapNode item)/*入堆*/20 {21     int i;22     for(i=r[0].fix+1;i>1;i/=2)23     {24         if(item.fix</*>*/r[i/2].fix) r[i]=r[i/2];25         else break;26     }27     r[i]=item;28     r[0].fix++;29 }30 void sift(HeapNode r[],int s,int t)/*篩選成小頂堆演算法*/31 {/*r[s...t]中的記錄除r[s]外均滿足堆的特性*/32     int i,j;33     HeapNode item;34     item=r[s];35     i=s;36     j=2*i;37     while(j<=r[0].fix)38     {39         if(j+1<=r[0].fix&&r[j+1].fix</*>*/r[j].fix) j++;40         if(item.fix>/*<*/r[j].fix){r[i]=r[j];i=j;j=2*i;}41         else break;42     }43     r[i]=item;44 }45 /*46 初始堆的建立:47 for(i=n/2;i>=1;--) sift(r,i,n);48 */49 /*堆排序*/50 /*大頂堆完成升序,小頂堆完成降序*/51 void Heat_sort(long r[],int n)52 {53     int i;54     long item;55     for(i=n/2;i>=1;i--) sift(r,i,n);/*初始堆的建立*/56     for(i=n;i>=2;i--)57     {58         item=r[i];59         r[i]=r[1];60         r[1]=item;61         sift(r,1,i-1); /*大頂堆完成升序,小頂堆完成降序*/62     }63 }

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.