C++ Array for Double Pointer Chain List

Keywords: C++ data structure linked list

Title Source==> AcWing Question 827

subject

Implements a double-linked list, which is initially empty and supports five operations:

  1. Insert a number on the leftmost side;
  2. Insert a number at the far right;
  3. Delete the number of KTH inserts;
  4. Insert a number to the left of the k th insertion number;
  5. Insert a number to the right of the k th insertion

Now you will perform M operations on the list, and after all operations, output the entire list from left to right.
Note: The number of the kth insertion in the title does not refer to the kth number of the current list of chains. For example, if n numbers have been inserted during the operation, the number of insertions will be in chronological order: the number of the first insertion, the number of the second insertion, and the number of the nth insertion.

Input Format

The first line contains the integer M, indicating the number of operations.
The next M lines contain one action command per line, which may be as follows:

  1. L x, the number x inserted at the leftmost end of the list.
  2. R x, indicating the insertion number x at the rightmost end of the list.
  3. D k, which means the number of the first k inserts will be deleted.
  4. IL k x, which means to insert a number to the left of the kth insertion number.
  5. IR k x, which means to insert a number to the right of the k th insertion number.

Output Format

Output the entire list from left to right on one line.

Data Range

1≤M≤100000
All operations are guaranteed to be legal.

Input sample:

10
R 7
D 1
L 3
IL 2 10
D 3
IL 2 7
L 8
R 9
IL 4 7
IR 2 2

Output sample:

8 7 7 3 2 9

Title Code

//2021 10 14 AcWing Question 827
#include <iostream>
using namespace std;

const int N = 100010;
// v[i] stores the value of number I
//l[i] Stores the left pointer of the ith number
//r[i] Stores the right pointer of the number I
//idx represents the current array position
int v[N],l[N], r[N], idx;

//Initialize, both the head and tail nodes are sentinel nodes
void init(){
    r[0] = 1; //Head Node 0
    l[1] = 0; //Tail Node 1
    idx = 2; //Currently used array position is 2
}

//Delete the k th inserted node
void remove(int k){
   l[r[k]] = l[k]; //The left pointer of the right node points to the left pointer of the k node
   r[l[k]] = r[k];//The right pointer of the left node points to the right pointer of the k node
}

//Insert x to the right of the k th digit
//If left insertion is to be implemented, the left pointer l[k] with a k-value of K node will be passed in
void insert(int k,int x){
    v[idx] = x; //Assigning values to insertion nodes
    l[idx] = k; //Insert node left pointer to k
    r[idx] = r[k]; //Insert Node Right Pointer to Right Node of k Node
    l[r[k]] = idx; //The left pointer of the right node of the k node points to the newly inserted node
    r[k] = idx; //The right pointer of the k node points to the newly inserted node
    idx ++; //Single-chain list opens up another location, array space+1
}

int main(){
    
    init(); //Double Chain List Initialization
    
    int m;
    cin >> m;
    while(m--){
        int k, x;
        string op;
        cin >> op;
        
        if(op == "L"){ //Insert the number x to the leftmost end of the list.
            cin >> x;
            insert(0, x); //Equivalent to inserting x to the left of the header node
        }
        else if(op == "R"){ // Insert the number x at the rightmost end of the list.
            cin >> x;
            insert(l[1], x); //Equivalent to inserting x to the right of the left node of the tail node
        }
        else if(op == "D"){ //Represents the number after the k th inserted number deleted.
            cin >> k;
            remove(k + 1); //The first indexed number of chains is 2, so the k-th indexed number is k+1
        }
        else if (op == "IL")
        {
            cin >> k >> x;
            insert(l[k + 1], x);
        }
        else
        {
            cin >> k >> x;
            insert(k + 1, x);
        }
        
    }
    
    //Traverse the values of the output single-chain table, from left to right
    for(int i = r[0]; i != 1;i = r[i]) cout << v[i] << " ";
    cout << endl;
    // //Traverse the values of the output single-chain table, right-to-left
    // for(int i = l[1]; i != 0;i = l[i]) cout << v[i] << " ";
    // cout << endl;
    
    return 0;
}

Ways of thinking

In the face of a large amount of data, if you use structured linked lists, the nodes of the new single-linked list are very slow when you insert a large number of inserts, and each time you use structured linked lists, you need to start from scratch each time you want to traverse to a node in the chain table, with a time complexity of O(n), because the nodes are linked by pointers.
When using arrays to implement chain tables, the chain tables implemented by arrays can find nodes directly through subscripts and assign values to the nodes directly. Therefore, the biggest advantage of single-chain tables implemented by arrays is that they are fast, and the insertion and deletion operations are O(1) time complexity.

Posted by Paghilom on Wed, 13 Oct 2021 09:47:54 -0700