初探12306售票算法

wzgt9456 9年前

来自: http://www.cnblogs.com/feichengwurao/p/5191253.html

1.以G71列车为例,首先对车次站台进行占位编码(从1开始到最后一站递加)

对以上占位简单描述以下:G71总共18个站点那么我们的单个座位的座位标识可以用十八位长度的二进制字符串表示10000000000000000每一位代表一个站点,每天放票前初始化到下面的订票表中,数据如下

订票表中的始发受限站点和终到受限站点可以灵活搭配(这个就可以实现限制站点发售)

2.查询余票

如果我们要查询日期为2016-06-11,始发站保定东站(3)到韶关站(15)的G71二等座F座位余票情况只需要执行如下sql(该SQL可以实现选座位和选车厢等功能)

select GUID,车次编码,车次类型,座位类型,车厢号码,座位编码,座位位置 from 订票表

where  to_number(substring(座位标识,3,15))=0

and 发车日期='2016-06-11'

and 车次编码='G71'

and substring(始发受限车站,3,4)=1

and substring(终到受限车站,15,16)=1

and 车票状态='待售'

and 车次类型='二等座'

and 座位位置='F'

3.预定票

3.1根据第二步中查询条件获取一条记录然后将车票状态改为锁定

3.2待锁定成功后进行支付

3.2支付成功后然后将保定到韶关的票(000111111111111000这里的始发站标记为0)与原有的票进行与运算,并将车票状态改为待售

3.3如果指定时间没有支付,那么可以将这条记录的车票状态恢复为待售

4.退票

获得该车次保定到韶关的票 (000111111111111000)与对应的票进行非运算,则即可回归票池子了

以下为相关java代码

  1 import java.math.BigDecimal;    2     3 public class MainTest {    4     public static void main(String[] args) {    5         String ticketFlag = "100000000000000000";    6         int beginStation = 3;    7         int endStation = 15;    8         long beginTime = System.currentTimeMillis();    9         String result = orderTicket(ticketFlag, beginStation, endStation);   10         if (result.equals(ticketFlag)) {   11             System.out.println("订票失败");   12         } else {   13             System.out.println("订票后的结果:" + result);   14             // 如果要取消的话,就进行这个操作   15             String b = buildTicket(ticketFlag.length(), beginStation,   16                     endStation);   17             System.out.println("释放后的结果:" + releaseTicket(ticketFlag, b));   18    19         }   20         long endTime = System.currentTimeMillis();   21         System.out.println("耗时:" + (endTime - beginTime));   22     }   23    24     /**   25      * 订票   26      *    27      * @param ticketFlag   28      * @param beginStation   29      * @param endStation   30      * @return   31      */   32     private static String orderTicket(String ticketFlag, int beginStation,   33             int endStation) {   34         String result = "";   35         if (checkCanTicket(ticketFlag, beginStation, endStation)) {   36             String b = buildTicket(ticketFlag.length(), beginStation,   37                     endStation);   38    39             String currentTicked = toTicket(ticketFlag, b);   40             System.out.println("预占票前结果:" + ticketFlag);   41             result = currentTicked;   42         } else {   43             result = ticketFlag;   44         }   45         ;   46         return result;   47     }   48    49     /**   50      * 取消已定票   51      *    52      * @param ticketFlag   53      * @param b   54      * @return   55      */   56     private static String releaseTicket(String ticketFlag, String b) {   57         StringBuilder tempSt = new StringBuilder("");   58         int length = ticketFlag.length();   59         for (int i = 0; i < length; i++) {   60             char tempA = ticketFlag.charAt(i);   61             char tempB = b.charAt(i);   62             if (tempA == '1' && tempB == '1') {   63                 tempSt.append("0");   64             } else {   65                 tempSt.append(tempA);   66             }   67         }   68         return tempSt.toString();   69     }   70    71     /**   72      * 创建区间占位票   73      *    74      * @param length   75      * @param beginStation   76      * @param endStation   77      * @return   78      */   79     private static String buildTicket(int length, int beginStation,   80             int endStation) {   81         StringBuilder st = new StringBuilder("");   82         for (int i = 0; i < length; i++) {   83             if (i >= beginStation && i < endStation) {   84                 st.append("1");   85             } else {   86                 st.append("0");   87             }   88         }   89         System.out.println("创建区间票:" + st.toString());   90         return st.toString();   91     }   92    93     /**   94      * 生成订票后的结果   95      *    96      * @param ticketFlag   97      * @param b   98      * @return   99      */  100     private static String toTicket(String ticketFlag, String b) {  101         StringBuilder tempSt = new StringBuilder("");  102         int length = ticketFlag.length();  103         for (int i = 0; i < length; i++) {  104             char tempA = ticketFlag.charAt(i);  105             char tempB = b.charAt(i);  106             if (tempA == '1' || tempB == '1') {  107                 tempSt.append("1");  108             } else {  109                 tempSt.append(tempA);  110             }  111         }  112         return tempSt.toString();  113     }  114   115     /**  116      * 是否可以订票  117      *   118      * @param ticketFlag  119      * @param beginStation  120      * @param endStation  121      * @return  122      */  123     private static boolean checkCanTicket(String ticketFlag, int beginStation,  124             int endStation) {  125         boolean result = false;  126         String tempTicket = ticketFlag.substring(beginStation, endStation);  127         BigDecimal b = new BigDecimal(tempTicket);  128         if (b.equals(new BigDecimal("0"))) {  129             result = true;  130         }  131         return result;  132     }  133   134 }