Who said that an ordered linked list can't perform binary search, it just needs evolution? !

foreword

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

Hello, my name is Tong.

In the last section, we learned everything about hashing together, especially the evolution of hash tables. I believe that through the study of the previous section, you will be able to tell the interviewer how the hash table has developed from start to finish. Up to this point.

However, can the ultimate form of HashMap only be realized in the form of "array + linked list + red-black tree"? Are there alternatives? Why doesn't Java use this alternative you say?

In this section, we will learn another data structure - skip table. Regarding the content of skip table, I will divide it into two sections. The first section introduces the evolution of skip table, and the second section code implements skip table and rewrites it. HashMap.

Well, let's start with the study of the first section of the skip table.

sorted array

We all know that arrays can support random access, that is, elements can be quickly located through subscripts, and the time complexity is O(1).

So, what other uses does this random access feature have in addition to finding elements based on subscripts?

Just imagine, if an array is ordered, and I want to find a specified element , how can I find it in the fastest way?

0

The simple method is to traverse the entire array from the beginning, and return when you encounter the element you want to find. For example, to find the element of 8, you need to go 6 times to find it, and to find the element of 10 is even more exaggerated, and it takes 8 times.

Therefore, the time complexity of finding elements in this way is O(n).

1

Fast method, because the array itself is ordered, so we can use binary search, start from the middle, if the specified element is smaller than the middle element, then search in the left half, if the specified element is larger than the middle element, then Search in the right half, in sequence, until the specified element is found. For example, to find the element 8, first locate the position in the middle (7/2=3), add 1 to the left pointer in the next search, use position 4 as the left pointer, and the middle position becomes (4+(7-4 )/2=5), it only takes 2 times to find the element 8.

Using binary search, the efficiency is improved by more than a star and a half, and even the worst case only requires log(n) time complexity.

2

ordered linked list

We have introduced the fast search of ordered arrays above. Let's take a look at the case of ordered linked lists.

3

The above is an ordered linked list. At this time, if I want to find the element 8, I can only search from the head of the linked list until I encounter 8. The time complexity is O(n), and there seems to be no better way.

4

Let us consider the difference between an ordered array and an ordered linked list. The reason why an ordered array can be directly located to the middle element is that it can be quickly accessed by index (subscript), then, we give an ordered array. Is it possible to achieve a similar function by adding an index to a linked list?

The answer is yes, this kind of ordered linked list with index is a skip list, please show the skip list below.

skip table

The first question: how to add an index to an ordered linked list?

Here, a concept of "layer" needs to be added. Assuming that the level of the original linked list is 0, then select some elements to extend upward to form the first level index. Similarly, on the basis of the first level index, select some elements The elements extend upward to form the second level index, until you feel that the number of levels of the index is almost the same, yes, the skip list is so random, you are satisfied with it ^^

Suppose, for the above ordered linked list, I have added some indexes like this:

5

The second question: where to start accessing this skip table? 6?3?1?9?

It doesn't seem to work, so we need to add a special node - the head node, which is placed in front of element 0. For example, the above skip list looks like the following after adding the head node:

6

At this point, as long as you start from the h2 node, you can quickly find any element in the skip list.

For example, to find the element of 8, h2 first look to the right, hey, it is 6, which is smaller than 8, jump to the position of 6, and then look to the right, ah, it is 9, which is larger than 8, so it cannot be Jump over, jump one step down, jump to the 6th position on the 1st floor, look to the right, it is 9 again, can't jump over, then jump down one step, to the 6th floor on the 0th floor, since, to the 0th floor, It can only be traversed in sequence according to the linked list until it encounters 8. The whole process is as follows:

7

It can be seen that the whole process is jumping, jumping, jumping, so it is named - Jump Table.

The number of elements here is relatively small, and there may not be too much advantage. Imagine that if there are a lot of elements, every two elements will form an index upward, and every two indexes will form an index upward. Finally, it is similar to an index. A balanced binary tree is:

8

It can be seen that each lookup can reduce the search range by half, so the query time complexity of the skip table is O(log n).

However, it is impossible to use such a fully balanced skip list in practice, because, if you want to maintain the balanced feature, it is necessary to perform a rebalancing operation when inserting or deleting elements, which greatly reduces the efficiency. So, in general, we use randomness to decide whether an element or index should generate an index.

The third question: when is the index generated?

The best time is to insert an element, because the next step after inserting an element is to use the index immediately. Why do you say this? Because whether it is insertion, deletion or query, in fact, you have to go through the query to find that element before proceeding to the next step. To put it bluntly, no matter what the operation is, it must be queried, and the query must go through the index, and the index must be built first, and the index must be built when the element is inserted.

OK, I will use a step-by-step method to show you the complete process of creating a skip table:

  1. In the initial state, there is only one head node h0 (no, there is also a watermark for Brother Tong to read the source code, naughty ^^).

    9

  2. Insert an element 4, put it after h0, and randomly decide whether to form an index upwards, and the result is no index.

    10

  3. Insert an element 3, start searching from h0, the next element of h0 is 4, which is larger than 3, so 3 is placed between h0 and 4, and then asks whether to form an index, and randomly decides to form an index, at this time, 3 forms the index upward, and at the same time, h0 also forms the index h1 upward, and the result is as follows:

    11

  4. Insert an element 9, start searching from h1, go through h1->3->3->4 in sequence, but no position is found, and finally insert it after 4, and ask whether to form an index, and randomly decide that I want to form an index, and I want to form a 2-level index (up to 1 more than the current level), and then it becomes like this:

    12

  5. Next, elements 1 and 7 are inserted, neither of which is surprising nor indexed:

    13

  6. Insert element 6. According to the index, the search route is h2->h1->3->3->4. Hey, it is found that the next 4 is 7. Therefore, 6 is placed between 4 and 7. Then, decide to Don't form an index, I randomly decided to say that I want to form an index, and I also want to form a 2-level index, which is very troublesome at this time. When forming the element index of 6, it is necessary to modify the line 3->9, and also modify The line h2->9 generates the following results:

    14

  7. Later, elements 8 and 10 were inserted without any risk, and no index was generated. Therefore, the final result is as follows:

    15

It can be seen that the skip list is a very random data structure. Even if the elements are reinserted in the same order, the generated skip list may be completely different and willful, so I like the data structure of the skip list very much.

The fourth question: the above describes the process of inserting elements, what is the deletion process like?

In the deletion process, the element must be found first. However, there is a little difference, very small difference, which is difficult to describe. For example, to delete the element 6, can I go from h2->6->6->6 this Where is the path?

No, because from this path, after deleting the index 6 of the first layer, the line 3->9 cannot be repaired, so when deleting elements, you can only go through h2->h1->3->3->4 ->6 this path, and remember the last index of each layer on the way, in order to correctly repair the index of each layer after deleting the 6 element.

After removing the 6, it looks like this:

16

Hey, talking about this, I accidentally think of a small optimization item in the Java skip table ConcurrentSkipListMap. In ConcurrentSkipListMap, whether it is searching, inserting, or deleting, it all follows the same search path as delete. In fact, it can be simple To optimize it, you can take another path when inserting and searching.

17

Interested students can take a look at my source code analysis: ConcurrentSkipListMap source code analysis of the dead java collection

Well, we will explain the theoretical knowledge about the skip table here.

postscript

In this section, we fully and clearly show the whole process of searching, inserting, and deleting elements in the skip table through a step-by-step method. Have you got it? Can you beat the interviewer?

However, many students may say "Talk is cheap, Show me the code", OK, in the next section, I will show you the details of the skip table implementation in the form of code, and use the skip table to rewrite HashMap, see Next Part. .

> Follow Princess "Tongge Read Source Code" to unlock more source code, basic and architecture knowledge.

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

Guess you like

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