使用優先佇列在iOS中實現訊息排序

2021-08-05 22:28:01 字數 1742 閱讀 8385

不重複:有時候流動網路很差,乙個請求發出去很久才響應,中間可能隔了幾秒鐘,這個時候,有些使用者很急可能會狂點介面,比如我,導致請求重**(實際中已做限頻,狂點也不會發請求),然後回來的訊息自然就有很多重複了。去重很簡單了,oc 中用 nsmutabledictionary,底層是雜湊表,把訊息id 作為 key,加入到字典中再拿出來,重複的就沒有了。但實際中資料量較小,你寫兩個 for 迴圈去重也不會有什麼效能問題,理論上會更耗cpu和電量。

第一的想法是每次收到新的訊息就加入到優先佇列中,然後一出隊就全部都是有序的了。但是 oc 中沒有優先佇列這種結構,甚至連佇列都沒有,乙個變通的做法就是用 nsmutablearray 來實現佇列和棧,但是用法很彆扭,如果 nsmutablearray 用陣列實現的話,會有大量的位移操作,效率會很低。

一開始我把訊息儲存到 nsarray 中,每次來了新訊息都執行排序+去重的操作來保證有序,資料量小就沒什麼問題,其實也不小,群裡面聊天幾十個人同時發訊息,一下就重複好多次這樣的操作。後來比較有空,就自己用 oc 實現了乙個優先佇列,方便使用,效率高,大量資料下效能也很好。

普通佇列是先進先出的結構,優先佇列是一種按照優先順序大小,比如小的先出隊,的一種結構。所以先進的不一定先出,它會把優先順序高的先出,下面我認為id小的優先順序高。要先出隊。

舉個例子

入隊元素順序:2, 3, 4, 5, 1

普通佇列出隊:2, 3, 4, 5, 1

優先佇列出隊:1, 2, 3, 4, 5 (有序)

那麼如何實現優先佇列?有以下三種方法

就是每加入乙個元素的時候,把它移到乙個「合適」的位置,舉個例子

佇列中已經有 1, 3, 4,現在要加入 2

那麼把 2 移到 1,3 的中間,就是 1, 2, 3, 4

這個「合適」的位置定義為:前乙個元素 <= 要加入的元素 <= 後乙個元素

入隊已經保證有序了,那麼出隊就直接把第乙個元素拿出來,就是最小的了。

顯然 n 個元素的時間複雜度,入隊操作 o(n),出隊操作 o(1)

缺點:該方法,如果有大量的入隊操作比較耗時。

因為方法1的入隊操作耗時,那麼方法2做了個改進,入隊的時候什麼也不做,直接追加到尾部,出隊時候去遍歷陣列中最小的元素出隊,舉個例子。

佇列中已經有 3, 1, 4,現在要加入 2

那麼把 2 加到尾部,就是 3, 1, 4, 2

出隊的時候,遍歷陣列,找到最小的元素1,出隊就行了

顯然,入隊操作 o(1),出隊操作 o(n)

缺點:如果有大量出隊操作比較耗時

由於上面兩種方法都有缺點,最後用這種資料結構來實現優先佇列

什麼是堆?

如下圖

heap

入隊操作,向堆中加入乙個元素

出隊操作,從堆中刪掉乙個元素

用堆來實現優先佇列,入隊,出隊操作複雜度 o(log n),比較平衡。

php Memcache 中實現訊息佇列

memcache 一般用於快取服務。但是很多時候,比如乙個訊息廣播系統,需要乙個訊息佇列。直接從資料庫取訊息,負載往往不行。如果將整個訊息佇列用乙個key快取到memcache裡面.對於乙個很大的訊息佇列,頻繁進行進行大資料庫的序列化 和 反序列化,有太耗費。下面是我用php 實現的乙個訊息佇列,只...

Memcache 中實現訊息佇列

memcache 一般用於快取服務。但是很多時候,比如乙個訊息廣播系統,需要乙個訊息佇列。直接從資料庫取訊息,負載往往不行。如果將整個訊息佇列用乙個key快取到memcache裡面,對於乙個很大的訊息佇列,頻繁進行進行大資料庫的序列化 和 反序列化,有太耗費。下面是我用php 實現的乙個訊息佇列,只...

訊息佇列在使用中的注意事項

非同步不是萬能的,實現非同步重要的手段,訊息佇列在使用中也是有很多注意事項的。訊息佇列至少有三處容易出現瓶頸,我們一經典的發布 訂閱模式為例。分析一下都可能存在哪些瓶頸。發布 佇列 訂閱 入隊瓶頸,發布訊息佇列,處理太慢,發布端堵塞應用程式。佇列持久化瓶頸,佇列持久化是需要寫入磁碟的,大量的密集io...