[estructura de datos] lista secuencial, lista enlazada


提示:以下是本篇文章正文内容,下面案例可供参考

1. Tabla de secuencias

La tabla de secuencia es una estructura lineal en la que los elementos de datos se almacenan secuencialmente en una unidad de almacenamiento con direcciones físicas continuas y generalmente se almacenan en una matriz. Agregue, elimine, verifique y modifique datos en la matriz.
Hay dos métodos de implementación: tabla de secuencia estática (matriz) y tabla de secuencia dinámica (desarrollo dinámico).
Dado que el tamaño de la matriz es fijo, es fácil desperdiciar espacio, por lo que la tabla de secuencia dinámica es una mejor opción.

implementación de la interfaz

SeqList.h

#pragma once

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>

typedef int SLDataType;
typedef struct SeqList
{
    
    
	SLDataType* a;
	int size;       // 记录存储多少个有效数据
	int capacity;   // 空间容量大小 
}SL;

void SLPrint(SL* ps);
void SLInit(SL* ps);
void SLDestroy(SL* ps);
void SLCheckCapacity(SL* ps);

// 尾插尾删
void SLPushBack(SL* ps, SLDataType x);
void SLPopBack(SL* ps);

// 头插头删
void SLPushFront(SL* ps, SLDataType x);
void SLPopFront(SL* ps);

// 中间插入删除
// 在pos位置插入数据
void SLInsert(SL* ps, int pos, SLDataType x);
// 删除pos位置数据
void SLErase(SL* ps, int pos);

//int SLFind(SL* ps, SLDataType x);

// begin查找x的起始位置
int SLFind(SL* ps, SLDataType x, int begin);

SeqList.c

#include "SeqList.h"

void SLInit(SL* ps)
{
    
    
	assert(ps);

	ps->a = NULL;
	ps->size = 0;
	ps->capacity = 0;
}

void SLCheckCapacity(SL* ps)
{
    
    
	assert(ps);

	if (ps->size == ps->capacity)
	{
    
    
		int newcapacity = ((ps->capacity == 0) ? 4 : 2 * ps->capacity);
		SLDataType* tmp = (SLDataType*)realloc(ps->a, newcapacity * sizeof(SLDataType) * 2);
		if (tmp==NULL)
		{
    
    
			perror("realloc fail!");
			exit(-1);
		}
		ps->capacity = newcapacity;
		ps->a = tmp;
	}
}

void SLPushBack(SL* ps, SLDataType x)
{
    
    
	//assert(ps);

	//SLCheckCapacity(ps);
	//ps->a[ps->size] = x;
	//ps->size++;
	SLInsert(ps, ps->size, x);
}

void SLPopBack(SL* ps)
{
    
    
	//assert(ps);
	//assert(ps->size > 0);

	//ps->a[ps->size - 1] = 0;
	//ps->size--;
	SLErase(ps, ps->size - 1);
}

void SLPushFront(SL* ps, SLDataType x)
{
    
    
	//assert(ps);

	//SLCheckCapacity(ps);
	//int i = 0;
	//for (i = ps->size - 1; i >= 0; i--)
	//{
    
    
	//	ps->a[i+1] = ps->a[i];
	//}
	//ps->a[0] = x;
	//ps->size++;
	SLInsert(ps, 0, x);
}

void SLPopFront(SL* ps)
{
    
    
	//assert(ps);
	//assert(ps->size > 0);

	//int i = 0;
	//for (i = 1; i < ps->size; i++)
	//{
    
    
	//	ps->a[i - 1] = ps->a[i];
	//}
	//ps->size--;

	SLErase(ps, 0);
}

void SLInsert(SL* ps, int pos, SLDataType x)
{
    
    
	assert(ps);
	assert(pos >= 0);
	assert(pos <= ps->size);

	SLCheckCapacity(ps);
	int i = ps->size - 1;
	for (i = ps->size - 1; i >= pos; i--)
	{
    
    
		ps->a[i + 1] = ps->a[i];
	}
	ps->a[pos] = x;
	ps->size++;
}

void SLErase(SL* ps, int pos)
{
    
    
	assert(ps);
	assert(pos >= 0);
	assert(pos < ps->size);

	int i = pos+1;
	for (i = pos+1; i < ps->size; i++)
	{
    
    
		ps->a[i - 1] = ps->a[i];
	}
	ps->size--;
}

void SLPrint(SL* ps)
{
    
    
	int i = 0;
	for (i = 0; i < ps->size; i++)
	{
    
    
		printf("%d ", ps->a[i]);
	}
	printf("\n");
}

void SLDestroy(SL* ps)
{
    
    
	assert(ps);

	if (ps->a)
	{
    
    
		free(ps->a);
		ps->a = NULL;
		ps->size = 0;
		ps->capacity = 0;
	}
}

int SLFind(SL* ps, SLDataType x, int begin)
{
    
    
	assert(ps);

	int i = 0;
	for (i = begin; i < ps->size; i++)
	{
    
    
		if (ps->a[i] == x)
		{
    
    
			return i;
		}
	}
	return -1;
}

tema

1. Eliminar elementos

Dada una matriz nums y un valor val, debe eliminar todos los elementos cuyo valor sea igual a val en su lugar y devolver la nueva longitud de la matriz eliminada.
No use espacio adicional en la matriz, debe usar solo O (1) espacio adicional y modificar la matriz de entrada en el lugar.
El orden de los elementos se puede cambiar. No necesita considerar elementos en la matriz más allá de la nueva longitud.

int removeElement(int* nums, int numsSize, int val){
    
    
    int right=0;
    int left=0;
    for(right=0;right<numsSize;right++)
    {
    
    
        if(nums[right]!=val)
        {
    
    
            nums[left]=nums[right];
            left++;
        }
    }
    return left;
}

2. Eliminar duplicados en una matriz ordenada

Dados los números de una matriz en orden ascendente, elimine los elementos repetidos en su lugar para que cada elemento aparezca solo una vez y devuelva la nueva longitud de la matriz eliminada. El orden relativo de los elementos debe ser coherente.
Dado que la longitud de la matriz no se puede cambiar en algunos idiomas, el resultado debe colocarse en la primera parte de la matriz nums. Más canónicamente, si hay k elementos después de eliminar los duplicados, entonces los primeros k elementos de nums deberían contener el resultado final.
Devuelve k después de insertar el resultado final en las primeras k posiciones de nums.
En lugar de usar espacio adicional, debe modificar la matriz de entrada en el lugar y hacerlo usando O (1) espacio adicional.

int removeDuplicates(int* nums, int numsSize){
    
    
    int fast=0;
    int slow=0;
     while(fast<numsSize)
     {
    
    
       if(nums[fast]==nums[slow])
       {
    
    
           fast++;
       }  
       else
       {
    
    
           slow++;
           nums[slow]=nums[fast];
           fast++;
       }
     }
     return slow+1;
}

Dos, lista enlazada

La lista enlazada es una estructura de almacenamiento no continua y no secuencial en la estructura de almacenamiento físico.El orden lógico de los elementos de datos se realiza a través del orden de enlace de los punteros en la lista enlazada.

implementación de la interfaz

1. Lista enlazada simple

inserte la descripción de la imagen aquí

Slist.h

#pragma once

#include <stdio.h>
#include <assert.h>
#include <stdlib.h>

typedef int SLTDateType;
typedef struct SListNode
{
    
    
	SLTDateType data;
	struct SListNode* next;
}SListNode;
 
// 动态申请一个节点
SListNode* BuySListNode(SLTDateType x);
// 单链表打印
void SListPrint(SListNode* plist);
// 单链表尾插
void SListPushBack(SListNode** pplist, SLTDateType x);
// 单链表的头插
void SListPushFront(SListNode** pplist, SLTDateType x);
// 单链表的尾删
void SListPopBack(SListNode** pplist);
// 单链表头删
void SListPopFront(SListNode** pplist);
// 单链表查找
SListNode* SListFind(SListNode* plist, SLTDateType x);

// 单链表在pos位置之后插入x
// 分析思考为什么不在pos位置之前插入?
void SListInsertAfter(SListNode* pos, SLTDateType x);
//在pos之前插入值
void SListInsert(SListNode** pphead, SListNode* pos, SLTDateType x);

// 单链表删除pos位置之后的值
// 分析思考为什么不删除pos位置?
void SListEraseAfter(SListNode* pos);
//删除pos位置的值
void SListErase(SListNode** pphead, SListNode* pos);
// 单链表的销毁
void SListDestroy(SListNode** plist);

SListNode* CreateSList(int n);

lista.c

#include "Slist.h"

SListNode* BuySListNode(SLTDateType x)
{
    
    
	SListNode* newnode = (SListNode*)malloc(sizeof(SListNode));
	if (newnode == NULL)
	{
    
    
		perror("malloc fail");
		exit(-1);
	}
	newnode->data = x;
	newnode->next = NULL;
	return newnode;
}

SListNode* CreateSList(int n)
{
    
    
	SListNode* phead = NULL, * ptail = NULL;
	int i = 0;
	for (i = 0; i < n; i++)
	{
    
    
		SListNode* newnode = BuySListNode(i);
		if (phead == NULL)
		{
    
    
			phead = ptail = newnode;
		}
		else
		{
    
    
			ptail->next = newnode;
			ptail = newnode;
		}
	}
	return phead;
}

void SListPrint(SListNode* plist)
{
    
    
	SListNode* cur = plist;
	while (cur != NULL)
	{
    
    
		printf("%d ", cur->data);
		cur = cur->next;
	}
	printf("NULL");
}

void SListPushBack(SListNode** pplist, SLTDateType x)
{
    
    
	SListNode* newnode = BuySListNode(x);
	if (*pplist == NULL)
	{
    
    
		*pplist = newnode;
	}
	else
	{
    
    
		SListNode* tail = *pplist;
		while (tail->next)
		{
    
    
			tail = tail->next;
		}
		tail->next = newnode;
	}
}

void SListPopBack(SListNode** pplist)
{
    
    
	assert(*pplist);
	if ((*pplist)->next == NULL)
	{
    
    
		free(*pplist);
		*pplist = NULL;
	}
	else
	{
    
    
		SListNode* prev = NULL;
		SListNode* tail = *pplist;
		while (tail->next)
		{
    
    
			prev = tail;
			tail = tail->next;
		}
		free(tail);
		prev->next = NULL;
	}
}

void SListPushFront(SListNode** pplist, SLTDateType x)
{
    
    
	SListNode* newnode = BuySListNode(x);
	newnode->next = *pplist;
	*pplist = newnode;
}

void SListPopFront(SListNode** pplist)
{
    
    
	assert(*pplist);
	SListNode* next = *pplist;
	free(*pplist);
	*pplist = next;
}

SListNode* SListFind(SListNode* plist, SLTDateType x)
{
    
    
	assert(plist);
	SListNode* cur = plist;
	while (cur)
	{
    
    
		if (cur->data == x)
		{
    
    
			return cur;
		}
		cur = cur->next;
	}
	return NULL;
}

//在pos后插入数据
void SListInsertAfter(SListNode* pos, SLTDateType x)
{
    
    
	assert(pos);

	SListNode* newnode = BuySListNode(x);
	SListNode* next = pos->next;
	pos->next = newnode;
	newnode->next = next;
}

//在pos之前插入值
void SListInsert(SListNode** pphead, SListNode* pos, SLTDateType x)
{
    
    
	assert(pos);

	if (*pphead == pos)
	{
    
    
		SListPushFront(pphead, x);
	}
	else
	{
    
    
		SListNode* newnode = BuySListNode(x);
		SListNode* prev = *pphead;
		while (prev->next != pos)
		{
    
    
			prev = prev->next;
		}
		prev->next = newnode;
		newnode->next = pos;
	}
}

void SListEraseAfter(SListNode* pos)
{
    
    
	assert(pos);

	if (pos->next == NULL)
	{
    
    
		return;
	}
	else
	{
    
    
		SListNode* nextnode = pos->next;
		pos->next = nextnode->next;
		free(nextnode);
	}
}

//删除pos位置的值
void SListErase(SListNode** pphead, SListNode* pos)
{
    
    
	assert(pos);
	assert(*pphead);

	if (pos == *pphead)
	{
    
    
		SListPopFront(pphead);
	}
	else
	{
    
    
		SListNode* prev = *pphead;
		while (prev->next != pos)
		{
    
    
			prev = prev->next;
		}
		prev->next = pos->next;
		free(pos);
	}
}

void SListDestroy(SListNode** pplist)
{
    
    
	SListNode* cur = *pplist;
	while (cur)
	{
    
    
		SListNode* next = cur->next;
		free(cur);
		cur = next;
	}
	*pplist = NULL;
}

2. Lista doblemente enlazada con bit centinela

inserte la descripción de la imagen aquí

Lista.h

#pragma once
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
#include <stdbool.h>

typedef int LTDataType;

typedef struct ListNode
{
    
    
	struct ListNode* next;
	struct ListNode* prev;
	LTDataType data;
}LTNode;

LTNode* BuyListNode(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);

//在pos之前插入
void LTInsert(LTNode* pos, LTDataType x);

void LTErase(LTNode* pos);

bool LTEmpty(LTNode* phead);
size_t LTSize(LTNode* phead);
void LTDestroy(LTNode* phead);

Lista.c

#include "List.h"

LTNode* BuyListNode(LTDataType x)
{
    
    
	LTNode* node = (LTNode*)malloc(sizeof(LTNode));
	if (node == NULL)
	{
    
    
		perror("malloc fail");
		exit(-1);
	}
	node->data = x;
	node->next = NULL;
	node->prev = NULL;

	return node;
}

LTNode* LTInit()
{
    
    
	LTNode* phead = BuyListNode(-1);
	phead->next = phead;
	phead->prev = phead;

	return phead;
}

void LTPrint(LTNode* phead)
{
    
    
	assert(phead);

	LTNode* cur = phead->next;
	while (cur != phead)
	{
    
    
		printf("%d ", cur->data);
		cur = cur->next;
	}
	printf("\n");
}

void LTPushBack(LTNode* phead, LTDataType x)
{
    
    
	assert(phead);

	/*LTNode* newnode = BuyListNode(x);
	LTNode* prev = phead->prev;

	phead->prev = newnode;
	newnode->next = phead;
	newnode->prev = prev;
	prev->next = newnode;*/

	LTInsert(phead, x);
}

void LTPopBack(LTNode* phead)
{
    
    
	assert(phead);
	assert(phead->next != phead);

	/*LTNode* tail = phead->prev;
	phead->prev = tail->prev;
	tail->prev->next = phead;
	free(tail);*/

	LTErase(phead->prev);
}

void LTPushFront(LTNode* phead, LTDataType x)
{
    
    
	assert(phead);
	/*LTNode* newnode = BuyListNode(x);

	LTNode* head = phead->next;
	phead->next = newnode;
	newnode->prev = phead;
	newnode->next = head;
	head->prev = newnode;*/
	LTInsert(phead->next, x);
}

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);*/
	LTErase(phead->next);
}

LTNode* LTFind(LTNode* phead, LTDataType x)
{
    
    
	assert(phead);

	LTNode* cur = phead->next;
	while (cur != phead)
	{
    
    
		if (cur->data == x)
		{
    
    
			return cur;
		}
		cur = cur->next;
	}
	return NULL;
}

//在pos之前插入
void LTInsert(LTNode* pos, LTDataType x)
{
    
    
	assert(pos);

	LTNode* newnode = BuyListNode(x);
	LTNode* prev = pos->prev;
	prev->next = newnode;
	newnode->prev = prev;
	newnode->next = pos;
	pos->prev = newnode;
}

//删除pos位置的值
void LTErase(LTNode* pos)
{
    
    
	assert(pos);

	LTNode* prev = pos->prev;
	LTNode* next = pos->next;
	prev->next = next;
	next->prev = prev;
	free(pos);
}

bool LTEmpty(LTNode* phead)
{
    
    
	assert(phead);
	return phead->next == phead;
}

size_t LTSize(LTNode* phead)
{
    
    
	assert(phead);
	size_t size = 0;
	LTNode* cur = phead->next;
	while (cur != phead)
	{
    
    
		size++;
		cur = cur->next;
	}
	return size;
}

void LTDestroy(LTNode* phead)
{
    
    
	assert(phead);
	LTNode* cur = phead->next;
	while (cur != phead)
	{
    
    
		LTNode* next = cur->next;
		free(cur);
		cur = next;
	}
	free(phead);
}

tema

Aquí hay una pregunta más completa directamente

copiar lista enlazada con punteros aleatorios

Dada una lista enlazada de longitud n, cada nodo contiene un puntero aleatorio adicional aleatorio, que puede apuntar a cualquier nodo de la lista enlazada o a un nodo vacío.
Construye una copia profunda de esta lista enlazada. Una copia profunda debe constar de exactamente n nodos completamente nuevos, donde el valor de cada nuevo nodo se establece en el valor de su correspondiente nodo original. Tanto el puntero siguiente como el puntero aleatorio del nuevo nodo también deben apuntar al nuevo nodo en la lista enlazada copiada, de modo que estos punteros en la lista enlazada original y la lista enlazada copiada puedan representar el mismo estado de lista enlazada. Los punteros de la lista enlazada copiada no deben apuntar a los nodos de la lista enlazada original.
Por ejemplo, si hay dos nodos X e Y en la lista enlazada original, donde X.random --> Y. Luego, los dos nodos x e y correspondientes en la lista de copia enlazada también tienen x.random --> y.
Devuelve el nodo principal de la lista copiada.
Una lista enlazada en entrada/salida está representada por una lista enlazada de n nodos. Cada nodo está representado por un [val, índice_aleatorio]:
val: un número entero que representa Node.val.
random_index: el índice del nodo al que apunta el puntero aleatorio (que va de 0 a n-1); nulo si no apunta a ningún nodo.
Su código solo acepta el encabezado del nodo principal de la lista vinculada original como parámetro entrante.

Dar mi idea:

  1. Se prefiere insertar un nodo de copia después de cada nodo, almacenando el mismo valor que el nodo anterior
  2. El nodo al que apunta random en el nodo de copia es el siguiente del nodo aleatorio del nodo de origen
  3. Haga una lista vinculada nuevamente e inserte los nodos copiados anteriormente en la nueva lista vinculada continuamente
struct Node* copyRandomList(struct Node* head) {
    
    
	struct Node* cur=head;
	//复制节点
    while(cur)
    {
    
    
        struct Node* copy=(struct Node*)malloc(sizeof(struct Node));
        struct Node* next=cur->next;
        copy->val=cur->val;
        cur->next=copy;
        copy->next=next;
        cur=next;
    }
    cur=head;
    //复制random
    while(cur)
    {
    
    
        struct Node* copy=cur->next;
        if(cur->random==NULL)
        {
    
    
            copy->random=NULL;
        }
        else
        {
    
    
            copy->random=cur->random->next;
        }
        cur=cur->next->next;
    }

     struct Node* copyhead=NULL,*copytail=NULL;
     cur=head;
     //复制节点单独拿出来
     while(cur)
     {
    
    
         struct Node* copy=cur->next;
         struct Node* next=copy->next;
         cur->next=next;
         if(copyhead==NULL)
         {
    
    
             copyhead=copytail=copy;
         }
         else
         {
    
    
             copytail->next=copy;
             copytail=copytail->next;
         }
         
         cur=next;
     }

     return copyhead;
}

Supongo que te gusta

Origin blog.csdn.net/lyq2632750277/article/details/128433707
Recomendado
Clasificación