浅析12306售票算法(java版)
作者:全城热恋 发布时间:2023-11-16 10:27:12
1.以G71列车为例,首先对车次站台进行占位编码(从1开始到最后一站递加)
对以上占位简单描述以下:G71总共18个站点那么我们的单个座位的座位标识可以用十八位长度的二进制字符串表示10000000000000000每一位代表一个站点,每天放票前初始化到下面的订票表中,数据如下余票根据座位标识中的0的个数决定最大余票数量
订票表中的始发受限站点和终到受限站点可以灵活搭配(这个就可以实现限制站点发售)
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)与原有的票进行或运算,并将车票状态改为待售
100000000000000000 | 000111111111111000 = 100111111111111000 这个时候的余票标识即为动态余票
3.3如果指定时间没有支付,那么可以将这条记录的车票状态恢复为待售
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();
}
/**
* 创建区间占位票
*
* @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("创建区间票:" + 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;
}
}


猜你喜欢
- 前言之前有人提到过取绝对值时 直接写三目运算符比用Mathf.Abs()效率高 没觉得能高太多今天测了一下 真是不测不知道 一测吓一跳 直接
- 一、介绍以及编解码流程MediaCodec 类可用于访问低级媒体编解码器,即编码器/解码器组件。它是 Android 低级多媒体支持基础结构
- 需要设置允许不安全代码.....项目->属性->生成->允许不安全代码/// <summary> &
- 本文实例为大家分享了Android Scroller实现弹性滑动的具体代码,供大家参考,具体内容如下首先看下实现效果,可以看到当我们手指松开
- 腾讯TBS浏览器服务我们都知道,在Android开发中,经常会用到Webview,而且WebView是出了名的坑的,各种bug。这时候腾讯老
- 实现需求:两个线程交替打印1,0,打印10轮java多线程口诀:高内聚,低耦合线程操作资源类判断干活通知防止虚假唤醒方式一:使用synchr
- 反射机制Java语言提供的一种基础功能,通过反射,我们可以操作这个类或对象,比如获取这个类中的方法、属性和构造方法等。 * :分为JDK动
- 这个月根据需求在项目中做了一个时间选择器,虽然没有用到Android原生的时间选择控件,但我羞愧地发现自己竟然从来没有用过这方面控件!趁现在
- Android UI 实现 * 详解listview 的使用步骤简单的listview * 实现1.实现效果图2.需要掌握的知识listvi
- 一、项目运行环境配置:Jdk1.8 + Tomcat8.5 + Mysql + HBuilderX(Webstorm也行)+ Eclispe
- activiti使用的时候,通常需要跟业务紧密的结合在一起,有些业务非常的复杂,比如一个简单的采购流程:流程如下: 供应商上新商品
- 前言加密配置是一个很常见的需求,在spring boot生态中,已经有非常多的第三方starter实现了,博主所在公司也有这种强制要求,一些
- 使用正则表达式,效率较高public boolean canParseInt(String str){if(str == null){ //
- Android应用经常会和服务器端交互,这就需要手机客户端发送网络请求,下面介绍四种常用网络请求方式,我这边是通过Android单元测试来完
- java的jar是一个打包工具,用于将我们编译后的class文件打包起来,这里面主要是举一个例子用来说明这个工具的使用。在C盘下的temp文
- 今天来说一个Java多机部署下定时任务的处理方案。需求: 有两台服务器同时部署了同一套代码, 代码中写有spring自带的定时任务,但是每次
- 首先我们知道:JVM发生内存错误的类型1、堆内存泄漏:OutOfMemory:Java heap space此种内存泄漏,增加内存,只能暂时
- 目录synchronized 实现原理适应性自旋(Adaptive Spinning)锁升级Java 对象头偏向锁(Biased Locki
- 在Spring MVC中想要对每一个URL进行权限控制,不想手工整理这样会有遗漏,所以就动手写程序了。代码如下: /** &nb
- 本文实例为大家分享了Unity实现弹球打砖块游戏的具体代码,供大家参考,具体内容如下创作界面记录摄像机所需脚本1射线shexianusing