中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

multimap和priority_queue怎么理解

發布時間:2021-12-30 14:43:40 來源:億速云 閱讀:89 作者:iii 欄目:大數據

本篇內容介紹了“multimap和priority_queue怎么理解”的有關知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領大家學習一下如何處理這些情況吧!希望大家仔細閱讀,能夠學有所成!

題目簡述:有一個人每天往返于一段道路中,走著走著就覺得無聊了,于是自己給自己找樂子發明了一個扔石頭的游戲:在一次單程行走過程中,假設整段路程中有 n 塊石頭,每塊石頭有兩個重要信息,一個是所處的位置,一個是石頭可以扔出的距離。還有一點值得注意,石頭的塊頭越大扔的距離就越近。此人從第一塊石頭開始,遇到的第奇數個石頭就搬起來往前扔,遇到的第偶數個石頭不作處理。如果在某個位置上有兩個石頭,那么此人會先看到個頭較大的那塊石頭(即扔的距離較近的那塊石頭)。現在要求算出此人走出多遠就沒石頭可扔了。

輸入數據:第一行給出測試數據的組數 t ( 1< = t <= 10 ),接下來給出 t 組測試數據,每組數據第一行 給出測試數據的組數 n ( 0 < n <=10 000) ,接下來的 n 行,每行給出一對測試數據 p 和 d ,( p( 0 <= p <= 10 000) 表示石頭的位置,d ( 0 <= d <= 1 000) 表示石頭可扔出的距離 )

輸出數據:給出每組測試數據的結果,每行一個數據。

測試數據如下:

multimap和priority_queue怎么理解


現在對整個題目進行分析,此人從第一塊石頭出發,隨著時間推移接下來遇到的石頭相對于起始位置越來越遠,因此石頭的位置是一個遞增的信息,由此可以斷定,存儲石頭信息的結構應該具備順序結構,但石頭的位置并不連續,如果用 vector 來存儲,勢必會造成空間的大量浪費。此人遇到偶數個石頭丟棄,遇到奇數個石頭要朝著他行走的方向往前扔,也就意味著扔到前面的石頭他還會再遇到。這就需要在處理的時候,刪掉偶數塊的石頭,并將奇數塊石頭重新添加到序列其他的位置,這就要求存儲石頭信息的結構需要有優良的插入、刪除性質,序列型容器 vector 在這一點上更顯的能力不足,這個時候,考慮其他的序列容器 隊列queue 、鏈表 list 。鏈表雖然在隨機插入刪除方面很有優勢,但若要求有序,鏈表操作是相當麻煩的。這個時候就剩 queue 還沒被拋棄,題目要求遇到一個石頭處理一個,即將此石頭出列進行其余操作,這正是隊列具備的特征,處理石頭的時候需要將奇數的石頭根據位置信息插入到相應位置。在有序的序列中,將元素插入到相應位置,priority_queue 就是應此要求誕生的。

選定了存儲結構,現在來討論一下具體的實現:使用計數器對此人遇到過的石頭進行計數,分成奇數和偶數情況來處理,偶數情況將該石頭信息出隊不作處理,奇數情況將石頭出隊,并把位置信息更改為當前位置加可扔距離再次入隊。每次對當前訪問的石頭位置進行存儲,如此處理直至隊列為空,輸出最后一個處理石頭的位置信息即可。

優先隊列需要對隊列的優先標準進行定義:當位置不相同時,位置靠前的優先性高,位置相同時,可扔距離較近的優先性較高。

在這個問題中需要考慮可扔距離為零的特殊情況。

下面對優先隊列使用中需要注意的問題進行闡述


優先隊列包含在 queue 頭文件中

優先隊列的聲明有三種形式,

第一種:

priority_queue< element_type >  que;

此時聲明了一個存儲 element_type 類型元素的優先隊列 ,名稱為 que,這句聲明中包含了如下信息:

  1. 該優先隊列元素的類型為 element_type,

  2. 該優先隊列使用的容器為默認容器 vector ,

  3. 該優先隊列使用的優先級關系為優先級由高到低,一般的數字大的數據優先級高,此時隊首的元素為優先級高的元素。確定優先級的比較函數是less();請注意,優先隊列中的內置函數只能對基本數據類型進行排序,如果要對特殊類型進行排序,需要自定義比較函數。


第二種: 

priority_queue< element_type, name< element_type > > ;

此時聲明了一個存儲 element_type 類型的元素的優先隊列 ,名稱為 que,這句聲明中包含了以下信息:

  1. 該優先隊列元素的類型為 element_type ,

  2. 該優先隊列使用的容器為 name 容器,( 此處的 name 為用戶需要使用的容器的名稱,并非真實存在的某容器,假設 此處需要使用 queue容器,那么聲明為

    priority_queue< element_type, queue< element_type > >

  3. 該隊列使用的優先級關系為默認優先級(由高到低),默認比較函數為 less()。

第三種:

priority_queue< element_type , vector< element_type > , less<element_type > > ;

這種定義用于用戶使用非 less()函數的其他優先級。

需要注意此時無論容器是不是默認容器 vector 都需要進行傳參,這由優先隊列相關函數內部實現決定。

例如:

現在元素類型為結構體類型,比較函數需要改變,則 處理如下:

struct node

{

     element_type x;

     element_type y;

};

bool compare( node a, node b )

{

      return a . x   >  a . y   ;(此處的優先級關系可任意更改)

}

priority_queue<node , vector<node> , compare<node> > ;

另例如下:

struct node

{

     friend  bool operator < ( node a , node b )

     {

           return a . y  >  b . y ; (同樣,此處的優先級順序也是可以根據需要任意更改的)

     }

     element_type x;

     element_type y;

};

 priority_queue< node>

或者下面這種:

priority_queue< node , vector<node> , less<node> > ; // 此時優先級實際上已經更改。

補充說明:

  1. 在優先隊列中,內置優先性比較函數有兩個:

    less(),由隊首開始優先性逐漸減小

    greater(),由隊首開始優先性逐漸增大

    但不聲明的情況下,默認使用 less(),需要使用 greater ()的時候,要使用上面介紹的第三種聲明方式。

2. 優先隊列其余函數大多與普通隊列 queue 的使用方法類似。


以上是使用優先隊列的方法,下面我將用 multimap 方法對此題進行講解,在此題中,multimap  方法似乎有些麻煩,但是也不失為一種解題思路,重在介紹 multimap 的相關函數使用方法。

在序列式容器中有自動排序功能的是 priority_queue ,而關聯式容器也有這個特點,而且紅黑樹實現效率非常高。

關聯式容器有 set / multiset  和 map / multimap 這兩對:

set 的結構相當于集合,除了滿足集合的唯一性、確定性,還滿足有序性(默認由小到大排列)。multiset 與 set 的相關用法大多相同,唯一的區別在于,multiset 允許集合中有相同元素的出現,由此會引起部分函數的差異。

map/multimap 的結構相當于 映射對的集合,同樣,兩者大同小異,區別在于multimap中允許有相同鍵值的元素出現。

由于在某一確定時刻每個石頭的位置和可扔距離是確定的,且一一對應。因此我想到可以用 map 容器,又因為扔石頭過程中,同一位置有可能出現多于一塊石頭,因此可以確定使用 multimap 容器。

思路和上面的思路大同小異,先將初始數據存入 map ,然后設置計數變量和存儲當前位置的變量,map 不空就不斷進行計數變量的奇偶判斷和map 刪除、插入元素的處理。同樣應該考慮可扔距離為零的情況。

在這個過程中有一些需要注意的地方:

一、頭文件

multimap 包含在 map 頭文件中,使用時要在程序打開頭文件編寫時加入#include<map>語句。

二、聲明

分為兩種:

第一種:

multimap<key_type , value_type> mp;

包含以下信息

  1. 聲明了一個 鍵值為 key_type 類型 、關聯值為 value_type 類型的 multimap  型變量 mp;

  2. multimap內 的鍵值排序按照默認排序順序由小到大;

第二種:

multimap<key_type , value_type ,compare< key_type> >;

包含以下信息

  1. 聲明了一個鍵值為 key_type 類型 ,關聯值為 value_type 類型的 multimap  型變量 mp;

  2. multimap 內鍵值的排序規則由比較函數 compare給出,請注意這里 compare()函數中的參數只有 鍵值的類型,而沒有關聯值的類型,原因是,multimap 內部的排序只根據鍵值大小進行排序,而對關聯值的順序沒有相應的處理,由此可見, multimap 中同一鍵值元素的相對位置并不是由關聯值的大小決定,而是由添加順序決定。


三、普通map可以用 map[key]來對鍵值為 key 的元素的關聯值進行操作,但 multimap 不包含此性質,因此向multimap中添加元素只能使用 insert()函數,同樣也不能用mp[ key ]來訪問某一元素。用法如下:

  1. mp . insert( pair< key_type ,value_type>( key ,value ) )

  2. mp . insert( make_pair ( key , value ) ) ;

其中,pair是一種模版類型,含有兩個成員分別為 first 和 second。 兩個成員的類型可以根據需要任意確定,可以是基本數據類型,也可以是用戶自定義類型。pair 可以作為新的類型 進行函數傳參和使用。聲明如下:

pair< element_type , element_type >  p = ( element_1 , element_2);

pair< element_type , element_type >  p = make_pair ( element_1 , element_2 )

需要使用pair 的兩個成員時如下:

p . first

p . second

巧用 pair,當某函數需要返回兩個類型不同的值時,可以定義 pair 來返回。

四、如何確定鍵值相同而關聯值不同的元素的個數,以及如何對它們進行訪問:

  1. 確定個數使用函數

    mp . count ( key ) ;

  2. 逐個進行訪問

    mp . equal_range ( key ) ;

    注意,此函數的返回值是兩個迭代器,其中,第一個迭代器返回的是 該鍵值第一個元素的迭代器,第二個迭代器返回的的是 該鍵值最后一個元素訪問結束即將跳轉的下一個元素的迭代器 。因此需要使用模版 pair ,如下:

    typedef   multimap< key_type , value_type >:: iterator  iter;

    pair< iter , iter > p ;

    p = mp . equal_range ( key ) ;

    while( p . first  !=  p . second )

    {

          cout << p . first << endl ;



          p . first ++ ;

  3. }

       在此應該注意思考一個問題:當multimap中只有一個元素的時候, p . second 此時的值應該與當前 mp . end ( ) 返回值相同,這時候,如果循環寫成這樣:

while( p . first  !=  p . second )

{

      cout << p . first << endl ;

      mp . insert ( make_pair( elem_1 , elem_ 2 )  ) ;

      p . first ++ ;

}

在插入新的元素后,   mp . end ( ) 值變了,但 p . second 值還是原來的末尾,既不是現在的尾,也不是新加入的元素的位置,p .first 會一直自增尋找結束條件,但 p . second 目前已經失效了,會陷入死循環,并且這種錯誤一般不容易被發現 。因此在編寫程序的過程中,應該盡量避免這種情況的發生。改進方法需要根據具體的要求來實現,在這里就不舉例了。

五、特殊查找

mp . lower_bound( key ) 查找第一個鍵值不小于 key 的元素,返回其迭代器

mp . upper_bound( key ) 查找第一個鍵值比 key 大的元素,返回其迭代器

由上面注意事項中所提到的,同一鍵值的不同元素在multimap中的順序并不是按照 value 值的大小決定,而是由輸入順序決定,因此,在本題中,需要將相同鍵值的元素摘出來存在vector中,對其進行排序再使用。本題中,multimap 比 priority_queue 復雜的地方就在此了。

“multimap和priority_queue怎么理解”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識可以關注億速云網站,小編將為大家輸出更多高質量的實用文章!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

大石桥市| 商河县| 延庆县| 普洱| 南京市| 康保县| 娄底市| 阿克陶县| 明溪县| 深水埗区| 浦城县| 明光市| 上犹县| 涞源县| 曲松县| 赣州市| 陆川县| 报价| 红原县| 崇文区| 镇康县| 资溪县| 阿克苏市| 连平县| 娱乐| 木兰县| 定结县| 阿合奇县| 乌拉特前旗| 泰来县| 五大连池市| 峨眉山市| 营山县| 石林| 阳东县| 景德镇市| 南阳市| 镶黄旗| 宁阳县| 汤原县| 磐石市|