導讀

相信大家應該都有搶火車票的經驗,每年年底,這都是一場盛宴。然而你有沒有想過搶火車票這個演算法是怎麼實現的呢? 應該沒有吧,咱們今天就來一一探討。其實並沒有你想的那麼難

bitmap與位運算

redis的bitmap基本使用咱們之前已經介紹過了,如果不是很熟悉的朋友可以看看這裡
redis bitmap的基本操作和應用

今天在這裡咱們主要是先回顧一下位運算

12306搶票演算法詳解


我們以北京到西安這趟高鐵為例,比如我的路線就是從北京到西安,車上如果只剩最後一張票了,那麼如果有其他人,在北京到西安這條路線之間買任何一站,那麼我都是買不了票的,換句話說,對於單個座位來說,必須是起點到目的地之間的所有站,都沒有人買的話,那麼才能被算是有票狀態。

所以我們可以嘗試用bitmap結合上位操作來實現這種場景,以上述北京到西安為例,我們把問題簡化

  • 比如一個火車上只有4個座位
  • 北京到西安,一共是4站,其實是三個區間的,分別為北京->石家莊,石家莊->鄭州,鄭州->西安

首先我們給每個區間構建一個空點陣圖(0為有票,1為無票)

接下來,比如有人買了一張從北京到西安的票

買票這個動作,比如被分配到的座位是編號為1的座位,那麼我們直接把北京到西安的所有站,1號座位全部設定為1,如下圖

接下來又有人買了一張從石家莊到西安的票

比如這次分配的是座位2,那麼我們把石家莊到西安的所有票全部設定為1就行了,如下圖

如何知道還剩幾張票?

其實解決這個問題很簡單,我們直接把上述點陣圖做一個或操作就可以了

或操作結果有幾個0,則說明還剩幾張票。

總結

其實解決這個問題主要在於點陣圖的構建,因為火車票對於某一個座位來說,只要起點到終點中間某一個區間被佔用了(置為1),那麼整個座位都是無效的這個特點,很容易想到用或操作的結果來判斷買票結果,我們這裡只用了4位是為了方便說明問題,實際中應該是火車上有多少座位,點陣圖的長度就應該是多少。
好了,關於搶票演算法我們就介紹到這裡,你有沒有Get到呢?或者你有沒有更好的實現方法呢?