A dynamic bidirectional skip list storage structure and processing method for matrix data sets
By employing a dynamic bidirectional skip list storage structure for matrix data sets on the FPGA chip, the problem of low matrix decomposition efficiency is solved, enabling fast data retrieval and set operations, adapting to efficient calculation of the current flow Jacobian matrix, and reducing storage resource overhead.
Patent Information
- Authority / Receiving Office
- CN · China
- Patent Type
- Patents(China)
- Current Assignee / Owner
- STATE GRID SHANGHAI ENERGY INTERCONNECTION RES INST CO LTD
- Filing Date
- 2026-02-12
- Publication Date
- 2026-05-05
AI Technical Summary
The lack of effective set operation data structures on FPGA chips leads to low matrix decomposition efficiency, slow calculation speed, and a large amount of on-chip storage resources. Furthermore, existing methods generate memory bandwidth pressure and non-zero element padding under CPU architecture, affecting the efficiency of power flow calculation.
It adopts a dynamic bidirectional skip list storage structure for matrix data sets, including data fields and index fields. Data is linked through doubly linked lists and hierarchical linked lists, combined with a probability-driven indexing mechanism, to achieve fast data insertion, deletion and set operations.
Significantly improves data retrieval efficiency, adapts to FPGA chip hardware scenarios, supports efficient operation of the trend Jacobian matrix, reduces storage and computing resource overhead, and improves the efficiency of structural optimization before matrix decomposition.
Smart Images

Figure CN121704787B_ABST
Abstract
Description
Technical Field
[0001] This invention relates to the field of power flow calculation technology, and in particular to a dynamic bidirectional skip list storage structure and processing method for matrix data sets. Background Technology
[0002] Power flow calculation is a crucial analytical calculation for power systems. Based on the power system's wiring configuration, parameters, and operating conditions, it calculates the electrical quantities under steady-state operation, including active power, reactive power, and voltage distribution within the grid. Power flow calculation is also fundamental for system safety, stability, and reliability analysis, used to study various issues arising during system planning and operation. For planned power systems, power flow calculation can verify whether the proposed power system plan meets the requirements of various operating modes. For operating power systems, it can predict whether various load changes and network structure alterations will jeopardize system safety, whether the voltage of all buses in the system is within permissible ranges, whether various components in the system (lines, transformers, etc.) will experience overload, and what preventative measures should be taken in advance if overloads occur.
[0003] Currently, there is no effective set operation data structure on FPGA chips, resulting in low matrix decomposition efficiency, slow calculation speed, and excessive on-chip storage resource consumption. Existing patent document CN110968832A discloses a method and apparatus for processing data. This method requires mapping the original dataset into a data stream in the form of a unified dataset model. This process involves large-scale data serialization operations, which generates significant memory bandwidth pressure under CPU architecture. Furthermore, although a single calculation can obtain any combination of union, intersection, and difference sets, reducing the number of calculations, the complete intermediate results need to be stored in memory. For power flow matrix decomposition, large-scale matrix decomposition produces non-zero element padding, significantly increasing memory consumption. Summary of the Invention
[0004] The technical problem to be solved by the present invention is to provide a dynamic bidirectional skip list storage structure and processing method for matrix data sets, which can achieve a balance between storage and computation efficiency.
[0005] The technical solution adopted by this invention to solve its technical problem is as follows: A dynamic bidirectional skip list storage structure for a matrix data set is provided, including a data field portion at the bottom and an index field portion above the data field portion; the data field portion is used to store original data, and the index field portion is used to store index data; the data field portion includes multiple data unit structures at the same level, and the index field portion includes multiple levels, each level including multiple data unit structures; wherein, data unit structures within the same level are linked from smallest to largest through a doubly linked list, and data unit structures between different levels are linked to the same data range through inter-level linked lists.
[0006] The data unit structure includes:
[0007] The preceding pointer register is used to point to the address of the previous data in the same level;
[0008] The subsequent pointer register is used to point to the address of the next data in the same level;
[0009] Data registers are used to store data;
[0010] Hierarchical registers are used to store the index level at which the data resides;
[0011] The lower-level pointer register is used to point to the lower-level index of the current data;
[0012] The upper-level pointer register is used to point to the upper-level index of the current data.
[0013] The dynamic bidirectional skip list storage structure for the matrix data set also includes:
[0014] The head pointer register is used to point to the smallest index of the top-level data;
[0015] The tail pointer register is used to point to the maximum index of the top-level data;
[0016] The minimum value register is used to store the minimum value of all data in the skip list;
[0017] The maximum value register is used to store the maximum value of all data in the skip list.
[0018] The technical solution adopted by this invention to solve its technical problem is as follows: a matrix data set processing method is provided, which uses the above-mentioned dynamic bidirectional skip list storage structure of the matrix data set to build a bidirectional skip list. Specifically, the bidirectional skip list is built layer by layer starting from the data field. During the building process, the data elements are arranged in ascending order. Whenever a data is inserted into the bidirectional skip list, the insertion range is narrowed down from the highest level through bidirectional and hierarchical search, and the insertion position is determined at the bottom level where the data field is located. Whenever a data is inserted into the bidirectional skip list, a probability-driven method is used to randomly determine whether to build a multi-level upper-level index for the data.
[0019] Whenever a piece of data is inserted into the bidirectional skip list, the insertion range is narrowed down from the highest level through bidirectional and hierarchical search, and the insertion position is determined at the bottom level where the data field is located. Specifically, this includes hierarchical interval bidirectional search and bottom interval bidirectional search.
[0020] The hierarchical interval bidirectional search is completed within the index field. During the search, the data index pointed to by the head pointer register and the tail pointer register are received respectively. The search interval is divided into two parts, the head and the tail, and bidirectional search is performed to find the interval of the data level. The search is then performed layer by layer downwards until the index level is the lowest level of the index part.
[0021] The bidirectional search of the underlying interval is completed within the data domain. During the search, the interval found by the upper-level index is refined, and the bidirectional search process is executed to find the position where the data is finally inserted into the underlying data domain.
[0022] Whenever a piece of data is inserted into the bidirectional skip list, a probability-driven method is used to randomly determine whether to create a multi-level upper-level index for that data. Specifically, when the generated random number is less than the preset index creation probability, an adjacent upper-level index is created for the current data, and the process continues to determine whether to create a higher-level index until the index level exceeds the preset maximum index level.
[0023] When it is necessary to delete data from the bidirectional skip list, the specific steps include:
[0024] When the data to be deleted is located in the middle of the bidirectional skip list, retrieve the preceding and following index addresses of the data to be deleted, delete the index of the data to be deleted, and reconnect the index pointers of the two data before and after the data to be deleted. Retrieve the upper-level index address from the upper-level pointer register. If the upper-level index address is not empty, retrieve the preceding and following index addresses of the upper-level data index, connect the two data at the current level, and save the preceding and following index addresses to the preceding and following pointer registers of the two data respectively. Save the upper-level index of the current data to the upper-level pointer register.
[0025] When the data to be deleted is located at the left boundary of the bidirectional skip list, retrieve the subsequent data index address of the data to be deleted, set the subsequent data index address of the data to be deleted as the new left boundary, and update the minimum value register of the data unit structure in the data field part; retrieve the upper-level index address from the upper-level pointer register, and when the upper-level index address is not empty, retrieve the subsequent index address of the upper-level data index, set the preceding pointer register of the subsequent data as the new left boundary, and save the upper-level index of the current data to the upper-level pointer register;
[0026] When the data to be deleted is located at the right boundary of the bidirectional skip list, retrieve the preceding data index address of the data to be deleted, set the preceding data index address of the data to be deleted as the new right boundary, and update the maximum value register of the data unit structure in the data field part; retrieve the upper-level index address from the upper-level pointer register, and when the upper-level index address is not empty, retrieve the preceding index address of the upper-level data index, set the subsequent pointer register of the preceding data as the new right boundary, and save the upper-level index of the current data to the upper-level pointer register.
[0027] When it is necessary to delete all data existing in bidirectional skip list B from bidirectional skip list A, the specific steps include:
[0028] Filter the data in the bidirectional skip list B that belong to the current top-level interval of the bidirectional skip list A, and store them in the candidate data doubly linked list;
[0029] The candidate data in the doubly linked list is located layer by layer from the top-level index of the doubly skip list A until its specific interval in the bottom-level data field is determined.
[0030] Verify whether the data in the candidate data doubly linked list actually exists in the doubly skipped list A. If it does not exist, delete the data from the candidate data doubly linked list. If it exists, batch delete the data by merging adjacent candidate data intervals.
[0031] When it is necessary to merge data from bidirectional skip lists A and B into bidirectional skip list C, the specific steps are as follows: perform bidirectional search and merge on bidirectional skip lists A and B, and determine the merging order according to size and adjacency; during the merging process, unbind data with non-optimal indexes and connect the unbound indexes to the optimal index data of the bidirectional skip lists.
[0032] The bidirectional search and merging of the bidirectional skip list A and bidirectional skip list B includes forward search merging and reverse search merging;
[0033] The forward search merging specifically includes:
[0034] When the data pointed to by the head pointer register in the bidirectional skip list A is equal to the data pointed to by the head pointer register in the bidirectional skip list B, the index with the larger level of the two data is taken as the optimal index, and the data corresponding to the optimal index is written into the bidirectional skip list C;
[0035] When the data pointed to by the head pointer register in bidirectional skip list A is less than the data pointed to by the head pointer register in bidirectional skip list B, if the next data pointed to by the head pointer register in bidirectional skip list A is still less than the data pointed to by the head pointer register in bidirectional skip list B, then the index with the larger level between the data pointed to by the head pointer register in bidirectional skip list A and the next data is taken as the optimal index, and the data corresponding to the optimal index is written into bidirectional skip list C; if the next data pointed to by the head pointer register in bidirectional skip list A is greater than the data pointed to by the head pointer register in bidirectional skip list B, then the bidirectional skip list C is... The index with the larger level between the data pointed to by the head pointer register in skip list A and the data pointed to by the head pointer register in bidirectional skip list B is used as the optimal index, and the data corresponding to the optimal index is written into bidirectional skip list C; if the next data pointed to by the head pointer register in bidirectional skip list A is equal to the data pointed to by the head pointer register in bidirectional skip list B, then the index with the larger level between the data pointed to by the head pointer register in bidirectional skip list A and its next data, and the data pointed to by the head pointer register in bidirectional skip list B, is used as the optimal index, and the data corresponding to the optimal index is written into bidirectional skip list C;
[0036] When the data pointed to by the head pointer register in bidirectional skip list A is greater than the data pointed to by the head pointer register in bidirectional skip list B, if the next data pointed to by the head pointer register in bidirectional skip list B is still less than the data pointed to by the head pointer register in bidirectional skip list A, then the index with the larger level between the data pointed to by the head pointer register in bidirectional skip list B and the next data is taken as the optimal index, and the data corresponding to the optimal index is written into bidirectional skip list C; if the next data pointed to by the head pointer register in bidirectional skip list B is greater than the data pointed to by the head pointer register in bidirectional skip list A, then the bidirectional skip list C is... The index with the larger level between the data pointed to by the head pointer register in skip list A and the data pointed to by the head pointer register in bidirectional skip list B is used as the optimal index, and the data corresponding to the optimal index is written into bidirectional skip list C; if the next data pointed to by the head pointer register in bidirectional skip list B is equal to the data pointed to by the head pointer register in bidirectional skip list A, then the index with the larger level between the data pointed to by the head pointer register in bidirectional skip list B and its next data, and the data pointed to by the head pointer register in bidirectional skip list A, is used as the optimal index, and the data corresponding to the optimal index is written into bidirectional skip list C;
[0037] The reverse search merging specifically includes:
[0038] When the data pointed to by the tail pointer register in the bidirectional skip list A is equal to the data pointed to by the tail pointer register in the bidirectional skip list B, the index with the larger level of the two data is taken as the optimal index, and the data corresponding to the optimal index is written into the bidirectional skip list C;
[0039] When the data pointed to by the tail pointer register in bidirectional skip list A is greater than the data pointed to by the tail pointer register in bidirectional skip list B, if the preceding data of the data pointed to by the tail pointer register in bidirectional skip list A is still greater than the data pointed to by the tail pointer register in bidirectional skip list B, then the index with the larger level among the data pointed to by the head pointer register in bidirectional skip list A and the preceding data is taken as the optimal index, and the data corresponding to the optimal index is written into bidirectional skip list C; if the preceding data of the data pointed to by the tail pointer register in bidirectional skip list A is less than the data pointed to by the tail pointer register in bidirectional skip list B, then the index with the larger level among the data pointed to by the tail pointer register in bidirectional skip list A and the tail pointer register in bidirectional skip list B is taken as the optimal index, and the data corresponding to the optimal index is written into bidirectional skip list C; if the preceding data of the data pointed to by the tail pointer register in bidirectional skip list A is equal to the data pointed to by the tail pointer register in bidirectional skip list B, then the index with the larger level among the data pointed to by the head pointer register in bidirectional skip list A, the preceding data, and the data pointed to by the tail pointer register in bidirectional skip list B is taken as the optimal index, and the data corresponding to the optimal index is written into bidirectional skip list C.
[0040] When the data pointed to by the tail pointer register in bidirectional skip list A is less than the data pointed to by the tail pointer register in bidirectional skip list B, if the data preceding the data pointed to by the head pointer register in bidirectional skip list B is still greater than the data pointed to by the head pointer register in bidirectional skip list A, then the index with the larger level between the data pointed to by the head pointer register in bidirectional skip list B and its preceding data is taken as the optimal index, and the data corresponding to the optimal index is written into bidirectional skip list C; if the data preceding the data pointed to by the head pointer register in bidirectional skip list B is less than the data pointed to by the head pointer register in bidirectional skip list A, then the data is written into bidirectional skip list C. The index with the larger level between the data pointed to by the tail pointer register in bidirectional skip list A and the data pointed to by the tail pointer register in bidirectional skip list B is used as the optimal index, and the data corresponding to the optimal index is written into bidirectional skip list C; if the data preceding the data pointed to by the head pointer register in bidirectional skip list B is equal to the data pointed to by the head pointer register in bidirectional skip list A, then the index with the larger level between the data pointed to by the head pointer register in bidirectional skip list B and its preceding data, and the data pointed to by the head pointer register in bidirectional skip list A, is used as the optimal index, and the data corresponding to the optimal index is written into bidirectional skip list C.
[0041] During the merging process, data with non-optimal indexes is unbound, and the unbound indexes are connected to the optimal index data of the bidirectional skip list. Specifically, this includes:
[0042] During forward search merging, the upper-level index address of the non-optimal index data is read, and the preceding address of the upper-level index address is taken out and written into the preceding index queue. The preceding address is taken out from the preceding index queue and matched with the upper-level index of the optimal index data in the bidirectional skip list C layer by layer. When matching, the subsequent pointer register of the preceding address is pointed to the index of the optimal index data in the bidirectional skip list C, and the preceding pointer register of the index of the optimal index data in the bidirectional skip list C is pointed to the preceding address.
[0043] During reverse search merging, the upper-level index address of the non-optimal index data is read, and the subsequent address of the upper-level index address is taken out and written into the subsequent index queue. The subsequent address is taken out from the subsequent index queue and connected layer by layer with the upper-level index of the optimal index data in the bidirectional skip list C. During the connection, the preceding pointer register of the subsequent address is pointed to the index of the optimal index data in the bidirectional skip list C, and the subsequent pointer register of the index of the optimal index data in the bidirectional skip list C is pointed to the subsequent address.
[0044] The technical solution adopted by the present invention to solve its technical problem is: to provide an electronic device, including a memory, a processor, and a computer program stored in the memory and executable on the processor, wherein the processor executes the computer program to implement the steps of the above-mentioned matrix data set processing method.
[0045] The technical solution adopted by the present invention to solve its technical problem is: to provide a computer-readable storage medium on which a computer program is stored, wherein the computer program, when executed by a processor, implements the steps of the above-mentioned matrix data set processing method.
[0046] Beneficial effects
[0047] Due to the adoption of the above technical solutions, the present invention has the following advantages and positive effects compared with the prior art: The bidirectional skip list storage structure of the present invention, through the hierarchical design of data field and index field, links the same level of doubly linked lists and associates the same data ranges at different levels, which greatly improves the data retrieval efficiency, can quickly locate the range of target data insertion, deletion and set operation, can adapt to FPGA chip hardware implementation scenarios, can efficiently support the union, difference and other operations in the optimal reordering process of the flow Jacobian matrix, and quickly output row permutation vector and column permutation vector, significantly reducing on-chip storage and computing resource overhead.
[0048] To address the matrix decomposition requirements under the scale of big data in the power grid, this storage structure can reduce the data range search time and improve the efficiency of batch data processing through dynamic indexing and bidirectional search mechanisms. It provides an efficient hardware data operation foundation for structural optimization before matrix decomposition, effectively solving the problems of low matrix decomposition efficiency and slow calculation speed caused by traditional storage structures. Attached Figure Description
[0049] Figure 1 This is a schematic diagram of the dynamic bidirectional skip list storage structure of the matrix data set in the first embodiment of the present invention;
[0050] Figure 2 This is a schematic diagram of the data unit structure in the first embodiment of the present invention;
[0051] Figure 3 This is a flowchart of deleting data from skip list B from skip list A in the first embodiment of the present invention;
[0052] Figure 4 This is a schematic diagram of a doubly linked list of candidate data to be deleted in the first embodiment of the present invention;
[0053] Figure 5 This is a flowchart of the underlying bidirectional search process in the first embodiment of the present invention;
[0054] Figure 6This is a flowchart of skip list data deletion and index reconnection in the first embodiment of the present invention;
[0055] Figure 7 This is a schematic diagram of the search and merging of skip list A and skip list B in the first embodiment of the present invention;
[0056] Figure 8 This is a flowchart of the data merging type of skip list A and skip list B in the first embodiment of the present invention. Detailed Implementation
[0057] The present invention will be further illustrated below with reference to specific embodiments. It should be understood that these embodiments are for illustrative purposes only and are not intended to limit the scope of the invention. Furthermore, it should be understood that after reading the teachings of this invention, those skilled in the art can make various alterations or modifications to the invention, and these equivalent forms also fall within the scope defined by the appended claims.
[0058] The first embodiment of the present invention relates to a dynamic bidirectional skip list storage structure for matrix data sets, which can be used to efficiently implement the calculation process of merging, differencing, searching, and deleting datasets with non-zero rows and non-zero columns in the optimal reordering process of the Jacobian matrix. It can quickly calculate the row permutation vector P_row and column permutation vector P_col of the optimal reordering of the Jacobian matrix, saving the overhead of FPGA chip storage and computing resources.
[0059] like Figure 1 As shown, the dynamic bidirectional skip list storage structure of the matrix data set includes a data field at the bottom and an index field above the data field. The data field stores the original data, and the index field stores index data. The data field includes multiple data unit structures at the same level, and the index field includes multiple levels, each containing multiple data unit structures. The data field is level 0 of the skip list, and the index field has a level greater than 0. Data units within the same level are linked from smallest to largest using a doubly linked list, and data between different levels are linked through inter-level linked lists to access the same data range. Above the data field are all levels of the index field, which are logically higher than any single level of the data field.
[0060] The dynamic bidirectional skip list storage structure of the matrix data set also includes four auxiliary registers: two head pointer registers skip_head_ptr[15:0] and tail pointer register skip_rear_ptr[15:0], which point to the minimum and maximum indices of the top-level data unit, respectively; and two minimum value registers skip_min_data[31:0] and maximum value registers skip_max_data[31:0], which store the minimum and maximum values of all data in the bidirectional skip list structure, respectively.
[0061] like Figure 2 As shown, the data unit structure includes six core data registers. The preceding pointer register `prior[15:0]` and the following pointer register `next[15:0]` represent the addresses of the preceding and following data units or indices of the current level data, respectively. The data register `data[31:0]` is the data unit, storing the row and column numbers of non-zero elements in the flow Jacobian matrix. The level register `level[15:0]` represents the index level of the current data element, with the lowest level of raw data being level 0. The lower-level pointer register `down[15:0]` and the upper-level pointer register `up[15:0]` represent the addresses of the next and previous level data units or indices of the current data, respectively.
[0062] When constructing a bidirectional skip list using the aforementioned matrix data set dynamic bidirectional skip list storage structure, the construction begins layer by layer from level 0 (i.e., the data field). During construction, data elements are arranged in ascending order, including a data insertion step and a step to build upper-level indexes. In the data insertion step, whenever a piece of data is inserted into the bidirectional skip list, the insertion range is narrowed down from the top-level data through a bidirectional, hierarchical search, and the insertion position is determined at the bottom level (level 0) where the data field is located. After each piece of data is inserted, the upper-level index building step is initiated, which randomly determines whether to build multiple levels of upper-level indexes for that data using a probability-driven approach.
[0063] In the data insertion step, starting from the data pointed to by the head pointer register `skip_head_ptr` and the tail pointer register `skip_rear_ptr`, the search proceeds sequentially from both ends to the middle, and from higher-level indices to lower-level indices, level by level, down the search list to determine the range of the data to be inserted. This continues until the data search level reaches 0, thus determining the range of data to be inserted. Finally, the data range of level 0 is retrieved from the down pointer register of the level 1 data unit as the final start and end addresses, and the search for the target data insertion position is synchronously performed from both ends towards the middle.
[0064] In the step of building a higher-level index, the decision to build a higher-level index for a data element is determined probabilistically, with the index building probability being p. If the generated random number is less than the index building probability p, an adjacent higher-level index is built for the current data, and the process continues to determine whether to build a higher-level index. When the index level exceeds the preset maximum index level... If the index creation for that data is terminated, then N is the number of data items in the skip list.
[0065] The following is a detailed explanation of the process of inserting data into a double skip list storage structure.
[0066] This process receives the head pointer address (head_addr) and tail pointer address (rear_addr) of the skip list to be inserted, along with the data to be inserted (data). It simultaneously searches downwards from the highest-level data unit pointed to by both the head and tail pointers, level by level, until the insertion position at the lowest level is determined and the data is inserted. This process includes a first sub-process and a second sub-process.
[0067] First sub-process: Bidirectional lookup of the insertion position for the data:
[0068] The first sub-process consists of two parts: hierarchical interval bidirectional search and bottom-level interval bidirectional search. The hierarchical interval bidirectional search is performed within the index field of the skip list. During the search, it receives data indices pointed to by the head pointer register `head_addr` and the tail pointer register `rear_addr`, divides the search interval into two parts (head and tail), and performs a bidirectional search to find the interval at the level where the data `data` resides, searching downwards layer by layer until the index level is 1 (i.e., the lowest level of the index section). The bottom-level interval bidirectional search is performed within the skip list data field. During the search, the intervals found by the upper-level index are refined, and the bidirectional search process is executed to find the final insertion position of the data in the bottom-level data field.
[0069] The position identifier register `position_sig` indicates whether the data to be inserted, `data`, has been found. A value of 1 indicates that the `data` data unit already exists in the bidirectional skip list, and 0 indicates that `data` does not exist in the skip list. Initially, `position_sig` is set to ← 0. The data in the skip list is divided into two intervals, `before` and `latter`, denoted by `P1` and `P2`, respectively. The search is performed synchronously from both ends of intervals P1 to the middle, where `P1 = [before_data1, before_data2]` and `P2 = [latter_data1, later_data2]`. `before_data1` and `before_data2` represent the first and last data registers of the first half of interval P1, respectively, and `latter_data1` and `latter_data2` represent the first and last data values of the second half of interval P2, respectively.
[0070] When performing a bidirectional search of the hierarchical interval, the interval endpoints are allocated for the P1 interval: the first element of the skip list is saved from the skip list head pointer register head_addr to before_data1, i.e., before_data1←skip_list_data[head_addr], the subsequent index address of the first element is extracted and saved to the next_addr register, i.e., next_addr←skip_list_next[head_addr], the right endpoint data value of the P1 interval is saved to before_data2, i.e., before_data2←skip_list_data[next_addr], and the level of the index of the first element is saved to the current_level register, i.e., current_level←skip_list_level[head_addr]. To allocate interval endpoints for interval P2: save the tail element from the rear_addr pointer register to later_data2, i.e., later_data2←skip_list_data[rear_addr], retrieve the preceding index address of the tail element and save it to the prior_addr register, i.e., prior_addr←skip_list_prior[rear_addr], and save the left endpoint data value of interval P2 to later_data1, i.e., later_data1←skip_list_data[prior_addr].
[0071] Next, a bidirectional search of the hierarchical interval is performed to determine the interval where the data is located, including three cases.
[0072] (1) If data > before_data2 and data < latter_data1, then shrink the hierarchical interval, move the search area towards the middle of the index, update the head pointer and the tail pointer, and save the subsequent address next_addr of the P1 interval and the previous address prior_addr of the P2 interval to the head_addr and rear_addr address pointer registers respectively, i.e., head_addr ← next_addr, rear_addr ← prior_addr.
[0073] (2) If before_data1 < data < before_data2 and the current index level current_level > 0, then limit the search range to the P1 interval and move the search level down one level. Save the interval endpoint addresses of the next level to head_addr and rear_addr respectively, i.e., head_addr ← skip_list_down[head_addr], rear_addr ← skip_list_down[next_addr]. At the same time, save the interval addresses {head_addr, next_addr} of this level to the data interval register data_interval pointed to by the interval address pointer register data_interval_ptr, data_interval[data_interval_ptr] ← {head_addr, next_addr}, and update data_interval_ptr ← data_interval_ptr + 1.
[0074] (3) If latter_data1 < data < latter_data2 and the current index level current_level > 0, then limit the search range to the P2 interval and move the search level down one level. Save the interval endpoint addresses of the next level to head_addr and rear_addr respectively, i.e., head_addr ← skip_list_down[prior_addr], rear_addr ← skip_list_down[rear_addr]. At the same time, save the interval addresses {prior_addr, rear_addr} of this level to the data interval register data_interval pointed to by the interval address pointer register data_interval_ptr, data_interval[data_interval_ptr] ← {prior_addr, rear_addr}, and update data_interval_ptr ← data_interval_ptr + 1.
[0075] Repeat the above two-way search process for the hierarchical interval until the search down to the lower layer terminates when the index level is 1.
[0076] When the index level current_level = 0, perform a two-way search for the bottom interval, including six cases.
[0077] (1) If before_data2 < data < latter_data1, then shrink the interval range, use the subsequent address next_addr of the P1 interval and the previous address prior_addr of the P2 interval as the start and end addresses for the next search, move the address index towards the middle of the interval, and update head_addr ← next_addr, that is, rear_addr ← prior_addr.
[0078] (2) If data < before_data2, the data insertion point is before before_data2 in the P1 interval. Save the data index address before before_data2 to the insertion position address pointer register insert_position_addr, that is, insert_position_addr ← head_addr, and record the insertion direction register insert_direction, that is, insert_direction ← 1, where 1 indicates that the insertion direction is backward.
[0079] (3) If data < before_data1, the insertion point is the head of the skip list. Save the head address to the insertion position address pointer register insert_position_addr, that is, insert_position_addr ← head_addr, and record the insertion direction register insert_direction ← 0, where 0 indicates that the insertion direction is forward.
[0080] (4) If data > latter_data1, the insertion point is after latter_data1. Save the address where the latter_data1 is located to the insertion position address pointer register insert_position_addr, that is, insert_position_addr ← prior_addr, and record the insertion direction register insert_direction ← 1.
[0081] (5) If data > later_data2, save the subsequent address of later_data2 to the insertion position address pointer register insert_position_addr, that is, insert_position_addr←rear_addr, and record the insertion direction register insert_direction←1.
[0082] (6) If data=before_data2 or data=latter_data1, it means that the data data already exists in the current skip list. Due to the uniqueness of the data set, the invalid insertion signal indicator register invalid_insert_sig is set to be valid, i.e. invalid_insert_sig←1.
[0083] Repeat the above bidirectional search process for the underlying interval until the final insertion position is found or an invalid insertion signal is returned.
[0084] Second sub-process: Create an upper-level index for newly inserted data (data).
[0085] In this sub-process, a random number random is generated by the linear feedback shift register LFSR. When the random number random is less than the index establishment probability p, and the value in the index level counter this_data_level is less than or equal to the maximum index level max_level, the following steps are repeated to build the index layer by layer. Initially, the value in the index level counter this_data_level is 0.
[0086] First, update the current index level counter this_data_level←this_data_level+1, and assign values to the data data field, level, and down pointer register pointed to by the new insertion position index current_skip_addr, that is, skip_list_data[current_skip_addr]←data, skip_list_level[current_skip_addr]←this_data_level, skip_list_down[current_skip_addr]←insert_position_addr. Then, take out the current level interval pointed to by the interval index data_interval_ptr from the data interval register data_interval and save it to the data_interval_addr[31:0] register, that is, data_interval_addr←data_interval[data_interval_ptr], update the interval index data_interval_ptr←data_interval_ptr-1, and there are three cases according to the size of the data value and the interval endpoints.
[0087] (1) If the data value is in the middle of the skip list, skip_min_data < data < skip_max_data of the skip list, save the values in the current level interval register data_interval to the prior and next registers pointed to by the new insertion position index current_skip_addr respectively, that is, skip_list_prior[current_skip_addr]←data_interval[31:16], skip_list_next[current_skip_addr]←data_interval[15:0].
[0088] (2) If data < skip_min_data of the skip list, the index is at the left boundary of the data at this level, update the prior and next registers of the current data index, that is, skip_list_prior[current_skip_addr]←null, skip_list_next[current_skip_addr]←data_interval[31:16].
[0089] (3) If data > skip list maximum value skip_max_data, the index is at the right boundary of the data at this level. Update the prior and next registers of the current data index, i.e. skip_list_prior[current_skip_addr]←data_interval[15:0], skip_list_next[current_skip_addr]←null.
[0090] Finally, update the skip list count counter skip_list_num ← skip_list_num + 1.
[0091] Repeat the above process until the newly inserted data has completed the creation of the high-level index.
[0092] In this implementation, when inserting a data flow into a bidirectional skip list, firstly, the first sub-flow is executed to search for the insertion position of the data `data` in a bidirectional hierarchical manner. The insertion position `insert_position_addr` and the invalid insertion signal indicator register `invalid_insert_sig` are returned. If `invalid_insert_sig` = 1, the data already exists in the skip list, and no insertion flow is needed. If `invalid_insert_sig` = 0, the data field `data`, the level `level`, and the lower-level index `down` register pointed to by `current_skip_addr` are assigned values, i.e., `skip_list_data[current_skip_addr]←data`, `skip_list_level[current_skip_addr]←0`, `skip_list_down[current_skip_addr]←null`. Based on the relationship between the `data` value and the interval endpoints, there are three cases:
[0093] (1) If the data value is between the extreme values at both ends of the skip list, skip_min_data < data < skip_max_data, then insert data after the address pointer register insert_position_addr of the insertion position. The address of the newly inserted data is saved in the address unit pointed to by current_skip_addr. The original subsequent index address of the insertion point is retrieved and saved to temp_next, and the index address of the subsequent point is updated to current_skip_addr, that is, skip_list_next[next] ← current_skip_addr. The previous data of the original subsequent index address temp_next points to the newly inserted address current_skip_addr, skip_list_prior[temp_next] ← current_skip_addr.
[0094] (2) If the data value < the skip list minimum value skip_min_data, then insert data at the skip list head. The previous node of the index insert_position_addr at the current insertion position points to the newly inserted address current_skip_addr, that is, skip_list_prior[insert_position_addr] ← current_skip_addr. The subsequent index of the newly inserted address points to the current insertion position, that is, skip_list_next[current_skip_addr] ← insert_position_addr. Update the previous index prior register of the newly inserted data, that is, skip_list_prior[current_skip_addr] ← null. At the same time, update the skip list minimum value and the minimum value index register, that is, skip_min_data ← data, skip_min_ptr ← current_skip_addr.
[0095] (3) If the value of data > the maximum value of the skip list, skip_max_data, then the insertion position is at the end of the skip list. The subsequent node of the current insertion position index insert_position_addr is set to the newly inserted address current_skip_addr, i.e., skip_list_next[insert_position_addr]←current_skip_addr. The preceding index of the newly inserted address is set to the current insertion position, i.e., skip_list_prior[current_skip_addr]←insert_position_addr. The next register of the newly inserted data is updated, i.e., skip_list_next[current_skip_addr]←null. Simultaneously, the maximum value and maximum value index register of the skip list are updated, i.e., skip_max_data←data, skip_max_ptr←current_skip_addr.
[0096] Then, update the index of the newly inserted address current_skip_addr ← current_skip_addr + 1.
[0097] Finally, the second sub-process is executed to build the upper-level index for the newly inserted data.
[0098] When data needs to be deleted from the skip list, the first sub-process is executed: The position of the data `data` in skip list A is found, and the `invalid_insert_sig` signal indicating whether `data` is in the skip list is returned. If `invalid_insert_sig` = 0, the data `data` is not in the skip list; if `invalid_insert_sig` = 1, the data `data` exists in the skip list. In this case, the data pointed to by `insert_position_addr` is deleted. Then, it is determined whether `data` has a higher-level index. All higher-level indexes are deleted, and the skip list is updated. Specifically, this includes the following three cases:
[0099] (1) If the minimum value of the skip list skip_min_data < the data data < the maximum value of the skip list skip_max_data, it means that the data data is in the middle of the bidirectional skip list. First, retrieve the index address of the preceding data and the index address of the following data of the data to be deleted pointed to by insert_position_addr, and save them to the prior_data_addr and next_data_addr registers respectively, that is, prior_data_addr←skip_list_prior[insert_position_addr], next_data_addr←skip_list_next[insert_position_addr]. Then, the index of the data `data` is deleted, and the index pointers of the two data points before and after `data` are reconnected. The preceding index `prior_data_addr` and the following index `next_data_addr` are saved to the `prior` and `next` address index registers, respectively, i.e., `skip_list_next[prior_data_addr]←next_data_addr` and `skip_list_prior[next_data_addr]←prior_data_addr`. The skip list data count counter `skip_list_num` is updated to `skip_list_num` - 1. Next, it is determined whether the data `data` has a higher-level index, i.e., the address of the higher-level index is retrieved from the `up` pointer register and saved to the `up_level_addr` register, i.e., `up_level_addr←skip_list_up[insert_position_addr]`. When the higher-level index `up_level_addr` of the data `data` is not null, the following process is repeated to delete all higher-level indices of the data `data` in turn.
[0100] Retrieve the preceding and following index addresses of the upper-level data index and save them to the `prior_data_addr` and `next_data_addr` registers respectively, i.e., `prior_data_addr ← skip_list_prior[up_level_addr]`, `next_data_addr ← skip_list_next[up_level_addr]`. Then, concatenate the preceding and following data at the current level, saving the preceding index `prior_data_addr` and the following index `next_data_addr` to the `prior` and `next` address index registers respectively, i.e., `skip_list_next[prior_data_addr] ← next_data_addr`, `skip_list_prior[next_data_addr] ← prior_data_addr`. Save the upper-level index of the current data to the up_level_addr register, i.e., up_level_addr←skip_list_up[up_level_addr], update the skip list data count counter skip_list_num←skip_list_num-1, and repeat the above steps until the value in the skip list data count counter skip_list_num is 0.
[0101] (2) If the data data = the minimum value of the skip list skip_min_data, then the data data is the left boundary of the skip list. Save the subsequent data index address of the data pointed to by insert_position_addr to next_data_addr, that is, next_data_addr←skip_list_next[insert_position_addr]. Set the previous address register of the data pointed to by next_data_addr to the new left boundary, that is, skip_list_prior[next_data_addr]←null. Update the skip list data count counter skip_list_num←skip_list_num-1. Update the minimum value skip_min_data and the minimum value pointer skip_min_ptr of the bottom-level data field, that is, skip_min_data←skip_list_data[next_data_addr], skip_min_ptr←next_data_addr. Then, it checks if the current data has a higher-level index. It retrieves the address of the higher-level index from the `up` register and saves it to the `up_level_addr` register, i.e., `up_level_addr ← skip_list_up [insert_position_addr]`. When the higher-level index `up_level_addr` of the data `data` is not null, the following process is repeated to delete all higher-level indices of the data `data` in turn.
[0102] Save the subsequent index of the upper-level data index to the next_data_addr register, i.e., next_data_addr ← skip_list_next[up_level_addr]. Set the preceding register of the subsequent data to the new left boundary, i.e., skip_list_prior[next_data_addr] ← null. Save the upper-level index of the current data to the up_level_addr register, i.e., up_level_addr ← skip_list_up[up_level_addr], and update the skip list data count counter skip_list_num ← skip_list_num - 1.
[0103] (3) If the data data = the maximum value of the skip list skip list skip_max_data, then the data data is the right boundary of the skip list. Save the index address of the preceding data of the data pointed to by insert_position_addr to prior_data_addr, that is, prior_data_addr←skip_list_prior[insert_position_addr]. Set the next address register of the data pointed to by prior_data_addr to the new right boundary, that is, skip_list_next[prior_data_addr]←null. Update the skip list data count counter skip_list_num←skip_list_num-1. Update the maximum value skip_max_data and the maximum value pointer skip_max_ptr of the bottom-level data field, that is, skip_max_data←skip_list_data[prior_data_addr], skip_max_ptr←prior_data_addr. Then, it checks if the current data has a higher-level index. It retrieves the address of the higher-level index from the `up` register and saves it to the `up_level_addr` register, i.e., `up_level_addr ← skip_list_up [insert_position_addr]`. When the higher-level index `up_level_addr` of the data `data` is not null, the following loop process is repeated to delete all higher-level indices of the data `data` in turn.
[0104] Save the preceding index of the upper-level data index to the prior_data_addr register, i.e., prior_data_addr ← skip_list_prior[up_level_addr]. Set the next register of the preceding data to the new right boundary, skip_list_next[prior_data_addr] ← null. Save the upper-level index of the current data to the up_level_addr register, i.e., up_level_addr ← skip_list_up[up_level_addr], and update the skip list data count counter skip_list_num ← skip_list_num - 1.
[0105] When it is necessary to delete all data existing in bidirectional skip list B from bidirectional skip list A, this embodiment designs a batch deletion strategy. Specifically, the batch deletion strategy is as follows: filter data in bidirectional skip list B that belongs to the current top-level interval of bidirectional skip list A, and store them in a candidate doubly linked list; locate all data in the candidate doubly linked list layer by layer downwards from the top-level index of bidirectional skip list A until its specific interval in the bottom-level data field is determined; verify whether the data in the candidate doubly linked list actually exists in bidirectional skip list A. If it does not exist, delete the data from the candidate doubly linked list; if it exists, achieve batch deletion of the data by merging adjacent candidate data intervals.
[0106] Figure 3 This is a flowchart for deleting data from skip list B from skip list A. The data in skip list B is stored in the candidate register. First, it is determined whether the data in the candidate register appears in skip list A. Then, the level and interval endpoints of each data point are recorded. The dependency relationship between the endpoints of two adjacent candidate data intervals is determined. Finally, several data interval endpoints that meet the conditions are connected to complete the batch deletion of data from skip list B.
[0107] Figure 4 The candidate data to be deleted is a doubly linked list. Each data unit consists of 5 data field registers: candidate_data[31:0] is the candidate data value register, candidate_prior[15:0] and candidate_next[15:0] represent the previous and subsequent data index addresses of the candidate data, respectively, candidate_interval_level[15:0] represents the current interval level of the candidate data, and candidate_interval_addr[15:0] represents the interval boundary index address of the candidate data. A singly linked list is used to point to the data interval interval. Each unit consists of two data fields: the interval_addr[15:0] register storing the interval boundary and the interval_down[15:0] pointer pointing to the next interval endpoint. This singly linked list stores the left and right endpoint addresses of the interval in sequence. candidate_head_addr represents the head pointer pointing to the first element of the doubly linked list of candidate data.
[0108] The start_ptr and end_ptr pointers point to the first and last elements of the candidate doubly linked list, respectively. The search starts bidirectionally from the head and tail of the list, checking whether the data pointed to by start_ptr and end_ptr is the data of the current skip list A at that level. If so, the address of the data range is saved, and then the start_ptr and end_ptr pointers move towards the middle of the list to continue the search.
[0109] Third sub-process: Determine the hierarchical range to which the data belongs.
[0110] This sub-process is responsible for calculating the hierarchical interval to which the data pointed to by `data_addr` belongs. It retrieves the data currently pointed to by `data_addr` from the candidate data linked list's `data` register and saves it to `data` (i.e., `data←candidate_data[data_addr]`), comparing it with the endpoints of the intervals at both ends of this data. The hierarchical level of this data is then saved to `data_level` (i.e., `data_level←candidate_level[data_addr]`). If the current hierarchical level `data_level` = 0, then `data` is already at the bottom of the skip list, and no further judgment is needed. If the current hierarchical level `data_level` > 0, the following process is executed to find the hierarchical interval to which `data` belongs.
[0111] Save the left endpoint index of the current level interval of data to the left_addr register, i.e., left_addr ← candidate_interval_addr[data_addr]. Retrieve the left endpoint address of the interval from the interval_addr register and save it to the before_addr register, i.e., before_addr ← interval_addr[left_addr]. Save the right endpoint index of the interval to the right_addr register, i.e., right_addr ← interval_down[left_addr]. Retrieve the right endpoint address of the interval and save it to the later_addr register, i.e., later_addr ← interval_addr[right_addr].
[0112] Then, retrieve the left endpoint address `new_level_left` and right endpoint address `new_level_right` of the next level interval corresponding to the current level interval from skip list A, i.e., `new_level_left←skip_list_down[before_addr]`, `new_level_right←skip_list_down[latter_addr]`. Save the left and right endpoint values of the next level interval to the `before_data` and `latter_data` registers, i.e., `before_data←skip_list_data[new_level_left]`, `latter_data←skip_list_data[new_level_right]`. Next, when the value of `data` > `latter_data`, repeat the following process to search for the interval to which `data` belongs in the new level.
[0113] The search interval is shifted forward, and the address of the right endpoint of the new level interval is saved to the left endpoint index, i.e., new_level_left←new_level_right. The right endpoint index of the interval is updated, i.e., new_level_right←skip_list_next[new_level_right]. The left and right endpoint values of the interval, before_data and later_data, are updated, i.e., before_data←skip_list_data[new_level_left] and later_data←skip_list_data[new_level_right].
[0114] Once the underlying interval containing the data is located, the fourth sub-process is executed to determine whether the data is in skip list A. If the data is in skip list A, the addresses of the preceding and following data are saved; otherwise, the data is deleted from the candidate doubly linked list. Ultimately, the candidate list contains only data that exists in skip list A.
[0115] Finally, determine whether the data is within the hierarchical range, including three cases.
[0116] (1) If data > before_data in skip list A and data < later_data in skip list A, then data is within the level interval. Save the index addresses of the two endpoints of the level interval to the interval_addr register, i.e., interval_addr[left_addr]←new_level_left, interval_addr[right_addr]←new_level_right. Update the level register of the current candidate data, i.e., candidate_level[data_addr]←candidate_levle[data_addr]-1.
[0117] (2) If data = before_data, where data is the left boundary of the interval, the lowest level interval is located directly through the level index. The head pointer of the candidate data list, start_ptr, is moved one position backward, i.e., start_ptr←candidate_next[data_addr]. The level of the left endpoint of the current interval of skip list A is saved to the before_data_level register, i.e., before_data_level←skip_list_level[new_level_left]. When the level of the left boundary data, before_data_level>0, the following loop process is executed to continue searching down to the next level.
[0118] Save the next level index address of the left endpoint of the current level interval to the before_data_down register, i.e., before_data_down←skip_list_down[new_level_left]. Save the level of the left endpoint of the new level interval to the before_data_level register, i.e., before_data_level←skip_list_level[before_data_down]. Update the left endpoint of the current level, new_level_left←before_data_down.
[0119] When the above loop process ends, the left interval endpoint has been searched to the bottom layer of skip list A. The addresses of the data before and after the left interval endpoint are saved to the interval_before_addr and interval_latter_addr registers, respectively: interval_before_addr ← skip_list_prior[before_data_down], interval_latter_addr ← skip_list_next[before_data_down]. Finally, the index addresses of the left and right endpoints of the bottom-layer interval are saved to the interval_addr linked list of the candidate data, respectively: interval_addr[left_addr] ← interval_before_addr, interval_addr[right_addr] ← interval_latter_addr. The level of the current candidate data is updated, i.e., candidate_level[data_addr] ← 0.
[0120] (3) If data = later_addr, then data is the right boundary of the interval. Directly locate the lowest level interval through the hierarchical index, move the end_ptr of the candidate data linked list forward by one position, i.e., end_ptr←candidate_prior[data_addr], save the level of the right endpoint of the current interval of skip list A to the later_data_level register, i.e., later_data_level←skip_list_level[new_level_right], when the level of the right boundary data later_data_level>0, execute the following loop process to continue searching down to the next level.
[0121] Save the next level index address of the right endpoint of the current level interval to the `latter_data_down` register, i.e., `latter_data_down←skip_list_down[new_level_right]`. Save the level of the right endpoint of the new level interval to the `latter_data_level` register, i.e., `latter_data_level←skip_list_level[latter_data_down]`. Update the right endpoint of the current level, `new_level_right←latter_data_down`.
[0122] When the above loop process ends, the endpoints of the right interval have been searched to the bottom layer of skip list A. The addresses of the data before and after the endpoints of the right interval are saved to the `interval_before_addr` and `interval_latter_addr` registers, respectively: `interval_before_addr←skip_list_prior[latter_data_down]`, `interval_latter_addr←skip_list_next[latter_data_down]`. Finally, the index addresses of the left and right endpoints of the bottom-level interval are saved to the `interval_addr` linked list of the candidate data, respectively: `interval_addr[left_addr]←interval_before_addr`, `interval_addr[right_addr]←interval_latter_addr`. The level of the current candidate data is updated: `candidate_level[data_addr]←0`.
[0123] Fourth sub-process: Candidate data linked list calculation process.
[0124] This sub-process is responsible for calculating the set of all data in skip list B that fall within a certain top-level data range of skip list A. The `upper_limit` register is set to the upper limit of a certain top-level range in skip list A, and the `current_data_addr` address index points to the current data address in skip list B to be checked. The current data is retrieved from skip list B and saved to `data`, i.e., `data←skip_list_data[current_data_addr]`. First, an empty candidate data linked list is created. `current_candidate_addr` represents the address of the candidate data to be written, and `candidate_head_addr` is the head address of the candidate data linked list. The head address of the candidate data linked list, `candidate_head_addr`, is set to point to the address of the data to be written, `current_candidate_addr`, and `candidate_head[candidate_head_addr]←current_candidate_addr`. The preceding index of the newly written data address is set to point to the head address of the candidate data linked list, i.e., `candidate_prior[current_candidate_addr]←candidate_head_addr`. When data < upper_limit of the top-level interval of skip list A, the following loop process is executed.
[0125] Store `data` in the candidate data linked list, saving the `data` value to the address of the currently to-be-written data, `current_candidate_addr`, i.e., `candidate_data[current_candidate_addr]←data`. Save the original level `original_level` of skip list A to the `interval_level` register of the candidate data linked list, i.e., `candidate_interval_level[current_candidate_addr]←original_level`. Connect the preceding `prior` and following `next` index addresses pointed to by `current_candidate_addr`, i.e., `candidate_next[current_candidate_addr]←current_candidate_addr+1`, `candidate_prior[current_candidate_addr+1]←current_candidate_addr`. Save the address of the currently newly inserted data, `current_candidate_addr`, to the candidate data interval index register, i.e., `candidate_interval_addr[current_candidate_addr]←current_candidate_addr`. Save the left and right endpoint addresses of the original hierarchical interval of skip list A, `original_prior_addr` and `original_next_addr`, to the candidate data linked list `interval_addr`, i.e., `interval_addr[current_interval_addr]←original_prior_addr`, `interval_addr[current_interval_addr+1]←original_next_addr`. Update the `interval_down` register of the candidate data to point to the right boundary of the interval, i.e., `interval_down[current_interval_addr]←current_interval_addr+1`. Set the right endpoint of the interval in the `interval_down` register of the candidate data to the boundary, i.e., `interval_down[current_interval_addr+1]←null`.Update the current candidate data interval address current_interval_addr ← current_interval_add+2, and update the current candidate data newly inserted address current_candidate_addr ← current_candidate_addr+2.
[0126] At this point, the insertion of one data into the candidate list is complete. Then, the data is shifted one position to the right for evaluation. The subsequent index and data value of the current data in skip list B are saved to the next_addr and data registers, respectively: next_addr ← skip_list_next[current_data_addr], data ← skip_list_data[next_addr]. The current data index in skip list B is updated: current_data_addr ← next_addr. The counter for the number of data in the candidate list, candidate_num ← candidate_num + 1, is also updated.
[0127] At this point, all data in skip list B that falls within the range of skip list A has been saved to the candidate data linked list.
[0128] Fifth sub-process: Underlying bidirectional search process.
[0129] like Figure 5 As shown, this subprocess is responsible for bidirectionally searching for data at the underlying level.
[0130] First, the first sub-process is executed once, including two cases.
[0131] (1) If the invalid data signal invalid_insert_sig=1, then the data exists in the skip list A. Save the left and right interval index addresses of the data to the new_level_left and new_level_right registers respectively, i.e. new_level_left←skip_list_prior[insert_position_addr], new_level_right←skip_list_next[insert_position_addr].
[0132] (2) If the invalid data signal invalid_insert_sig=0, then data is not in skip list A, and data is deleted from the candidate list. Save the previous and next data index addresses from the candidate data to prior_addr and next_addr, that is, prior_addr←candidate_prior[data_addr], next_addr←candidate_next[data_addr]. There are three cases: 1) If prior_addr≠candidate_head_addr, and next_addr≠null, then connect the candidate data indices pointed to by prior_addr and next_addr in the candidate list, that is, candidate_next[prior_addr]←next_addr, candidate_prior[next_addr]←prior_addr. 2) If prior_addr equals the head address of the candidate list (candidate_head_addr), then the head pointer is moved to the address following the current data (next_addr), i.e., candidate_head[candidate_head_addr]←next_addr. The prior register of subsequent data is then moved to the head address (candidate_head_addr), i.e., candidate_prior[next_addr]←candidate_head_addr. 3) If next_addr equals null, the index address in the next register of the preceding data is deleted, i.e., candidate_next[prior_addr]←null.
[0133] The sixth sub-process: Delete the data in the candidate list to be deleted from the skip list A.
[0134] Once all candidate data in the candidate list has been added, the data level is 0. By updating the previous and subsequent index connections in skip list A, a batch deletion operation is performed on the candidate data. Figure 6The flowchart for skip list data deletion and index reconnection is provided. Two auxiliary pointers, `start_ptr` and `end_ptr`, are used to determine whether to connect the preceding and following addresses of a candidate data `data`. `start_ptr` points to the currently deleted data `data` in the candidate data linked list, and `end_ptr` points to the adjacent data following `data`. If the preceding data's `start_latter_data` is less than or equal to the following data's `end_before_data`, then the two data points pointed to by `start_ptr` and `end_ptr` are not adjacent in skip list A, and the addresses of the endpoints of the intervals corresponding to `start_ptr` and `end_ptr` are directly connected. If the preceding data's `start_latter_data` is greater than the following data's `end_before_data`, then the two data points pointed to by `start_ptr` and `end_ptr` are adjacent in skip list A, and `end_ptr` is shifted one data point to the right to continue the judgment. If the first non-adjacent data is encountered, the maximum interval range indices corresponding to `start_ptr` and `end_ptr` are connected. This process is repeated until all data in the candidate data linked list has been judged.
[0135] The `candidate_left` parameter represents the number of remaining data items in the candidate list after data deletion. Initially, the total number of data items in the candidate list, `candidate_num`, is stored in `candidate_left←candidate_num`, and `start_ptr` and `end_ptr` point to the first two data items in the list. When the number of remaining data items in the candidate list, `candidate_left`, is greater than 0, the following loop process is repeated to delete the candidate data in the list in batches.
[0136] First, calculate interval 1. Retrieve the left endpoint linked list address of the data pointed to by `start_ptr` from the candidate data interval address index register `candidate_interval_addr` and save it to the `first_before_interval` register, i.e., `first_before_interval ← candidate_interval_addr[start_ptr]`. Next, save the left endpoint index of the interval to `first_before_addr`, i.e., `first_before_addr ← interval_addr[first_before_interval]`. Then, retrieve the right endpoint linked list address of the interval and save it to `first_latter_interval`, i.e., `first_latter_interval ← interval_down[first_before_interval]`. Finally, save the right endpoint index of the interval to `first_latter_addr`, i.e., `first_latter_addr ← interval_addr[first_latter_interval]`. Finally, the left and right endpoint values of the first data interval are saved to the first_before_data and first_latter_data registers respectively, i.e., first_before_data←skip_list_data[first_before_addr], first_latter_data←skip_list_data[first_latter_addr].
[0137] Next, calculate interval 2, retrieve the address of the left endpoint of the linked list pointing to the data in end_ptr, and save it to the second_before_interval register, i.e., second_before_interval←candidate_interval_addr[end_ptr]. Then, save the index of the left endpoint of the interval to second_before_addr, i.e., second_before_addr←interval_addr[second_before_interval]. Retrieve the address of the right endpoint of the interval and save it to second_latter_interval, i.e., second_latter_interval←interval_down[second_before_interval]. Finally, save the index of the right endpoint of the interval to second_latter_addr, i.e., second_latter_addr←interval_addr[second_latter_interval]. Finally, the left and right endpoint values of the second data interval are saved to the second_before_data and second_latter_data registers respectively, i.e., second_before_data←skip_list_data[second_before_addr], second_latter_data←skip_list_data[second_latter_addr].
[0138] Compare the endpoint values of interval 1 and interval 2, and there are two cases.
[0139] (1) If the right endpoint value of interval 1, first_latter_data, is less than or equal to the left endpoint value of interval 2, second_before_data, then the data pointed to by start_ptr and end_ptr are not adjacent. The left and right endpoint address indices of interval 1, first_before_addr and first_latter_addr, are saved to the prior and next registers of skip list A, respectively, i.e., skip_list_prior[first_latter_addr]←first_before_addr, skip_list_next[first_before_addr]←first_latter_addr. Then it is determined whether the first data pointed to by start_ptr has a higher-level index. If there is a higher-level index, the process of deleting data from the skip list is executed to delete all higher-level indices. Finally, the address index register of the data to be deleted is updated to move the candidate data to the right side of the linked list, i.e., start_ptr←end_ptr, end_ptr←candidate_next[end_ptr].
[0140] (2) If the right endpoint value of interval 1, first_latter_data, is greater than the left endpoint value of interval 2, second_before_data, then the data pointed to by start_ptr and end_ptr are adjacent. It is necessary to determine whether there is still adjacent data in the subsequent linked list of end_ptr. Update the index address of the subsequent data of end_ptr, that is, end_ptr←candidate_next[end_ptr]. Take the address of the left endpoint linked list of the data pointed to by end_ptr from the candidate data interval address index register candidate_interval_addr and save it to the new_before_interval register, that is, new_before_interval←candidate_interval_addr[end_ptr]. Then save the left endpoint index of the interval to new_before_addr, that is, new_before_addr←interval_addr[new_before_interval]. Then, the left endpoint value of the subsequent data interval is saved to the new_before_data register, i.e., new_before_data←skip_list_data[new_before_addr]. Finally, the address of the right endpoint linked list of the interval is retrieved and saved to new_latter_interval, i.e., new_latter_interval←interval_down[new_before_interval]. When the subsequent index end_ptr ≠ null, and the right endpoint value of interval 2, second_latter_data, is greater than the left endpoint value of the subsequent interval, new_before_data, the following loop process is executed.
[0141] Save the right endpoint index of the subsequent interval to new_latter_addr, i.e., new_latter_addr←interval_addr[new_latter_interval]. Next, save the right endpoint value of the subsequent data interval to the new_latter_data register, i.e., new_latter_data←skip_list_data[new_latter_addr]. Update the subsequent data index address of end_ptr, i.e., end_ptr←candidate_next[end_ptr], and update the right endpoint value of interval 2 with the right endpoint value of the new subsequent interval, second_latter_data←new_latter_data. Finally, update the linked list address of the left endpoint of the interval, new_before_interval←candidate_interval_addr[end_ptr], and at the same time update the index of the left endpoint of the interval, new_before_addr and the value of the left endpoint, new_before_data, that is, new_before_addr←interval_addr[new_before_interval], new_before_data←skip_list_data[new_before_addr].
[0142] After the above loop process completes, `second_latter_data` stores the right endpoint value of interval 2 to be connected with the left endpoint of interval 1 pointed to by `start_ptr`. Then, all intermediate adjacent data are deleted in batches. The `next` index of the data pointed to by `start_ptr` is set to `second_latter_data`, i.e., `skip_list_next[first_before_addr]←second_latter_data`, and the `prior` index of the data pointed to by `second_latter_data` is set to the left endpoint of interval 1, i.e., `skip_list_prior[second_latter_data]←first_before_addr`. At the same time, the process of deleting data `data` from the skip list is executed. It is checked whether the adjacent data to be deleted has a higher-level index. If so, all higher-level indexes are deleted.
[0143] Finally, update the index of the data to be deleted in the candidate list to point to the next data to be deleted, i.e., start_ptr←end_ptr, end_ptr←candidate_next[end_ptr].
[0144] The following is a detailed explanation of the process of deleting skip list B from skip list A.
[0145] The top-level interval of skip list A is used as the judgment interval in turn. Data in skip list B that meet the interval are stored into the candidate list in turn. Then, the fifth sub-process is executed once to filter the data in the candidate list that falls into the interval from skip list A, until all the top-level intervals of skip list A have been searched.
[0146] The `delete_num` counter represents the number of data items deleted from skip list B. Initially, `delete_num` ← 0. The number of data items in skip list B is saved to the `skip_num_B` counter from the head address `head_B_addr` of skip list B, i.e., `skip_num_B ← skip_list_num_B[head_B_addr]`. The addresses of the first data items in skip list A and skip list B are saved to `skip_A_addr` and `skip_B_addr` respectively, i.e., `skip_A_addr ← skip_head_A_addr[head_A_addr]` and `skip_B_addr ← skip_head_B_addr[head_B_addr]`. The preceding index, following index, and level of the first element of skip list A are saved to the registers A_prior, A_next, and A_level, respectively, i.e., A_prior ← skip_list_A_prior[skip_A_addr], A_next ← skip_list_A_next[skip_A_addr], and A_level ← skip_list_A_level[skip_A_addr]. skip_min_A_ptr and skip_min_B_ptr are the indices pointing to the minimum values at the bottom levels of skip lists A and B, respectively. The right endpoint of the top-level interval of skip list A is used as the upper limit value (upper_limit_A) for calculating the candidate list, i.e., upper_limit_A ← skip_list_A_data[A_next]. The current data address (current_data_addr) of skip list B is set to the minimum value of skip list B, i.e., current_data_addr ← skip_min_B_ptr. When the index A_next of subsequent data in skip list A is not null, and the number of deleted data in skip list B is less than or equal to the total number of data in skip list B, skip_num_B, the following loop process is executed.
[0147] First, execute the fourth sub-process once to calculate the data falling within a top-level interval in skip list A and save it to the candidate list. Then, for i=1 to the number of data in the candidate list, candidate_num, execute the third sub-process to sequentially determine the endpoints of the intervals for all data in the candidate list from the higher-level index to the lower-level index, until the lowest level. Next, execute the sixth sub-process to delete the data and its upper-level index from the candidate list in skip list A. Finally, move the subsequent index A_next in skip list A to the next interval (A_next←skip_list_A_next[A_next]), and update the count of deleted data in skip list B (delete_num←delete_num+candidate_num), where candidate_num is the number of data in the candidate list.
[0148] This concludes the above process, completing the workflow of batch deleting data from skip list B from skip list A.
[0149] When it is necessary to merge data from bidirectional skip lists A and B into bidirectional skip list C, this embodiment designs a union calculation process that searches and merges bidirectionally from the head and tail of skip lists A and B towards the middle of the linked lists. Specifically, bidirectional search and merging is performed on skip lists A and B, and the merging order is determined according to size and adjacency relationships; during merging, data with non-optimal indices is unbound, and the unbound indices are connected to the optimal index data of the bidirectional skip lists.
[0150] Figure 7 This diagram illustrates the search and merge process for merging skip lists A and B. Before executing the skip list merge procedure, the head pointer (skip_head_C_ptr) and tail pointer (skip_rear_C_ptr) of skip list C point to the boundaries of the data range first selected as having the highest-level index. The skip list merge process consists of a forward search merge process and a reverse search merge process.
[0151] The forward search and merge process starts from the data pointed to by start_ptr_A and start_ptr_B and searches and merges towards the back of the linked list, including three cases.
[0152] (1) If the data pointed to by skiplist A and skiplist B currently, data_A = data_B, then skiplist C retains the one with the larger index level between skiplist A and skiplist B, and then moves the search pointer addresses of skiplist A and skiplist B backward, that is, start_ptr_A ← skip_list_A_next[start_ptr_A], start_ptr_B ← skip_list_B_next[start_ptr_B].
[0153] (2) If the data pointed to by skiplist A currently, data_A < the data pointed to by skiplist B currently, data_B, then it is necessary to judge the adjacent relationship between the subsequent data of data_A and data_B, and save the subsequent data index address and data value of data_A to start_ptr_A and next_data_A respectively, that is, start_ptr_A ← skip_list_A_next[start_ptr_A], next_data_A ← skip_list_A_data[start_ptr_A]. At this time, the following three situations are included: 1) If next_data_A < data_B, then the subsequent data of skiplist A is next_data_A, and skiplist C retains the maximum of the index levels of next_data_A and data_A. 2) If next_data_A > data_B, then the subsequent data of skiplist A is data_B, and skiplist C retains the maximum of the index levels of data_A and data_B. 3) If next_data_A = data_B, then skiplist C retains the maximum of the index levels among data_A, data_B, and next_data_A.
[0154] (3) If the data data_A pointed to by skip list A is greater than the data data_B pointed to by skip list B, it is necessary to determine the adjacent relationship between the subsequent data of data_B and data_A. Save the subsequent data index address and data value of data_B to start_ptr_B and next_data_B respectively, that is, start_ptr_B ← skip_list_B_next[start_ptr_B], next_data_B ← skip_list_B_data[start_ptr_B]. At this time, the following three situations are included: 1) If next_data_B < data_A, the subsequent data of skip list B is next_data_B, and skip list C retains the maximum of the index levels of next_data_B and data_B. 2) If next_data_B > data_A, the subsequent data of skip list B is data_A, and skip list C retains the maximum of the index levels of data_A and data_B. 3) If next_data_B = data_A, skip list C retains the maximum of the index levels among data_A, data_B, and next_data_B.
[0155] The reverse search and merge process starts from the data pointed to by start_ptr_A and start_ptr_B and searches and merges towards the front end of the linked list, including three situations.
[0156] (1) If the data data_A = data_B pointed to by skip list A and skip list B, skip list C retains the larger of the index levels in skip list A and skip list B, and then move the search pointer addresses of skip list A and B forward, that is, end_ptr_A ← skip_list_A_prior[end_ptr_A], end_ptr_B ← skip_list_B_prior[end_ptr_B].
[0157] (2) If the data data_A currently pointed to by skip list A > the data data_B currently pointed to by skip list B, it is necessary to judge the adjacent relationship between the previous data of data_A and data_B. Save the index address and data value of the previous data of data_A to end_ptr_A and prior_data_A respectively, i.e., end_ptr_A ← skip_list_A_prior[end_ptr_A], prior_data_A ← skip_list_A_data[end_ptr_A]. At this time, the following three situations are included: 1) If prior_data_A > data_B, the previous data of skip list A is prior_data_A, and skip list C retains the maximum of the index levels of prior_data_A and data_A. 2) If prior_data_A < data_B, the previous data of skip list A is data_B, and skip list C retains the maximum of the index levels of data_A and data_B. 3) If prior_data_A = data_B, skip list C retains the maximum of the index levels among data_A, data_B, and prior_data_A.
[0158] (3) If the data data_A currently pointed to by skip list A < the data data_B currently pointed to by skip list B, it is necessary to judge the adjacent relationship between the previous data of data_B and data_A. Save the index address and data value of the previous data of data_B to end_ptr_B and prior_data_B respectively, i.e., end_ptr_B ← skip_list_B_prior[end_ptr_B], prior_data_B ← skip_list_B_data[end_ptr_B]. At this time, the following three situations are included: 1) If prior_data_B > data_A, the previous data of skip list B is prior_data_B, and skip list C retains the maximum of the index levels of prior_data_B and data_B. 2) If prior_data_B < data_A, the previous data of skip list B is data_A, and skip list C retains the maximum of the index levels of data_A and data_B. 3) If prior_data_B = data_A, skip list C retains the maximum of the index levels among data_A, data_B, and prior_data_B.
[0159] Figure 8This is a flowchart illustrating the data merging process for skip lists A and B. Each time skip lists A and B are merged, the optimal index is first selected, which is the upper-level index with the highest index level in the current decision sequence. After selecting the optimal index, the unbinding direction of the upper-level data indexes needs to be determined based on the search direction of the candidate data in the current candidate list. This includes the unbinding process for preceding indexes and subsequent indexes.
[0160] The seventh sub-process: the process of unbinding the preceding index.
[0161] This sub-process is responsible for unbinding all the upper-level forward indices of the data unit pointed to by data_ptr, and returning the address of the preceding data index of all upper-level indices.
[0162] During forward data merging, the data at start_ptr_A and start_ptr_B are first retrieved. The data with the smaller value between data_A and data_B is selected and linked to the lowest-level data field linked list of skip list C, denoted as data_C=min{data_A,data_B}. The index address of data_C, data_C_addr, is the index of the data with the smallest value. The selection of higher-level indexes requires determining the adjacency relationship between the current data and subsequent data, as well as their index levels. The index levels of the data at start_ptr_A and start_ptr_B are saved to index_level_A and index_level_B respectively, i.e., index_level_A ← data_index_level_A[start_ptr_A], index_level_B ← data_index_level_B[start_ptr_B]. The sizes of index_levelA and index_level_B are compared, and all upper-level indexes with larger index levels are selected as indexes for the corresponding data in skip list C. For data with smaller indexes, the index unbinding process unbind_index[data_C_addr] is executed, and the subsequent data of the upper-level indexes are connected to the preceding index of the current data in skip list C.
[0163] When the number of index levels is greater than 0, the following loop process is executed to unbind the preceding data index of each level layer by layer.
[0164] Save the upper-level data index of the current data to upper_data_addr, i.e., upper_data_addr←skip_list_up[data_ptr]. Retrieve the previous index address of the upper-level data and save it to the prior_index_addr register, i.e., prior_index_addr←skip_list_prior[upper_data_addr]. Then write the previous index prior_index_addr to the previous index queue prior_index_FIFO, execute write_FIFO[prior_index_FIFO, prior_index_addr], and update the previous data index level counter prior_index_num←prior_index_num+1.
[0165] After selecting a piece of data as the optimal index each time, the preceding index of that data needs to be connected to each piece of data in the current data index level. The ninth sub-process is then executed to perform the preceding index connection.
[0166] Eighth sub-process: Subsequent index unbinding process.
[0167] This sub-process is responsible for unbinding all subsequent upper-level indices of the data unit pointed to by data_ptr, and returning the address of the subsequent data index of all upper-level indices.
[0168] During reverse data merging, the data at end_ptr_A and end_ptr_B are first retrieved. The data with the larger data_A and data_B values are then linked to the lowest-level data field linked list of skip list C, denoted as data_C=max{data_A,data_B}. The index address of data_C, data_C_addr, is the index of the data with the largest data value. The selection of higher-level indexes requires determining the adjacency relationship between the current data and the preceding data, as well as their index levels. The index levels of the data at start_ptr_A and start_ptr_B are saved to index_level_A and index_level_B respectively, i.e., index_level_A←data_index_level_A[end_ptr_A], index_level_B←data_index_level_B[end_ptr_B]. The sizes of index_level_A and index_level_B are compared, and all upper-level indexes with larger index levels are selected as indexes for the corresponding data in skip list C. For data with smaller indexes, the index unbinding process unbind_index[data_C_addr] is executed, and the subsequent data of the upper-level indexes are connected to the subsequent indexes of the current data in skip list C.
[0169] When the number of index levels (index_level_num) > 0, the following loop process is executed to unbind the subsequent data indexes of each level one by one.
[0170] Save the upper-level data index of the current data to upper_data_addr, upper_data_addr←skip_list_up[data_ptr]. Retrieve the subsequent index address of the upper-level data and save it to the next_index_addr register, i.e. next_index_addr←skip_list_next[upper_data_addr]. Then write the subsequent index next_index_addr to the subsequent index queue next_index_FIFO, execute write_FIFO[next_index_FIFO, next_index_addr], and update the counter for the number of subsequent data index levels next_index_num←next_index_num+1.
[0171] After selecting a data point as the optimal index each time, it is necessary to connect the subsequent indexes of the current data to each data point in the current index level, and execute the tenth sub-process to perform the subsequent index connection process.
[0172] Ninth sub-process: Preorder index join process.
[0173] This sub-process is responsible for connecting the indexes of preceding data to the upper-level index units of the current data. It needs to determine the size of the preceding data index level and the current index level, and perform matching and connection according to the level. The number of data index levels to be connected is saved to the `current_index_num` counter, where `current_index_num` ← `data_index_level[data_ptr]`, and the number of connected indexes is set to `connect_num` ← 0. When `connect_num` ≤ the minimum value between the number of preceding data index levels (`prior_index_num`) and the number of data index levels to be connected (`current_index_num`), i.e., `connect_num` ≤ min{prior_index_num, current_index_num}`, the following loop process is executed.
[0174] The process involves sequentially retrieving the address of the next pending index from the prior index queue `prior_index_FIFO` and saving it to the `prior_index_addr` register (i.e., `prior_index_addr ← read_FIFO[prior_index_FIFO]`). Then, the address of the previous index of the current data is saved to `current_index_addr` (i.e., `current_index_addr ← skip_list_up[data_ptr]`). Next, the `next` pointer of the preceding data index `prior_index_addr` is set to the address of its subsequent data, `current_index_addr` (i.e., `skip_list_next[prior_index_addr] ← current_index_addr`). Finally, the preceding prior index of the level pointed to by the current `current_index_addr` is set to its preceding data index address `prior_index_addr` (i.e., `skip_list_prior[current_index_addr] ← prior_index_addr`). Finally, the count of connected indices is updated (`connect_num` ← `connect_num + 1`).
[0175] After the above loop process is completed, the indexes of the preceding data have been connected to the upper-level index units of the current data. Next, the unconnected indexes in the preceding and subsequent indexes are checked. The counters for the remaining unconnected indexes of the preceding and subsequent data are set to prior_index_left and current_index_left, respectively, i.e., prior_index_left ← prior_index_num - connect_num, current_index_left ← current_index_num - connect_num.
[0176] When the remaining index of the preceding data is greater than 0, repeat the following steps: set the next register, which is the pointer to the next index of the preceding data, to null, skip_list_next[prior_index_addr] ← null, then save the next upper-level preceding data index from the preceding data index queue to prior_index_addr, i.e., prior_index_addr ← read_FIFO[prior_index_FIFO], and finally update the remaining index of the preceding data, prior_index_left ← prior_index_left - 1.
[0177] When the number of remaining indices for the current data is greater than 0 (current_index_left), repeat the following steps: set the preceding index pointer of the current data to null (i.e., skip_list_prior[current_index_addr] ← null), then save the upper-level index of the current data to current_index_addr (i.e., current_index_addr ← skip_list_up[current_index_addr]), and finally update the number of remaining indices for the current data (current_index_left ← current_index_left - 1).
[0178] Tenth sub-process: Subsequent index connection process.
[0179] This sub-process is responsible for connecting subsequent indices of the current data to the index units of the current data. It needs to determine the size of the subsequent data index level and the current index level, and perform matching and connection according to the level. The number of data index levels to be connected is saved to the `current_index_num` counter, i.e., `current_index_num ← data_index_level[data_ptr]`, and the number of connected indexes is set to `connect_num ← 0`. When `connect_num ≤ min{next_index_num, current_index_num}`, the following loop process is executed.
[0180] The system sequentially retrieves the address of the next pending index from the next_index_FIFO queue and saves it to the next_index_addr register (i.e., next_index_addr ← read_FIFO[next_index_FIFO]). It then saves the address of the previous index of the current data to current_index_addr (i.e., current_index_addr ← skip_list_up[data_ptr]). Next, it sets the prior pointer of the next data index next_index_addr to its preceding data address current_index_addr (i.e., skip_list_prior[next_index_addr] ← current_index_addr). Finally, it sets the next index of the level pointed to by current_index_addr to its next data index address next_index_addr (i.e., skip_list_next[current_index_addr] ← next_index_addr). The system then updates the counter for the number of connected indices, connect_num, by incrementing it by 1.
[0181] After the above loop process is completed, the indices of subsequent data have been connected to the upper-level index unit of the current data. Next, the unconnected indices in the subsequent and current indices are determined. The counters next_index_left and current_index_left for the remaining number of unconnected indices in the subsequent and current data are set respectively, i.e., next_index_left ← next_index_num - connect_num, current_index_left ← current_index_num - connect_num.
[0182] When the number of remaining indices for subsequent data next_index_left > 0, repeat the following steps: set the preceding index pointer prior register of the subsequent data to null, i.e., skip_list_prior[next_index_addr] ← null, then save the next upper-level subsequent data index from the subsequent data index queue to next_index_addr, i.e., next_index_addr ← read_FIFO[next_index_FIFO], and finally update the number of remaining indices for subsequent data next_index_left ← next_index_left - 1.
[0183] When the number of remaining indices for the current data is greater than 0, repeat the following steps: set the next register, which is the pointer to the next index of the current data, to null (i.e., skip_list_next[current_index_addr] ← null), then save the upper-level index of the current data to current_index_addr (i.e., current_index_addr ← skip_list_up[current_index_addr]), and finally update the number of remaining indices for the current data to current_index_left ← current_index_left - 1.
[0184] The following is a detailed explanation of the calculation process for the union of bidirectional skip lists A and B.
[0185] Initially, pointers start_ptr_A and start_ptr_B pointing to the first data in skip list A and skip list B, respectively, and pointers end_ptr_A and end_ptr_B pointing to the last data in skip list A and skip list B, respectively, are retrieved from the skip_head_ptr and skip_rear_ptr pointer registers, respectively. That is, start_ptr_A←skip_head_ptr_A[skip_head_addr_A], start_ptr_B←skip_head_ptr_B[skip_head_addr_B], end_ptr_A←skip_rear_ptr_A[skip_rear_addr_A], end_ptr_B←skip_rear_ptr_B[skip_rear_addr_B]. Then, the header data of skip lists A and B are saved to the start_data_A and start_data_B registers respectively, i.e., start_data_A ← skip_list_data_A[start_ptr_A], start_data_B ← skip_list_data_B[start_ptr_B]. The tail data of skip lists A and B are saved to the end_data_A and end_data_B registers respectively, i.e., end_data_A ← skip_list_data_A[end_ptr_A], end_data_B ← skip_list_data_B[end_ptr_B]. Then, based on the adjacency relationship and index level of the data before and after start_data_A and start_data_B, and end_data_A and end_data_B, both forward search and reverse search merging processes are performed simultaneously. Finally, based on the selected optimal index, the index unbinding and join processes are performed.
[0186] The following loop is executed when start_ptr_A ≤ end_ptr_A, or start_ptr_B ≤ end_ptr_B.
[0187] Simultaneously, the forward search and merging process and the reverse search and merging process are executed. Based on the selected best index, the preceding / following index unbinding process and the preceding / following index joining process are executed respectively. The current header and tail pointer indexes of skip lists A and B are updated according to the current data size relationship between the header and tail.
[0188] (1) There are three cases in the forward search merging process.
[0189] 1) If data_A = data_B, select the one with a larger data index level pointed to by start_ptr_A and start_ptr_B as the optimal index. First, select the data with the smallest index level, min{index_level_A, index_level_B}, to execute the seventh sub-process, and then select the data with the larger index level, max{index_level_A, index_level_B}, to execute the ninth sub-process. Then update the data index, and move the search pointers of skip list A and B backward, start_ptr_A ← skip_list_A_next[start_ptr_A], start_ptr_B ← skip_list_B_next[start_ptr_B].
[0190] 2) If data_A < data_B, first move the current index of skip list A backward, start_ptr_A ← skip_list_A_next[start_ptr_A], and then judge the adjacent relationship and index level size between the subsequent data next_data_A pointed to by start_ptr_A and data_A and data_B, including the following three cases: 1) If next_data_A < data_B, first select the data with the smallest index level, min{data_A, next_data_A}, to execute the seventh sub-process, and then select the data with the larger index level, max{data_A, next_data_A}, to execute the ninth sub-process; 2) If next_data_A > data_B, first select the data with the smallest index level, min{data_A, data_B}, to execute the pre-index unbinding process of the seventh sub-process, and then select the data with the larger index level, max{data_A, data_B}, to execute the pre-index connection process of the ninth sub-process; 3) If next_data_A = data_B, first select the data with the smallest index level, min{data_A, data_B, next_data_A}, to execute the seventh sub-process, and then select the data with the larger index level, max{data_A, data_B, next_data_A}, to execute the pre-index connection process of the ninth sub-process;
[0191] 3) If data_A > data_B, first move the current index of skip list B backward, start_ptr_B ← skip_list_B_next[start_ptr_B], and then determine the adjacent relationship and index level size of the subsequent data next_data_B pointed to by start_ptr_B with respect to data_A and data_B, including the following three cases: 1) If next_data_B < dataA, first select the data with the smallest index level, min{data_B, next_data_B}, to execute the seventh sub-process, and then select the data with the larger index level, max{data_B, next_data_B}, to execute the ninth sub-process; 2) If next_data_B > data_A, first select the data with the smallest index level, min{data_A, data_B}, to execute the seventh sub-process, and then select the data with the larger index level, max{data_A, data_B}, to execute the ninth sub-process; 3) If next_data_B = data_A, first select the data with the smallest index level, min{data_A, data_B, next_data_B}, to execute the seventh sub-process, and then select the data with the larger index level, max{data_A, data_B, next_data_B}, to execute the ninth sub-process;
[0192] (2) During the reverse search and merge process, there are the following three cases.
[0193] 1) If data_A = data_B, select the one with the larger index level of the data pointed to by start_ptr_A and start_ptr_B as the optimal index. First, select the data with the smallest index level, min{index_level_A, index_level_B}, to execute the eighth sub-process, and then select the data with the larger index level, max{index_level_A, index_level_B}, to execute the tenth sub-process. Then update the data index and move the search pointer addresses of skip lists A and B forward, end_ptr_A ← skip_list_A_prior[end_ptr_A], end_ptr_B ← skip_list_B_prior[end_ptr_B].
[0194] 2) If data_A > data_B, first move the current index of skip list A forward, end_ptr_A ← skip_list_A_prior[end_ptr_A], and then determine the adjacent relationship and index level size between the previous data prior_data_A pointed to by end_ptr_A and data_A and data_B, including the following three cases: ① If prior_data_A > data_B, first select the data with the smallest index level min{data_A, prior_data_A} to execute the eighth sub-process, and then select the data with the larger index level max{data_A, prior_data_A} to execute the tenth sub-process; ② If prior_data_A < data_B, first select the data with the smallest index level min{data_A, data_B} to execute the eighth sub-process, and then select the data with the larger index level max{data_A, data_B} to execute the tenth sub-process; ③ If prior_data_A = data_B, first select the data with the smallest index level min{data_A, data_B, prior_data_A} to execute the eighth sub-process, and then select the data with the larger index level max{data_A, data_B, prior_data_A} to execute the tenth sub-process;
[0195] 3) If data_A < data_B, first move the current index of skip list B forward, end_ptr_B ← skip_list_B_prior[end_ptr_B], and then determine the adjacent relationship and index level size of the prior data prior_data_B pointed to by end_ptr_B with data_A and data_B, including the following three cases: 1) If prior_data_B > dataA, first select the data with the smallest index level min{data_B, prior_data_B} to execute the eighth sub-process, and then select the data with the larger index level max{data_B, prior_data_B} to execute the tenth sub-process; 2) If prior_data_B < data_A, first select the data with the smallest index level min{data_A, data_B} to execute the eighth sub-process, and then select the data with the larger index level max{data_A, data_B} to execute the tenth sub-process; 3) If prior_data_B = data_A, first select the data with the smallest index level min{data_A, data_B, prior_data_B} to execute the eighth sub-process, and then select the data with the larger index level max{data_A, data_B, prior_data_B} to execute the tenth sub-process;
[0196] The above loop process ends, and the calculation process of the batch union of data in skip list A and skip list B is completed.
[0197] The second embodiment of the present invention relates to an electronic device, including a memory, a processor, and a computer program stored on the memory and executable on the processor. When the processor executes the computer program, the steps of the matrix data set processing method in the first embodiment are implemented.
[0198] The third embodiment of the present invention relates to a computer-readable storage medium, on which a computer program is stored. When the computer program is executed by a processor, the steps of the matrix data set processing method in the first embodiment are implemented.
[0199] Those skilled in the art should understand that the embodiments of the present application can be provided as a method, a system, or a computer program product. Therefore, the present application can take the form of a complete hardware embodiment, a complete software embodiment, or an embodiment combining software and hardware aspects. Moreover, the present application can take the form of a computer program product implemented on one or more computer-usable storage media (including but not limited to disk memories and optical memories, etc.) containing computer-usable program codes.
[0200] This application is described with reference to flowchart illustrations and / or block diagrams of methods, apparatus (systems), and computer program products according to embodiments of this application. It will be understood that each block of the flowchart illustrations and / or block diagrams, and combinations of blocks in the flowchart illustrations and / or block diagrams, can be implemented by computer program instructions. These computer program instructions can be provided to a processor of a general-purpose computer, special-purpose computer, embedded processor, or other programmable data processing apparatus to produce a machine, such that the instructions, which execute via the processor of the computer or other programmable data processing apparatus, generate instructions for implementing the flowchart... Figure 1 One or more processes and / or boxes Figure 1 A device that provides the functions specified in one or more boxes.
[0201] These computer program instructions may also be stored in a computer-readable storage medium that can direct a computer or other programmable data processing device to operate in a particular manner, such that the instructions stored in the computer-readable storage medium produce an article of manufacture including instruction methods implemented in a process. Figure 1 One or more processes and / or boxes Figure 1 The function specified in one or more boxes.
[0202] These computer program instructions may also be loaded onto a computer or other programmable data processing equipment to cause a series of operational steps to be performed on the computer or other programmable equipment to produce a computer-implemented process, thereby providing instructions that execute on the computer or other programmable equipment for implementing the process. Figure 1 One or more processes and / or boxes Figure 1 The steps of the function specified in one or more boxes.
[0203] The above description is merely a specific embodiment of the present invention, but the scope of protection of the present invention is not limited thereto. Any variations or substitutions that can be easily conceived by those skilled in the art within the technical scope disclosed in the present invention should be included within the scope of protection of the present invention. Therefore, the scope of protection of the present invention should be determined by the scope of the claims.
Claims
1. A method for processing matrix data sets, characterized in that, A dynamic bidirectional skip list storage structure for a matrix data set is used to build the bidirectional skip list. Specifically, it is built layer by layer starting from the data field. During the building process, the data elements are arranged in ascending order. Whenever a data is inserted into the bidirectional skip list, the insertion range is narrowed down from the highest level through bidirectional and hierarchical search, and the insertion position is determined at the bottom level where the data field is located. After each data is inserted into the bidirectional skip list, a probability-driven method is used to randomly determine whether to build multiple upper-level indexes for that data. The dynamic bidirectional skip list storage structure of the matrix data set includes a data field portion at the bottom and an index field portion above the data field portion. The data field portion is used to store the original data, and the index field portion is used to store index data. The data field portion includes multiple data unit structures at the same level, and the index field portion includes multiple levels, each level including multiple data unit structures. Among them, the data unit structures within the same level are linked from smallest to largest through a doubly linked list, and the data unit structures between different levels are linked to the same data range through inter-level linked lists. When it is necessary to delete all data existing in bidirectional skip list B from bidirectional skip list A, the specific steps include: Filter the data in the bidirectional skip list B that belong to the current top-level interval of the bidirectional skip list A, and store them in the candidate data doubly linked list; The data in the candidate data doubly linked list is located layer by layer from the top-level index of the doubly skip list A until its specific interval in the bottom data field is determined. Verify whether the data in the candidate data doubly linked list actually exists in the doubly skipped list A. If it does not exist, delete the data from the candidate data doubly linked list. If it exists, batch delete the data by merging adjacent candidate data intervals.
2. The matrix data set processing method according to claim 1, characterized in that, The data unit structure includes: The preceding pointer register is used to point to the address of the previous data in the same level; The subsequent pointer register is used to point to the address of the next data in the same level; Data registers are used to store data; Hierarchical registers are used to store the index level at which the data resides; The lower-level pointer register is used to point to the lower-level index of the current data; The upper-level pointer register is used to point to the upper-level index of the current data.
3. The matrix data set processing method according to claim 1, characterized in that, The dynamic bidirectional skip list storage structure for the matrix data set also includes: The head pointer register is used to point to the smallest index of the top-level data; The tail pointer register is used to point to the maximum index of the top-level data; The minimum value register is used to store the minimum value of all data in the skip list; The maximum value register is used to store the maximum value of all data in the skip list.
4. The matrix data set processing method according to claim 1, characterized in that, Whenever a piece of data is inserted into the bidirectional skip list, the insertion range is narrowed down from the highest level through bidirectional and hierarchical search, and the insertion position is determined at the bottom level where the data field is located. Specifically, this includes hierarchical interval bidirectional search and bottom interval bidirectional search. The hierarchical interval bidirectional search is completed within the index field. During the search, the data index pointed to by the head pointer register and the tail pointer register are received respectively. The search interval is divided into two parts, the head and the tail, and bidirectional search is performed to find the interval of the data level. The search is then performed layer by layer downwards until the index level is the lowest level of the index part. The bidirectional search of the underlying interval is completed within the data domain. During the search, the interval found by the upper-level index is refined, and the bidirectional search process is executed to find the position where the data is finally inserted into the underlying data domain.
5. The matrix data set processing method according to claim 1, characterized in that, Whenever a piece of data is inserted into the bidirectional skip list, a probability-driven method is used to randomly determine whether to create a multi-level upper-level index for that data. Specifically, when the generated random number is less than the preset index creation probability, an adjacent upper-level index is created for the current data, and the process continues to determine whether to create a higher-level index until the index level exceeds the preset maximum index level.
6. The matrix data set processing method according to claim 1, characterized in that, When it is necessary to delete data from the bidirectional skip list, the specific steps include: When the data to be deleted is located in the middle of the bidirectional skip list, retrieve the preceding and following index addresses of the data to be deleted, delete the index of the data to be deleted, and reconnect the index pointers of the two data before and after the data to be deleted. Retrieve the upper-level index address from the upper-level pointer register. If the upper-level index address is not empty, retrieve the preceding and following index addresses of the upper-level data index, connect the two data at the current level, and save the preceding and following index addresses to the preceding and following pointer registers of the two data respectively. Save the upper-level index of the current data to the upper-level pointer register. When the data to be deleted is located at the left boundary of the bidirectional skip list, retrieve the subsequent data index address of the data to be deleted, set the subsequent data index address of the data to be deleted as the new left boundary, and update the minimum value register of the data unit structure in the data field part; retrieve the upper-level index address from the upper-level pointer register, and when the upper-level index address is not empty, retrieve the subsequent index address of the upper-level data index, set the preceding pointer register of the subsequent data as the new left boundary, and save the upper-level index of the current data to the upper-level pointer register; When the data to be deleted is located at the right boundary of the bidirectional skip list, retrieve the preceding data index address of the data to be deleted, set the preceding data index address of the data to be deleted as the new right boundary, and update the maximum value register of the data unit structure in the data field part; retrieve the upper-level index address from the upper-level pointer register, and when the upper-level index address is not empty, retrieve the preceding index address of the upper-level data index, set the subsequent pointer register of the preceding data as the new right boundary, and save the upper-level index of the current data to the upper-level pointer register.
7. The matrix data set processing method according to claim 1, characterized in that, When it is necessary to merge data from bidirectional skip lists A and B into bidirectional skip list C, the specific steps are as follows: perform bidirectional search and merge on bidirectional skip lists A and B, and determine the merging order according to size and adjacency; during the merging process, unbind data with non-optimal indexes and connect the unbound indexes to the optimal index data of the bidirectional skip lists.
8. The matrix data set processing method according to claim 7, characterized in that, The bidirectional search and merging of the bidirectional skip list A and bidirectional skip list B includes forward search and merging; the forward search and merging specifically includes: When the data pointed to by the head pointer register in the bidirectional skip list A is equal to the data pointed to by the head pointer register in the bidirectional skip list B, the index with the larger level of the two data is taken as the optimal index, and the data corresponding to the optimal index is written into the bidirectional skip list C; When the data pointed to by the head pointer register in bidirectional skip list A is less than the data pointed to by the head pointer register in bidirectional skip list B, if the next data pointed to by the head pointer register in bidirectional skip list A is still less than the data pointed to by the head pointer register in bidirectional skip list B, then the index with the larger level between the data pointed to by the head pointer register in bidirectional skip list A and the next data is taken as the optimal index, and the data corresponding to the optimal index is written into bidirectional skip list C; if the next data pointed to by the head pointer register in bidirectional skip list A is greater than the data pointed to by the head pointer register in bidirectional skip list B, then the bidirectional skip list C is... The index with the larger level between the data pointed to by the head pointer register in skip list A and the data pointed to by the head pointer register in bidirectional skip list B is used as the optimal index, and the data corresponding to the optimal index is written into bidirectional skip list C; if the next data pointed to by the head pointer register in bidirectional skip list A is equal to the data pointed to by the head pointer register in bidirectional skip list B, then the index with the larger level between the data pointed to by the head pointer register in bidirectional skip list A and its next data, and the data pointed to by the head pointer register in bidirectional skip list B, is used as the optimal index, and the data corresponding to the optimal index is written into bidirectional skip list C; When the data pointed to by the head pointer register in bidirectional skip list A is greater than the data pointed to by the head pointer register in bidirectional skip list B, if the next data pointed to by the head pointer register in bidirectional skip list B is still less than the data pointed to by the head pointer register in bidirectional skip list A, then the index with the larger level between the data pointed to by the head pointer register in bidirectional skip list B and the next data is taken as the optimal index, and the data corresponding to the optimal index is written into bidirectional skip list C; if the next data pointed to by the head pointer register in bidirectional skip list B is greater than the data pointed to by the head pointer register in bidirectional skip list A, then the bidirectional skip list C is... The index with the larger level between the data pointed to by the head pointer register in skip list A and the data pointed to by the head pointer register in bidirectional skip list B is taken as the optimal index, and the data corresponding to the optimal index is written into bidirectional skip list C; if the next data pointed to by the head pointer register in bidirectional skip list B is equal to the data pointed to by the head pointer register in bidirectional skip list A, then the index with the larger level between the data pointed to by the head pointer register in bidirectional skip list B and its next data, and the data pointed to by the head pointer register in bidirectional skip list A, is taken as the optimal index, and the data corresponding to the optimal index is written into bidirectional skip list C.
9. The matrix data set processing method according to claim 7, characterized in that, The bidirectional search and merging of the bidirectional skip list A and bidirectional skip list B includes reverse search and merging, which specifically includes: When the data pointed to by the tail pointer register in the bidirectional skip list A is equal to the data pointed to by the tail pointer register in the bidirectional skip list B, the index with the larger level of the two data is taken as the optimal index, and the data corresponding to the optimal index is written into the bidirectional skip list C; When the data pointed to by the tail pointer register in bidirectional skip list A is greater than the data pointed to by the tail pointer register in bidirectional skip list B, if the preceding data of the data pointed to by the tail pointer register in bidirectional skip list A is still greater than the data pointed to by the tail pointer register in bidirectional skip list B, then the index with the larger level among the data pointed to by the head pointer register in bidirectional skip list A and the preceding data is taken as the optimal index, and the data corresponding to the optimal index is written into bidirectional skip list C; if the preceding data of the data pointed to by the tail pointer register in bidirectional skip list A is less than the data pointed to by the tail pointer register in bidirectional skip list B, then the index with the larger level among the data pointed to by the tail pointer register in bidirectional skip list A and the tail pointer register in bidirectional skip list B is taken as the optimal index, and the data corresponding to the optimal index is written into bidirectional skip list C; if the preceding data of the data pointed to by the tail pointer register in bidirectional skip list A is equal to the data pointed to by the tail pointer register in bidirectional skip list B, then the index with the larger level among the data pointed to by the head pointer register in bidirectional skip list A, the preceding data, and the data pointed to by the tail pointer register in bidirectional skip list B is taken as the optimal index, and the data corresponding to the optimal index is written into bidirectional skip list C. When the data pointed to by the tail pointer register in bidirectional skip list A is less than the data pointed to by the tail pointer register in bidirectional skip list B, if the data preceding the data pointed to by the head pointer register in bidirectional skip list B is still greater than the data pointed to by the head pointer register in bidirectional skip list A, then the index with the larger level between the data pointed to by the head pointer register in bidirectional skip list B and its preceding data is taken as the optimal index, and the data corresponding to the optimal index is written into bidirectional skip list C; if the data preceding the data pointed to by the head pointer register in bidirectional skip list B is less than the data pointed to by the head pointer register in bidirectional skip list A, then the data is written into bidirectional skip list C. The index with the larger level between the data pointed to by the tail pointer register in bidirectional skip list A and the data pointed to by the tail pointer register in bidirectional skip list B is used as the optimal index, and the data corresponding to the optimal index is written into bidirectional skip list C; if the data preceding the data pointed to by the head pointer register in bidirectional skip list B is equal to the data pointed to by the head pointer register in bidirectional skip list A, then the index with the larger level between the data pointed to by the head pointer register in bidirectional skip list B and its preceding data, and the data pointed to by the head pointer register in bidirectional skip list A, is used as the optimal index, and the data corresponding to the optimal index is written into bidirectional skip list C.
10. The matrix data set processing method according to claim 7, characterized in that, During the merging process, data with non-optimal indexes is unbound, and the unbound indexes are connected to the optimal index data of the bidirectional skip list. Specifically, this includes: During forward search merging, the upper-level index address of the non-optimal index data is read, and the preceding address of the upper-level index address is taken out and written into the preceding index queue. The preceding address is taken out from the preceding index queue and matched with the upper-level index of the optimal index data in the bidirectional skip list C layer by layer. When matching, the subsequent pointer register of the preceding address is pointed to the index of the optimal index data in the bidirectional skip list C, and the preceding pointer register of the index of the optimal index data in the bidirectional skip list C is pointed to the preceding address. During reverse search merging, the upper-level index address of the non-optimal index data is read, and the subsequent address of the upper-level index address is taken out and written into the subsequent index queue. The subsequent address is taken out from the subsequent index queue and connected layer by layer with the upper-level index of the optimal index data in the bidirectional skip list C. During the connection, the preceding pointer register of the subsequent address is pointed to the index of the optimal index data in the bidirectional skip list C, and the subsequent pointer register of the index of the optimal index data in the bidirectional skip list C is pointed to the subsequent address.
11. An electronic device comprising a memory, a processor, and a computer program stored in the memory and executable on the processor, characterized in that, When the processor executes the computer program, it implements the steps of the matrix data set processing method as described in any one of claims 1-10.
12. A computer-readable storage medium having a computer program stored thereon, characterized in that, When the computer program is executed by a processor, it implements the steps of the matrix data set processing method as described in any one of claims 1-10.
Citation Information
Patent Citations
Data processing method and device
CN110968832A
Data access method of priority queue
CN114489485A
Data storage system and method for automatic design of super-large-scale integrated circuit
CN118170769A
Compression, storage and calculation device for matrix double linked list
CN119691235A