First launch on the whole network: 12306 ticket grabbing algorithm is exposed? (Ten pictures are done)

file

foreword

This article is included in the album: http://dwz.win/HjK , click to unlock more knowledge of data structures and algorithms.

Hello, I'm Brother Tong, a hard-core man who climbs twenty-six floors every day and doesn't forget to read the source code.

I believe that everyone has the experience of grabbing and brushing tickets. At the end of each year, this is a feast.

However, have you ever wondered how the 12306 ticket grabbing algorithm is implemented?

No, think about it, or have no idea?

Today, we will expose how 12306, which people love and hate, achieves ticket grabbing.

Bit Operations Review

We know that computers can only recognize 0 and 1. To operate these 0s and 1s, we can only perform bit operations. So, how many bit operations are there?

Let's review:

operation symbol Example result
and & 1101 & 0110 0100
or | 1101 & 0110 1111
XOR ^ 1101 ^ 0110 1011
Negate ~ ~1101 0010
shift left << 1101 << 1 11010
Signed right shift (high-order complement by 1) >> 1101 >> 1 1110
Shift right without sign (fill high-order 0s) >>> 1101 >>> 1 0110

The above bit operations take Java as an example, there may not be >>> operations in other languages.

OK, the brief review of bit operations is here, and students who don't understand can Baidu it by themselves.

bitmap

Although most languages ​​provide bit operations, they do not provide a type similar to a bit array. To use these bit operations, we can only implement them through numeric types, such as int/long in Java.

And these arrays of digital types, we can generally call it "BitMap" (BitMap).

For example, if we need to use 128-bit memory, we can apply for an array containing two long types long[] bitmap = new long[2];.

But what's the use of bitmaps?

It is very useful. For example, if we want to count the activity of a user for one year, we can use bitmap to achieve it.

There are 365 days in a year, a long type can represent 64 bits, 365/64=6, only 6 long types are needed to record the activity of a user for a year. How to record it?

It is very simple. Initially, all the bits in the bitmap are 0. When the user logs in one day, find the day in the bitmap and change its bit to 1. After one year, this bitmap is recorded. On which days the user has logged in, count the number of 1s in this bitmap and divide by 365 to get his activity.

file

OK, this is just a very simple usage of bitmap. There are many advanced usages of bitmap, such as counting active users, current limit, permission control, etc. Of course, there is also the 12306 ticket grabbing algorithm that we are going to expose today.

12306 ticket grabbing algorithm

We know that a train has many seats and can go to many stations. Take a train G67 from Beijing to Guangzhou as an example:

file

There are a total of 18 stations on the G67 train. Some people may get off the train when they arrive in Wuhan, some people may get off at Changsha, some people may get on the train from Wuhan and get off at Hengshan West, and some people may even get off from Hengshan West. From Beijing all the way to Guangzhou, we assume that this train has a total of 200 seats.

So, how to implement a reasonable ticket grabbing strategy to ensure that the train can take the most people? (no standing ticket)

What is "the person who sits the most"? Assuming that for the No. 10 position, one person goes from Beijing to Wuhan, another person goes from Wuhan to Changsha, and another person goes from Changsha to Guangzhou, then three people can sit for this position; for another position, one person travels from Beijing to Guangzhou , then only one person can sit in this position. To put it simply, for a specific location, there can be no intersection between two people. For example, if one person travels from Beijing to Changsha, and the other person travels from Wuhan to Guangzhou, the two people cannot be arranged in the same position.

file

OK, let me give you a minute to think about it, don't rush to look down.


Well, one minute is up, let's move on.

First, let's review the information on the G67 train: a total of 18 stations and a total of 200 seats.

In order to facilitate the explanation and drawing, we assume that it has only 6 stations in Beijing, Xinyang, Wuhan, Yueyang, Changsha and Guangzhou, with a total of 8 seats.

For such information, we can implement the ticket grabbing strategy as follows:

  1. Create 5 bitmaps, each with a size of 8 bits, and initially, the value of each bit is 0.

    Why 5 bitmaps? Because when you arrive at the station, you get off the bus, and Guangzhou Station is the terminal station, and everyone at the station has to get off. For example, when a person goes from Beijing to Wuhan, he gets off the bus when he arrives in Wuhan, so it will not occupy the location of Wuhan.

file

  1. The ticket grabbing logic is handled in a single thread. The advantage of a single thread is that there is no need to consider concurrency issues, no CPU context switching, etc., and the entire operation is a CPU operation, which is fast and more efficient using a single thread.

    Of course, we have a better choice - Redis, Redis itself is a single-threaded processing, and it naturally supports BitMap, the speed is fast and good, interested students can learn about BitMap in Redis.

  2. Suppose the first person's request comes, and he wants to grab a ticket from Beijing to Wuhan. At this time, we only need to OR the two bitmaps of Beijing and Xinyang. In the result, all 0 positions indicate that the To grab the position, you can randomly return one of these positions, and mark this position as 1 in the two bitmaps of Beijing and Xinyang, indicating that this position is occupied by someone in Beijing and Xinyang. (Why did Wuhan not participate in the calculation? As mentioned earlier, this person got off the bus when he arrived in Wuhan.)

    Assuming that the last seat of this person is No. 2, then after the operation, the situation of each graph is as follows:

    file

  3. Then, the second person's request came. Suppose he wants to go from Xinyang to Changsha. At this time, he needs to OR the three bitmaps of Xinyang, Wuhan and Yueyang:

    Assuming that the last seat of this person is No. 4, then, after the calculation, the situation of each map is as follows:

    file

  4. Then, the third person's request comes. Suppose he wants to go from Beijing to Guangzhou. At this time, all 5 bitmaps are OR'ed:

    Assuming that the last seat of this person is No. 1, then, after the operation, the situation of each map is as follows:

    file

  5. OK, after multiple requests, suppose the bitmap becomes the following:

    file

    Please think, at this time, can you still get a ticket from Beijing to Guangzhou?

    can? can not? For those who can answer, please read it again from the beginning ^^

Well, we will introduce the ticket grabbing algorithm here. Have you got it? Or do you have a better way to do it?

postscript

In this section, we reviewed the operation of bit operations together, and learned how to use bitmaps to implement the 12306 ticket grabbing algorithm. Regarding bitmaps, there are actually many uses, such as various statistics, current limiting, and permission control.

Brother Tong received the latest information: All recursion can be rewritten as non-recursive, how to achieve it? Is there any trick? In the next section, we will discuss this topic together.

Follow the official account owner "Tong Ge Read Source Code" to unlock more source code, basics, and architecture knowledge.

file

{{o.name}}
{{m.name}}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324154481&siteId=291194637