【Linked List】|Single Linked List|Double Linked List|Simulated Linked List|Operation of Linked List

One, linked list

The linked list is the most basic linear data structure. Usually, we use this data structure to complete some operations that the array cannot complete or that the completion is not very good. The most important thing is the random insertion operation, whether it is an array or a queue. Stack operations cannot complete the operation of inserting values ​​very well, because they need to completely change the subscript value to complete the insertion of values. Inserting values ​​requires an O(n) cycle, but for linked lists It only needs an O(1) time, and the insertion operation of the linked list is undoubtedly the core operation of the linked list.

For the storage structure of the linked list, we simulate the linked list using an array. First, we must have an e[N] **idx ** to store the data of the linked list, and idx serves for e[N] . Then there is the pointer of the linked list. First of all, the single linked list must have a pointer pointing to the next node. At the same time, it will also have a matching head storage head node. The pointer in the double linked list is a left pointer and a right pointer. , the head and tail nodes in these two pointers are represented in specific ways.
insert image description here

Second, single linked list

1. The structure of a single linked list

The singly linked list is composed of two parts, one part is the data storage part **e[N] idx **, which is the so-called node of the linked list; the other part is the pointer operation, **ne[N] head **, this It is the chain in the linked list; the operation of the single linked list can be regarded as the operation of the chain and the node.

The pointer of the singly linked list is advanced, and the point of each stay is not assigned;


const int N = 100010 ;

int e[N], idx = 0 ;

int ne[N] , head ;

2. Operation of single linked list

1. Initialization operation of singly linked list

// Just change the two pointers every time you initialize, and the original data will be overwritten when the data is stored

void init()
{
    
    
	head = - 1 ;
	idx = 0 ;
}
2. Insert operation of singly linked list
insert operation

//First we open a node first, then we need to assign a value to this node, then we change some pointers of this point, and then change the pointer of the head node

void insert_head(int x)
{
    
    
	e[idx] = x , ne[idx] = head , head = idx ++ ;
}

Insert the first few numbers

//First of all, we can know based on the above, we need to know the pointer of the item **i - 1**, the ne[i] pointed to , solve this ** u **, and take this u as the head .

void insert(int x ,int j)
{
    
    
	int u ;
	for(u = head , int i = 0 ; i < j - 1; i ++ )
		u = ne[u] ;
	e[idx] = x, ne[idx] = u , u = idx ++ ;

}
3, delete operation

//First of all, it is the simplest operation to delete the head node,
we can directly assign the head node

void remove_head ()
{
    
    
	head = ne[head] ;
}

Since we are not as flexible as an array when calling data in a linked list, we generally only call the head node, and insert and delete operations are completed at the head node. Cold knowledge: the time complexity of random insertion in a single linked list is the same as other
data The structure is similar

Another point of the linked list is that you can search for the inserted value and delete the value after n

3. Total operation of single linked list

#include <iostream>
using namespace std ;

const int N = 100010 ;

int idx = 0  , e[N] , ne[N] ,head = - 1 ;

void insert ( int  u)
{
    
    
	e[idx] = u , ne[idx] = head , head = idx ++ ;
}

void remove (int u )
{
    
    
	ne[u] = ne[ne[u]] ;
}


void add(int k, int x)
{
    
    
    e[idx] = x, ne[idx] = ne[k], ne[k] = idx ++ ;
}


int main ()
{
    
    
	int n ;
	cin >> n ;
	while ( n -- )
	{
    
    
		char s;
		int a , b ;
		cin >> s ;
		if(s == 'H')
		{
    
    
			cin >> a ;
			insert(a) ;
		}
		else if(s == 'D')
		{
    
    
			cin >> a ;
			if(a)
			remove(a - 1) ;
			//删除第 a 个插入的数的后面的数 
			else 
			{
    
    
			    head = ne[head] ;
			}
		}
		else 
		{
    
    
			cin >> a >> b ;
			add( a - 1, b );
			//注意:我们要完成的插入操作是第k位 后面的,当我们插入的时候 idx 是从0 开始的 所以我们减去 1 
		}	
	}

    for(int  i = head ; i != -1 ; i = ne[i] )
        cout << e[i] << " " ;
    return 0 ;
	return 0 ;
}

4,Practical application of singly linked list to store tree

Singly linked list storage tree, first of all, the tree is composed of nodes and edges, so we need to understand two operations, the creation of nodes and the creation of edges;

variable needed

Root node: h[N] // There are multiple heads so we use h[N] instead Edge
nodes: e[N] ,ne[N] ,idx

created head node

First, the head node needs to be initialized once, so that they all point to -1;

add edge

Just make the so-called h[N] equivalent to head

void add (int a ,int b )
{
    
    
	e[ ++ idx] = b ;
	ne[idx] = h[a] ;
	h[a] = idx ;
}
``
### 3,双链表的实现
 
1,双链表的结构,双链表有两个指针 **l[N] r[N]** 和一个存储数值的地址 **idx ,e[N]**
  2,双链表的基本操作
###### 双链表的创建
  
```cpp
void init ()
{
    
    
	idx = 2 ;
	r[1] = 0 ;
	l[0] = 1 ;
}
Insertion operation of double-linked list (insert to the inserted node)

Our operation is to insert the k-1th inserted number

void insert (int k ,int x)
{
    
    
    e[idx] = x ;
    l[idx] = k ;
    r[idx] = r[k] ;
    l[r[k]] = idx ;
    r[k] = idx ++ ;
}

To complete the insertion operation on the left is to let the pointer go to the left once, and then use this backward insertion function to complete the insertion operation.

Delete operation of double linked list

The deletion of the double linked list is the operation of making both sides equal to each other

//删除第 k - 1 个插入的值 
void remove ( int k) 
{
    
    	
	l[r[k]] = l[k] ;
	r[l[k]] = r[k] ;
}

3. Overall code implementation

#include <iostream>

using namespace std ;

const int N = 100010 ;

int idx , l[N] , r[N] , e[N] ;

void init ()
{
    
    
    r[0] = 1 ;
    l[1] = 0 ;
    idx = 2;
}
void insert (int k ,int x)
{
    
    
    e[idx] = x ;
    l[idx] = k ;
    r[idx] = r[k] ;
    l[r[k]] = idx ;
    r[k] = idx ++ ;
}
void remove (int k )
{
    
    
    r[l[k]] =r[k] ;
    l[r[k]] = l[k] ;
}

int main ()
{
    
    
    init();
    int n ;
    cin >> n ;
    while (n -- )
    {
    
    
        string str ;
        cin >> str ;
        int k , x;
        if(str == "L" ) 
        {
    
    
            cin >> x ;
            insert(0 , x) ;
        }   
        else if(str == "R")
        {
    
    
            cin >> x ;
            insert(l[1] , x );
        }
        else if (str == "D")
        {
    
    
            cin >> x ;
            remove(x + 1 );
        }
        else if (str == "IL")
        {
    
    
            cin >> k >> x ;
            insert(l[k + 1 ] , x );
        }
        else 
        {
    
    
            cin >> k >> x ;
            insert(k + 1 , x );
        }
    }
    for(int i = r[0] ; i != 1 ;i = r[i])
        cout <<e[i]<< " ";
    return 0 ;
}

3. Circular linked list operation

1. Construction of circular linked list

#include <iostream>
#include <algorithm>
using namespace std ;

const int N = 100010  ;

int ne[N] , e[N] ,idx ;


int main ()
{
    
    

   ____链表的构建_____
   //构建链表的n - 1个序列类似
   //  324 34  454 65 45665 6
   //   1   2   3   4  5    —    指针
   //   0   1   2   3  4    5    下标

   //构建链表的循环(n)  ne[6] = 0 ; 


   return 0 ;
}

2. The other operations of the circular linked list are the same as those of the single linked list

Example Joseph problem
n people form a circle, start counting from the first person, the person who counts to mm goes out, and then the next person starts counting again from 11, and the person who counts to mm goes out of the circle again, and so on , until all the people are out of the circle, please output the numbers of the people who are out of the circle in turn.

#include <iostream>
using namespace std ;

const int N = 120 ;

int e[N] ,ne[N] ,idx  ;

int main () 
{
    
    
    int n , m ;
    cin >> n >> m ;
    for(int i = 1 ; i < n ; i  ++ )
    {
    
    
        e[ ++ idx] = i ; 
        ne[idx] = idx + 1 ;
    }
    e[++ idx] = n ; 
    int p = 0  ;
    ne[0] = 1 ;
    ne[idx] = 1 ;
    for(int i = 0 ; i < n ; i ++ )
    {
    
    
        for(int j = 0 ; j < m - 1 ; j ++ )
            p = ne[p] ; 
        cout << e[ne[p]] << " ";
        ne[p] = ne[ne[p]]; 
    }
    return 0 ;
}

Guess you like

Origin blog.csdn.net/wen030803/article/details/131791164