Prefiro confiar na minha própria força para abrir o meu futuro do que buscar o favor dos poderosos
Diretório de artigos
O nome da função ou nome da variável de cada interface da lista vinculada de fio duplo
Código-fonte de implementação da interface de lista duplamente vinculada
Índice rápido [arquivos de cabeçalho e declarações de função]
Implementação de interface de lista duplamente vinculada
Análise de Construção de Lista Duplamente Vinculada
Definição e inicialização de lista duplamente vinculada
Inserção e exclusão de lista duplamente vinculada
Revisão anterior:
Estrutura de dados - lista vinculada individualmente
Estrutura de Dados - Lista de Sequências
Olá a todos, meu nome é Ji Ning.
Este artigo apresenta uma lista vinculada com melhor desempenho do que uma única lista vinculada - uma lista duplamente vinculada, que pode implementar com mais eficiência a inserção, exclusão e pesquisa de dados.
A primeira metade do artigo é o nome e o código-fonte correspondentes da lista duplamente vinculada, e a segunda metade do artigo é uma explicação específica da implementação da lista duplamente vinculada.
O nome da função ou nome da variável de cada interface da lista vinculada de fio duplo
LTDDataType | Renomeação de tipo de dados de lista duplamente vinculada |
ListaNode | estrutura de lista duplamente vinculada |
LTNode | Renomeação de lista duplamente vinculada |
ComprarLTNode | criar um nó |
LTI | inicializar nó |
LTPrint | imprimir lista duplamente vinculada |
LTPushBack | plugue de cauda |
LTPopBack | exclusão de cauda |
LTPushFront | plugue |
LTPopFront | exclusão de cabeça |
Tamanho LTS | Calcule o número de elementos da lista duplamente vinculada |
LTFencontrar | Encontre elementos da lista vinculada |
LTInserir | insira o nó antes da posição |
LTErase | Exclua o nó na posição pos |
Código-fonte de implementação da interface de lista duplamente vinculada
Índice rápido [arquivos de cabeçalho e declarações de função]
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
typedef int LTDataType;//重命名
typedef struct ListNode
{
LTDataType Data;
struct ListNode* next;
struct ListNode* prev;
}LTNode;
LTNode* BuyLTNode(LTDataType x); //创建一个新节点
LTNode* LTInit(); //哨兵位的头结点
void LTPrint(LTNode*phead);//打印双链表
void LTPushBack(LTNode* phead, LTDataType x);//尾插
void LTPopBack(LTNode* phead);//尾删
void LTPushFront(LTNode* phead, LTDataType x);//头插
void LTPopFront(LTNode* phead);//头删
LTNode* LTFind(LTNode* phead, LTDataType x);//寻找结点
void LTInsert(LTNode*phead,LTNode* pos, LTDataType x); //在pos之前插入结点
Implementação de interface de lista duplamente vinculada
LTNode* BuyLTNode(LTDataType x)
{
LTNode* nownode =(LTNode*)malloc(sizeof(LTNode));
if (nownode == NULL)
{
perror("malloc fail");
}
nownode->Data = x;
nownode->next = NULL;
nownode->prev = NULL;
return nownode;
}
LTNode* LTInit()
{
LTNode* phead = BuyLTNode(0);
phead->next = phead;
phead->prev = phead;
return phead;
}
void LTPushBack(LTNode* phead, LTDataType x)
{
assert(phead);
LTNode* tail = phead->prev;
LTNode* nownode = BuyLTNode(x);
nownode->next = phead;
nownode->prev = tail;
tail->next = nownode;
phead->prev = nownode;
}
void LTPrint(LTNode* phead)
{
assert(phead);
printf("phead<=>");
LTNode* cur = phead;
while (cur->next!=phead)
{
printf("%d<=>", cur->next->Data);
cur = cur->next;
}
printf("\n");
}
void LTPopBack(LTNode* phead)
{
assert(phead);
assert(phead->next != phead);//只有哨兵位的时候不能删
LTNode* tail = phead->prev;
LTNode* tailPrev = tail->prev;
tailPrev->next = tail->next;
phead->prev = tailPrev;
free(tail);
}
void LTPushFront(LTNode* phead, LTDataType x)
{
assert(phead);
LTNode* first = phead->next;
LTNode* nownode = BuyLTNode(x);
nownode->next = first;
nownode->prev = phead;
phead->next = nownode;
first->prev = nownode;
}
void LTPopFront(LTNode* phead)
{
assert(phead);
assert(phead->next != phead);//只有哨兵位的时候不能删除
LTNode* first = phead->next;
LTNode* second = first->next;
phead->next = second;
second->prev = phead;
free(first);
}
LTNode* LTFind(LTNode* phead, LTDataType x)
{
assert(phead);
LTNode* cur = phead;
while (cur->next != phead)
{
if (cur->next->Data == x)
return cur->next;
cur = cur->next;
}
return NULL;
}
void LTInsert(LTNode* phead, LTNode* pos, LTDataType x)
{
assert(phead);
assert(pos);
LTNode* cur = phead;
while (cur->next != pos)
{
cur = cur->next;
}
LTNode*nownode = BuyLTNode(x);
nownode->next = pos;
nownode->prev = cur;
cur->next = nownode;
pos->prev = nownode;
}
void LTErase(LTNode* phead, LTNode* pos)
{
assert(pos&&phead);
assert(pos->next != pos);
assert(phead->next != phead);
LTNode* cur = phead;
LTNode* posNext = pos->next;
while (cur->next != pos)
{
cur = cur->next;
}
cur->next = posNext;
posNext->prev = cur;
free(pos);
}
Análise de Construção de Lista Duplamente Vinculada
Lista duplamente vinculada, em comparação com a lista vinculada única, o nó da lista duplamente vinculada tem dois domínios de ponteiro, um apontando para o próximo nó, o outro apontando para o nó anterior, a lista duplamente vinculada padrão tem um nó principal com um bit sentinela, a cabeça do bit sentinela O nó armazena o endereço do primeiro nó válido (phead->next) e o endereço do último nó válido (phead->prev).
Comparação de diagramas lógicos de lista vinculada simples e dupla
Comparação de diagramas físicos de listas vinculadas simples e duplas
Definição e inicialização de lista duplamente vinculada
Há um campo de dados e dois campos de ponteiro na lista duplamente vinculada, um ponteiro aponta para o endereço do próximo nó e um ponteiro aponta para o endereço do nó anterior, e a estrutura da lista duplamente vinculada é renomeada novamente.
Quando uma lista duplamente vinculada abre um novo nó, primeiro ela precisa abrir um espaço do tamanho de um nó, apontar seu próximo e NULL para vazio e, em seguida, atribuir seu valor de campo de dados a x.
Inserção e exclusão de lista duplamente vinculada
Para deletar a lista duplamente vinculada, a primeira coisa a ficar clara é que o nó cabeça do bit sentinela não pode ser deletado, pois é o suporte estrutural de toda a lista duplamente vinculada. Ao excluir, encontre o nó anterior e o próximo nó do nó a ser excluído, aponte o próximo ponteiro do nó anterior para o próximo nó e aponte o ponteiro anterior do próximo nó para o nó anterior. Finalmente, o espaço do nó excluído é liberado.
A inserção de uma lista duplamente vinculada, ao inserir, pode teoricamente inserir um nó em qualquer posição. Porque no momento da inicialização, os campos de ponteiro que definem os nós recém-criados estão todos vazios. Portanto, ao inserir, é necessário alterar os dois campos de ponteiro do nó inserido, apontar seu próximo ponteiro para o próximo nó e fazer com que seu ponteiro anterior aponte para o nó anterior. Da mesma forma, aponte o próximo ponteiro do nó anterior para este novo nó e aponte o ponteiro anterior do próximo ponteiro para este novo nó.