淺析12306售票算法(java版)
1.以G71列車為例,首先對車次站臺進行占位編碼(從1開始到最后一站遞加)
對以上占位簡單描述以下:G71總共18個站點那么我們的單個座位的座位標識可以用十八位長度的二進制字符串表示10000000000000000每一位代表一個站點,每天放票前初始化到下面的訂票表中,數據如下余票根據座位標識中的0的個數決定最大余票數量
訂票表中的始發(fā)受限站點和終到受限站點可以靈活搭配(這個就可以實現限制站點發(fā)售)
2.查詢余票
如果我們要查詢日期為2016-06-11,始發(fā)站保定東站(3)到韶關站(15)的G71二等座F座位余票情況只需要執(zhí)行如下sql(該SQL可以實現選座位和選車廂等功能)
select GUID,車次編碼,車次類型,座位類型,車廂號碼,座位編碼,座位位置 from 訂票表
where to_number(substring(座位標識,3,15))=0
and 發(fā)車日期='2016-06-11'
and 車次編碼='G71'
and substring(始發(fā)受限車站,3,4)=1
and substring(終到受限車站,15,16)=1
and 車票狀態(tài)='待售'
and 車次類型='二等座'
and 座位位置='F'
3.預定票
3.1根據第二步中查詢條件獲取一條記錄然后將車票狀態(tài)改為鎖定
3.2待鎖定成功后進行支付
3.2支付成功后然后將保定到韶關的票(000111111111111000這里的始發(fā)站標記為0)與原有的票進行或運算,并將車票狀態(tài)改為待售
100000000000000000 | 000111111111111000 = 100111111111111000 這個時候的余票標識即為動態(tài)余票
3.3如果指定時間沒有支付,那么可以將這條記錄的車票狀態(tài)恢復為待售
100111111111111000^000111111111111000 = 100000000000000000 這個時候的余票及自動還原回去了
4.退票
獲得該車次保定到韶關的票 (000111111111111000)與對應的票進行非運算,則即可回歸票池子了
以下為相關java代碼
import java.math.BigDecimal; public class MainTest { public static void main(String[] args) { String ticketFlag = ""; int beginStation = ; int endStation = ; long beginTime = System.currentTimeMillis(); String result = orderTicket(ticketFlag, beginStation, endStation); if (result.equals(ticketFlag)) { System.out.println("訂票失敗"); } else { System.out.println("訂票后的結果:" + result); // 如果要取消的話,就進行這個操作 String b = buildTicket(ticketFlag.length(), beginStation, endStation); System.out.println("釋放后的結果:" + releaseTicket(ticketFlag, b)); } long endTime = System.currentTimeMillis(); System.out.println("耗時:" + (endTime - beginTime)); } /** * 訂票 * * @param ticketFlag * @param beginStation * @param endStation * @return */ private static String orderTicket(String ticketFlag, int beginStation, int endStation) { String result = ""; if (checkCanTicket(ticketFlag, beginStation, endStation)) { String b = buildTicket(ticketFlag.length(), beginStation, endStation); String currentTicked = toTicket(ticketFlag, b); System.out.println("預占票前結果:" + ticketFlag); result = currentTicked; } else { result = ticketFlag; } ; return result; } /** * 取消已定票 * * @param ticketFlag * @param b * @return */ private static String releaseTicket(String ticketFlag, String b) { StringBuilder tempSt = new StringBuilder(""); int length = ticketFlag.length(); for (int i = ; i < length; i++) { char tempA = ticketFlag.charAt(i); char tempB = b.charAt(i); if (tempA == '' && tempB == '') { tempSt.append(""); } else { tempSt.append(tempA); } } return tempSt.toString(); } /** * 創(chuàng)建區(qū)間占位票 * * @param length * @param beginStation * @param endStation * @return */ private static String buildTicket(int length, int beginStation, int endStation) { StringBuilder st = new StringBuilder(""); for (int i = ; i < length; i++) { if (i >= beginStation && i < endStation) { st.append(""); } else { st.append(""); } } System.out.println("創(chuàng)建區(qū)間票:" + st.toString()); return st.toString(); } /** * 生成訂票后的結果 * * @param ticketFlag * @param b * @return */ private static String toTicket(String ticketFlag, String b) { StringBuilder tempSt = new StringBuilder(""); int length = ticketFlag.length(); for (int i = ; i < length; i++) { char tempA = ticketFlag.charAt(i); char tempB = b.charAt(i); if (tempA == '' || tempB == '') { tempSt.append(""); } else { tempSt.append(tempA); } } return tempSt.toString(); } /** * 是否可以訂票 * * @param ticketFlag * @param beginStation * @param endStation * @return */ private static boolean checkCanTicket(String ticketFlag, int beginStation, int endStation) { boolean result = false; String tempTicket = ticketFlag.substring(beginStation, endStation); BigDecimal b = new BigDecimal(tempTicket); if (b.equals(new BigDecimal(""))) { result = true; } return result; } }
相關文章
Logback 使用TurboFilter實現日志級別等內容的動態(tài)修改操作
這篇文章主要介紹了Logback 使用TurboFilter實現日志級別等內容的動態(tài)修改操作,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-08-08如何在springMVC的controller中獲取request
這篇文章主要介紹了如何在springMVC的controller中獲取request,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下2019-12-12