淺析12306售票算法(java版)
1.以G71列車為例,首先對(duì)車次站臺(tái)進(jìn)行占位編碼(從1開始到最后一站遞加)

對(duì)以上占位簡(jiǎn)單描述以下:G71總共18個(gè)站點(diǎn)那么我們的單個(gè)座位的座位標(biāo)識(shí)可以用十八位長(zhǎng)度的二進(jìn)制字符串表示10000000000000000每一位代表一個(gè)站點(diǎn),每天放票前初始化到下面的訂票表中,數(shù)據(jù)如下余票根據(jù)座位標(biāo)識(shí)中的0的個(gè)數(shù)決定最大余票數(shù)量

訂票表中的始發(fā)受限站點(diǎn)和終到受限站點(diǎn)可以靈活搭配(這個(gè)就可以實(shí)現(xiàn)限制站點(diǎn)發(fā)售)
2.查詢余票
如果我們要查詢?nèi)掌跒?016-06-11,始發(fā)站保定東站(3)到韶關(guān)站(15)的G71二等座F座位余票情況只需要執(zhí)行如下sql(該SQL可以實(shí)現(xiàn)選座位和選車廂等功能)
select GUID,車次編碼,車次類型,座位類型,車廂號(hào)碼,座位編碼,座位位置 from 訂票表
where to_number(substring(座位標(biāo)識(shí),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.預(yù)定票
3.1根據(jù)第二步中查詢條件獲取一條記錄然后將車票狀態(tài)改為鎖定
3.2待鎖定成功后進(jìn)行支付
3.2支付成功后然后將保定到韶關(guān)的票(000111111111111000這里的始發(fā)站標(biāo)記為0)與原有的票進(jìn)行或運(yùn)算,并將車票狀態(tài)改為待售
100000000000000000 | 000111111111111000 = 100111111111111000 這個(gè)時(shí)候的余票標(biāo)識(shí)即為動(dòng)態(tài)余票
3.3如果指定時(shí)間沒有支付,那么可以將這條記錄的車票狀態(tài)恢復(fù)為待售
100111111111111000^000111111111111000 = 100000000000000000 這個(gè)時(shí)候的余票及自動(dòng)還原回去了
4.退票
獲得該車次保定到韶關(guān)的票 (000111111111111000)與對(duì)應(yīng)的票進(jìn)行非運(yùn)算,則即可回歸票池子了
以下為相關(guān)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("訂票后的結(jié)果:" + result);
// 如果要取消的話,就進(jìn)行這個(gè)操作
String b = buildTicket(ticketFlag.length(), beginStation,
endStation);
System.out.println("釋放后的結(jié)果:" + releaseTicket(ticketFlag, b));
}
long endTime = System.currentTimeMillis();
System.out.println("耗時(shí):" + (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("預(yù)占票前結(jié)果:" + 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();
}
/**
* 生成訂票后的結(jié)果
*
* @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;
}
}

相關(guān)文章
Struts2開發(fā) 基本配置與類型轉(zhuǎn)換
本篇文章,小編將為大家介紹關(guān)于Struts2開發(fā) 基本配置與類型轉(zhuǎn)換,有需要的朋友可以參考一下2013-04-04
java基礎(chǔ)知識(shí) super和this使用解析
這篇文章主要介紹了java基礎(chǔ)知識(shí) super和this使用解析,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-11-11
SpringBoot電腦商城項(xiàng)目刪除收貨地址的實(shí)現(xiàn)方法
這篇文章主要介紹了SpringBoot項(xiàng)目--電腦商城刪除收貨地址功能實(shí)現(xiàn),本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-09-09
Logback 使用TurboFilter實(shí)現(xiàn)日志級(jí)別等內(nèi)容的動(dòng)態(tài)修改操作
這篇文章主要介紹了Logback 使用TurboFilter實(shí)現(xiàn)日志級(jí)別等內(nèi)容的動(dòng)態(tài)修改操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-08-08
教你使用Java獲取當(dāng)前時(shí)間戳的詳細(xì)代碼
這篇文章主要介紹了如何使用Java獲取當(dāng)前時(shí)間戳,通過兩個(gè)java示例,向大家展示如何獲取java中的當(dāng)前時(shí)間戳,文本通過示例代碼給大家展示了java獲取當(dāng)前時(shí)間戳的方法,需要的朋友可以參考下2022-01-01
MyBatis查詢結(jié)果resultType返回值類型的說明
這篇文章主要介紹了MyBatis查詢結(jié)果resultType返回值類型的說明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2020-11-11
如何在springMVC的controller中獲取request
這篇文章主要介紹了如何在springMVC的controller中獲取request,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-12-12
使用json字符串插入節(jié)點(diǎn)或者覆蓋節(jié)點(diǎn)
這篇文章主要介紹了使用json字符串插入節(jié)點(diǎn)或者覆蓋節(jié)點(diǎn)的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-08-08

