1. 程式人生 > >優先佇列-堆

優先佇列-堆

優先佇列

  佇列是一個操作受限的線性表,資料只能在一端進入,另一端出來,具有先進先出的性質。有時在佇列中需要處理優先順序的情況,即後面進入的資料需要提前出來,這裡就需要優先佇列。優先佇列是至少能夠提供插入和刪除最小值這兩種操作的資料結構。對應於佇列的操作,插入相當於入隊,刪除最小相當於出隊。
  連結串列,二叉查詢樹,都可以提供插入和刪除最小這兩種操作。對於連結串列的實現,插入需要O(1),刪除最小需要遍歷連結串列,故需要O(N)。對於二叉查詢樹,這兩種操作都需要O(logN);而且隨著不停的刪除最小的操作,二叉查詢樹會變得非常不平衡;同時使用二叉查詢樹有些浪費,因此很多操作根本不需要。一種較好的實現優先佇列的方式是二叉堆(下面簡稱堆)。
  

  堆實質上是滿足如下性質的完全二叉樹:樹中任一非葉結點的關鍵字均不大於(或不小於)其左右孩子(若存在)結點的關鍵字。首先堆是完全二叉樹(只有最下面的兩層結點度能夠小於2,並且最下面一層的結點都集中在該層最左邊的若干位置的二叉樹),其次任意節點的左右孩子(若有)值都不小於其父親,這是小根堆,即最小的永遠在上面。相反的是大根堆,即大的在上面。
  因為完全二叉樹有很好的規律,因此可以只用資料來儲存資料而不需要連結串列。如下圖:
  這裡寫圖片描述
  如圖儲存在陣列中的資料A~J,對於任意位置i,其左兒子在陣列中位置為2i,其右兒子在陣列中位置為2i+1,其父親位置在floor(i/2)。
  
  堆的插入:插入堆,那麼堆中元素將加一,會在最後一個葉子後新增一個葉子,如上圖中的J後面。添加了一個葉子後,需要按照大小比較將這個值放到特定的位置,直到滿足堆條件,這是個上濾過程。
  堆的刪除最小:刪除堆中最小的一個,對於小根堆來說就是刪除根,刪除根後,需要將下面的元素按照大小規則往上移,直到刪除最後一個葉子,這是個下濾過程。
  建堆的時間複雜度為O(N),刪除堆最小值的時間複雜度為O(logN),N為節點數。

定義一個堆結構並實現資料插入和刪除最小值操作:

#define max 20
struct queue
{
  int size;
  int data[max];
};

//insert a data to queue;
void insert(queue &q, int x)
{
  int tmp = q.size;  //store data at the first site data[0]
  q.data[tmp] = x;
  while ((tmp-1)/2>=0)
  {
    if(q.data[tmp] < q.data[(tmp-1)/2])
    {
      q.data[tmp] = q.data[(tmp-1
)/2]; q.data[(tmp-1)/2] = x; tmp = (tmp-1)/2; }else break; // } q.size++; } //delete the minimum data in the queue void deletemin(queue &q) { int tmp = 0; while (tmp*2+2 < q.size) { if(q.data[tmp*2+1]<q.data[tmp*2+2]) { q.data[tmp] = q.data[tmp*2+1]; tmp = tmp*2+1; } else { q.data[tmp] = q.data[tmp*2+2]; tmp = tmp*2+2; } } q.data[tmp] = q.data[q.size-1]; q.data[q.size-1] = 0; q.size--; } int main() { queue q; q.size = 0; //it's necessary insert(q,7);insert(q,5);insert(q,2); insert(q,3);insert(q,1);insert(q,4); deletemin(q); for(int i=0; i<q.size; i++) cout << q.data[i]; return 0; }

STL中的優先佇列:priority_queue

  priority_queue為STL中實現的優先佇列結構,輸入存入佇列會自動按照大根堆的性質儲存。它的模板宣告帶有三個引數:
  priority_queue<Type, Container, Functional> Type 為資料型別,Container 為儲存資料的容器,Functional 為元素比較方式。Container 必須是用陣列實現的容器,比如 vector, deque 但不能用 list。STL裡面預設用的是 vector,比較方式預設用 operator< , 所以如果你把後面倆個引數預設的話,優先佇列就是大頂堆,隊頭元素最大。
  priority_queue<int,vector<int>,greater<int> >q3;//定義小的先出隊

常用的函式:

  push()    //插入一個數;
  pop()     //刪除最小(大)的那個數;
  //front()   //返回隊首元素;
  //back()    //返回隊尾元素;
  top()     //返回隊頂元素,沒有上面兩個,queue才有
  empty()   //佇列是否為空
  size()    //佇列中元素個數

priority_queue定義在標頭檔案queue中,在此檔案中還有一種資料型別queue,即單向佇列,基本操作也是上面的幾個函式,與雙向佇列deque略有差別。
基本定義:queue<int> q;

int main()
{
  queue<int> s;
  priority_queue<int> ss;
  priority_queue<int,vector<int>,greater<int> >q3;
  s.push(1);s.push(2); s.pop();
  ss.push(1);ss.push(4);ss.push(0);ss.pop();
  q3.push(1);q3.push(4);q3.push(0);q3.pop();
  return 0;
}

需要注意的是:優先佇列priority_queue是不支援迭代器的運算的,讀取元素只能在佇列首部讀取(top), queue也是一樣的不支援,因此不能對queue進行排序,只能讀取隊首和隊尾的資料(front,back()),同樣的stack也是一樣不能使用迭代器,只能讀取棧頂的資料。
對於自己定義的資料型別作為佇列引數,用法參考:priority_queue的用法

相關推薦

優先佇列

優先佇列   佇列是一個操作受限的線性表,資料只能在一端進入,另一端出來,具有先進先出的性質。有時在佇列中需要處理優先順序的情況,即後面進入的資料需要提前出來,這裡就需要優先佇列。優先佇列是至少能夠提供插入和刪除最小值這兩種操作的資料結構。對應於佇列的操作,插

優先佇列排序介紹

1 堆的基本概念 堆也叫優先佇列,堆是一種特殊的完全二叉樹資料結構,堆分為兩種,最大堆,最小堆。 最大堆:根節點大於左右兩個子節點的完全二叉樹 最小堆:根節點小於左右兩個子節點的完全二叉樹 堆可以用陣列來儲存,a[i]處存根節點,a[2*i] a[2*i + 1]分別存左子樹的

演算法-優先佇列排序

優先佇列 許多應用程式都需要處理有序的元素,但不一定要求他們全部有序,或是不一定要一次就將他們排序。很多情況下我們會收集一些元素,處理當前鍵值最大的元素,然後再收集更多元素,再處理當前鍵值最大的元素,如此這般。 在這種情況下,一個合適的資料結構應該支援兩種操作:刪除最大元素和插入元素。

八大排序演算法(六)——優先佇列排序

6.1 API 優先佇列是一種抽象資料型別,它表示了一組值和對這些值的操作。優先佇列最重要的操作就是刪除最大元素和插入元素。 6.2 初級實現 6.2.1 陣列實現(無序) 或許實現優先佇列最簡單方法就是基於下壓棧的程式碼。insert()方法的程式碼和棧的完全一樣。要實現刪除最大元素,

(Java資料結構和演算法)---優先佇列排序

堆主要用於實現優先佇列。 利用有序陣列可以實現優先佇列(從小到大或從大到小的陣列),刪除的時間複雜度是O(1),但是插入的時間複雜度是O(N)。用堆實現優先佇列,插入和刪除的時間複雜度都是O(logN)。 簡介 堆是一種完全二叉樹,且每個節點的值都大於等於子節點值(大根堆)。

玩轉資料結構——第七章:優先佇列

內容概要: 什麼是優先佇列? 堆的基礎結構 向堆中新增元素Sift Up 從堆中取出元素和Sift Down Heapify和Replace 基於堆的優先佇列 LeetCode上優先佇列相關的問題 java中的PriorityQueue 和堆相關的更多話題和

資料結構——優先佇列

什麼是優先佇列? 普通佇列:先進先出,後進後出 優先佇列:出隊順序和入隊順序無關;和優先順序相關,如醫院中,病重先安排病床 優先佇列的現例項子: ①cpu任務排程,動態選擇優先順序最高的任務執行 ②王者榮耀中,攻擊鍵優先打敵人,無敵人時候優先打最近的小兵 關於

資料結構——優先佇列

優先佇列: 優先佇列也是一個佇列,他和普通佇列的區別是:普通佇列是先進先出,後進先出的;優先佇列是出隊順序和入隊順序無關,和優先順序相關。(如:醫院看病時,病情最嚴重的那個需要先看病)  實現優先佇列同樣底層也可以選擇多種資料結構, 選擇 普通的線性結構實現:出隊O(1),入隊

《常見演算法和資料結構》優先佇列(3)——排序

堆排序 本系列文章主要介紹常用的演算法和資料結構的知識,記錄的是《Algorithms I/II》課程的內容,採用的是“演算法(第4版)”這本紅寶書作為學習教材的,語言是java。這本書的名

排序演算法(3)—優先佇列排序

本文主要討論基於二叉堆資料結構的優先佇列的實現以及衍生的堆排序 實現優先佇列還可以使用棧,佇列等資料結構,在此略 文章最後附有堆排序完整程式碼 優先佇列 1. 主要解決問題 有時候比不

優先佇列

優先佇列和普通佇列的區別在於,優先佇列(堆)總是先優先處理佇列中最小的元素。 優先佇列(堆)允許至少下列兩種操作:Insert(插入),以及DeleteMin(刪除最小者),他的工作是找出、返回和刪除優先佇列中的最小元素。Insert操作類似於Enqueue(入隊),而DeleteMin則是佇列中Deque

PAT 備考——優先佇列)與排序

一、堆 堆是完全二叉樹型中的一種的資料結構,按照排列順序分為大頂堆和小頂堆。其中大頂堆表示二叉樹中所有根節點比子節點大,小頂堆反之。 因此,以大頂堆為例,堆具有如下兩個性質: 有序性:從根節點到任意子節點的路徑,所經過的節點是有序排列的; 完全性:與完全二叉樹相同,當用陣

優先佇列的一些知識

1.概念 優先佇列:普通的佇列具有先進先出的特性,元素追加在隊尾,如果刪除的話,從隊頭刪除。而在優先佇列中,佇列中的資料被賦予了優先順序。當訪問元素時,優先順序最高的會先被刪除。所以說優先佇列是最高階

第6章 優先佇列

優先佇列 優先佇列資料結構屬於電腦科學中最精緻的一種 6.1 模型 優先佇列允許至少兩種操作:插入和刪除最小者 6.2 一些簡單的實現 優先佇列的插入和刪除最小者的最壞情形時間均為o(logN),但插入操作實際上將花費平均時間,若無刪除操作的干擾,該結構的實現將以線性時間建

基於優先佇列排序

          public class MaxPQ<Key extends Comparable<key>>{               private Key[] pq;               private int N = 0;               pulbi

八、優先佇列排序

優先佇列 一種常見的資料結構,需要支援兩種操作:刪除最大(最小)元素和插入元素。這種資料型別叫做優先佇列。 API MaxPQ()//建立一個優先佇列 MaxPQ(int max)//建立一個最大容量為max的優先佇列 MaxPQ(key

優先佇列 實戰:HDU1242

什麼叫優先佇列呢,能完成以下任務的就叫做優先佇列: ·插入一個數值 ·取出最小的數值(獲取數值,並且刪除) 實現優先佇列,應該使用二叉樹完成,是一種叫二叉堆的資料結構(binary heap) 二叉堆分為兩種,最小堆和最大堆。最小堆是父節點的鍵值總是小於等於子節點的鍵值。最

Priority Queue(Heaps)--優先佇列

0)引論 前面已經有了連結串列,堆疊,佇列,樹等資料結構,尤其是樹,是一個很強大的資料結構,能做很多事情,那麼為什麼還要引進一個優先佇列的東東呢?它和佇列有什麼本質的不同呢?看一個例子,有一個印表機,但是有很多的檔案需要列印,那麼這些任務必然要排隊等候印表機逐步的處理。這裡

優先佇列)淺談

1、概述 在分析堆之前,你可以理解一下佇列和棧,其實他們都是對任務的一種排程策略,只是各自的準則不同罷了,佇列為先進先出,棧為先進後出,而堆是每個任務分配了一個優先權,根據優先權進行任務的執行。排程程式通過堆始終能獲取優先權最高的任務進行執行。比較常見應用為作業系統。 2、

優先佇列)及相關操作

二叉堆(堆) 堆是一顆完全二叉樹:除了底層每個節點都有兩個孩子,底層節點從左到右依次填入(不能有間隔)。 一顆高為hh的完全二叉樹有2h∼2h+1−12h∼2h+1−1個節點;NN的節點的完全二叉樹的高度為⌊logN⌋⌊log⁡N⌋。 堆可以用陣列實現:如果