Um, lista encadeada
A lista encadeada é a estrutura de dados linear mais básica. Geralmente, usamos essa estrutura de dados para concluir algumas operações que o array não pode concluir ou cujo preenchimento não é muito bom. O mais importante é a operação de inserção aleatória, seja uma uma matriz ou uma fila. As operações de pilha não podem concluir muito bem a operação de inserção de valores, pois precisam alterar completamente o valor subscrito para concluir a inserção de valores. Inserir valores requer um ciclo O(n), mas para vinculados listas Precisa apenas de um tempo O(1) , e a operação de inserção da lista encadeada é, sem dúvida, a operação central da lista encadeada.
Para a estrutura de armazenamento da lista encadeada, simulamos a lista encadeada usando um array. Primeiro, devemos ter um e [N] **idx ** para armazenar os dados da lista encadeada, e o idx serve para e[N] . Depois, há o ponteiro da lista encadeada. Em primeiro lugar, a lista encadeada única deve ter um ponteiro apontando para o próximo nó. Ao mesmo tempo, ela também terá um nó de cabeça de armazenamento de cabeça correspondente. O ponteiro na ligação dupla list é um ponteiro esquerdo e um ponteiro direito. , os nós inicial e final nesses dois ponteiros são representados de maneiras específicas.
Segundo, lista encadeada única
1. A estrutura de uma única lista encadeada
A lista encadeada individualmente é composta de duas partes, uma parte é a parte de armazenamento de dados **e[N] idx **, que é o chamado nó da lista encadeada; a outra parte é a operação do ponteiro, **ne [N] head **, é a cadeia na lista encadeada; a operação da lista encadeada única pode ser considerada como a operação da cadeia e do nó.
O ponteiro da lista vinculada individualmente é avançado e o ponto de cada permanência não é atribuído;
const int N = 100010 ;
int e[N], idx = 0 ;
int ne[N] , head ;
2. Operação de lista encadeada única
1. Operação de inicialização de lista encadeada individualmente
// Basta alterar os dois ponteiros toda vez que você inicializar e os dados originais serão substituídos quando os dados forem armazenados
void init()
{
head = - 1 ;
idx = 0 ;
}
2. Inserir operação de lista encadeada individualmente
operação de inserção
//Primeiro abrimos um nó primeiro, depois precisamos atribuir um valor a este nó, depois alteramos alguns ponteiros deste ponto e depois alteramos o ponteiro do nó principal
void insert_head(int x)
{
e[idx] = x , ne[idx] = head , head = idx ++ ;
}
Insira os primeiros números
//Antes de tudo, podemos saber com base no exposto acima, precisamos saber o ponteiro do item **i - 1**, o ne[i] apontado para , resolva isso ** u ** e pegue isso u como a cabeça .
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, operação de exclusão
//Em primeiro lugar, é a operação mais simples para excluir o nó principal,
podemos atribuir diretamente o nó principal
void remove_head ()
{
head = ne[head] ;
}
Como não somos tão flexíveis quanto um array ao chamar dados em uma lista vinculada, geralmente chamamos apenas o nó principal e as operações de inserção e exclusão são concluídas no nó principal Conhecimento frio: a complexidade de tempo da inserção aleatória em um único vinculado a listaéigual aos outros
dados A estruturaésemelhanteOutro ponto da lista encadeada é que você pode procurar o valor inserido e deletar o valor após n
3. Operação total de lista encadeada única
#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,Aplicação prática de lista encadeada individualmente para armazenar árvore
Árvore de armazenamento de lista encadeada isoladamente, em primeiro lugar, a árvore é composta de nós e arestas, então precisamos entender duas operações, a criação de nós e a criação de arestas;
variável necessária
Nó raiz: h[N] // Existem várias cabeças, então usamos h[N] em vez de nós de borda
: e[N] ,ne[N] ,idx
nó principal criado
Primeiro, o nó principal precisa ser inicializado uma vez, para que todos apontem para -1;
adicionar borda
Basta fazer o chamado h[N] equivalente a cabeça
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 ;
}
Operação de inserção de lista encadeada dupla (inserir no nó inserido)
Nossa operação é inserir o k-1º número inserido
void insert (int k ,int x)
{
e[idx] = x ;
l[idx] = k ;
r[idx] = r[k] ;
l[r[k]] = idx ;
r[k] = idx ++ ;
}
Para concluir a operação de inserção à esquerda, deixe o ponteiro ir para a esquerda uma vez e, em seguida, use essa função de inserção reversa para concluir a operação de inserção.
Excluir operação de lista encadeada dupla
A exclusão da lista encadeada dupla é a operação de tornar os dois lados iguais entre si
//删除第 k - 1 个插入的值
void remove ( int k)
{
l[r[k]] = l[k] ;
r[l[k]] = r[k] ;
}
3. Implementação geral do código
#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. Operação de lista encadeada circular
1. Construção de lista encadeada circular
#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. As outras operações da lista encadeada circular são as mesmas da lista encadeada única
Exemplo Problema de Joseph
n pessoas formam um círculo, começam a contar a partir da primeira pessoa, a pessoa que conta até mm sai, e então a próxima pessoa começa a contar novamente a partir de 11, e a pessoa que conta até mm sai do círculo novamente, e assim por diante, até que todas as pessoas estejam fora do círculo, por favor, imprima os números das pessoas que estão fora do círculo.
#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 ;
}