積分排名在很多專案都會出現,積分排名主要滿足以下需求:
當排序的資料量不大的時候,這個需求很容易滿足,但是如果資料量很大的時候比如百萬級、千萬級甚至上億的時候,或者有實時排名需求;這個時候要滿足效能、低成本等需求,在設計上就變得複雜起來了。
高效做法是不對積分進行排序,僅僅是統計每個積分區間的人數,用積分區間的形式去統計相應的人數,下面是演算法描述。
1.根據積分範圍建立平衡二叉樹
設[0, n]為積分範圍, 構造的平衡二叉樹如下圖:
每個節點包含兩個資料字段(除了指標):
積分的區間的劃分是根據平分的方式,把當前積分範圍一分為二生成兩個子節點,然後遞迴的重複該步驟,直到積分區間無法劃分為止(即區間[x, y], x == y)
例子:假設積分範圍為: [0, 5], 構造的平衡二叉樹如下圖:
節點內的資料表示當前積分區間的人數。
從上圖可以看出來,所有積分都在葉子節點,葉子節點即最小粒度的積分區間。
2. 統計相應積分區間的人數
這裡主要有兩種操作:
假設積分為i,
新增積分:
新增積分的過程就是查詢積分i, 同時累加查詢過程經過的節點計數。
下面給出操作例子,注意觀察操作路徑。
例: 需要新增積分3, 結果如下圖
接著在新增積分4,結果如下圖
接著再新增積分4,結果如下圖
接著新增積分2,結果如下圖
刪除積分
刪除積分的過程也是查詢積分i, 區別是查詢過程經過的節點計數全部減1。
ps: 只有積分是存在的情況下,才能做刪除操作,另外用一組標記,標識積分是否存在,這裡就不列舉了。
例子: 刪除積分4, 結果如下圖
3. 查詢名次操作
查詢某個積分的排名的過程也是查詢積分i的過程,下面是查詢過程統計節點計數的演算法:
對於查詢路徑上的任意節點,如果積分在左節點區間,則累加右節點區間的計數。
最終累加計數的結果加1即是積分的名次
例子: 查詢積分3的名次
藍色節點是查詢積分3經過的路徑,紅色節點是需要累加的計數值。
最終結果是:0 + 1 + 1, 積分3的名次是第2名
從上面的演算法可以看出,對平衡二叉樹的操作,演算法複雜度是o(log n), n是最大積分。
在積分範圍不變的情況下,演算法複雜度是穩定的,跟使用者量無關,因此可以實現海量使用者積分排名、實時排名演算法需要。
對於海量積分資料實時排名、這裡給出的是核心演算法,實際業務的時候還需要增加一些額外的處理,比如uid於積分的對映表用於記錄使用者歷史積分、積分與uid的對映表用於topn這種查詢前n名的需求、資料持久化、高可用等需求。
參考自海量積分資料實時排名處理方式介紹一
海量積分資料實時排名處理方式介紹一
查詢使用者名次。查詢topn 即查詢前n名的使用者 實時排名 很多專案是可選的 當排序的資料量不大的時候,這個需求很容易滿足,但是如果資料量很大的時候比如百萬級 千萬級甚至上億的時候,或者有實時排名需求 這個時候要滿足效能 低成本等需求,在設計上就變得複雜起來了。這裡列舉下日常對於排名的常規做法和缺...
資料實時備份
隨著企業對資訊系統的依賴性越來越高,資料庫作為資訊系統的核心擔當著重要的角色。尤其在一些對資料可靠性要求很高的行業如銀行 電信等,如果發生意外停機或資料丟失其損失會十分慘重。資料庫的備份是乙個長期的過程,而恢復只在發生事故後進行,恢復可以看作是備份的逆過程,恢復的程度的好壞很大程度上依賴於備份的情況...
Javascript中資料實時推送
資料變化後前端需要更新,有幾種方式 參考 1.利用setinterval函式,每隔n秒去非同步拉取資料。對資料實時性要求不高時可用。2.ajax輪詢方式推送資料。缺點是服務端需要在死迴圈中反覆查詢資料庫。還沒有試過這種方式 3.利用websocket推送資料,這是html5提供的方法,所以只能支援h...