[Structure des données] Tableau de séquence d'implémentation du langage C (super détaillé)

Table des matières

concept et structure

Implémentation de la fonction d'interface

Initialisation de la table de séquence

Jugement de capacité

 Insérer à la fin de la table de séquence

 Supprimer à la fin de la table de séquence

Insertion d'en-tête de séquence

Supprimer l'en-tête de la séquence

Recherche dans la table de séquence

Insérer à la position spécifiée dans la table de séquence

Supprimer la position spécifiée dans la table de séquence

Tableau de séquence d'impression

Tableau de séquence de destruction

Code complet de la table de séquence


concept et structure

La table séquentielle est un type de table linéaire. Il s'agit d'une structure linéaire qui utilise une unité de stockage avec une adresse physique continue pour stocker les éléments de données en séquence. Généralement, le stockage en tableau est utilisé . Terminez l'ajout, la suppression, la vérification et la modification des données sur la baie.

Le tableau de séquence est généralement divisé en :

1. Table de séquence statique : utilisez un tableau de longueur fixe pour stocker les éléments.

#define N 100
//顺序表的静态存储
typedef int SLDatatype;
typedef struct SeqList
{
	SLDataType Data[N]; //定长数组
	int size;           //有效数据个数
}SeqList;

Cette méthode de stockage présente des limites lors du stockage des données. Lorsque la quantité de données stockées est très petite, la longueur du tableau est trop longue, ce qui entraînera une perte d'espace ; lorsque la quantité de données stockées est très grande, l'espace du tableau peut ne pas être Assez, mais cette méthode de stockage ne peut pas être étendue. Par conséquent, lors de l’implémentation d’une table de séquence, nous utilisons généralement une table de séquence dynamique. Cela peut améliorer notre utilisation de l’espace.

2. Table de séquence dynamique : utilisez des tableaux ouverts dynamiquement pour stocker des éléments.

//顺序表的动态存储
typedef int SLDatatype;
typedef struct SeqList
{
	SLDataType* Data; //定长数组
	int size;         //有效数据个数
	int capacity;     //空间容量的大小
}SeqList;

Implémentation de la fonction d'interface

Initialisation de la table de séquence

//初始化链表
void SLInit(SeqList* ps)
{
	assert(ps);   //判空,如果传入的空指针,后面对它进行解引用就会报错
	ps->data = NULL; //将data初始化为空指针
	ps->capacity = ps->size = 0;
}

Maintenant que l'initialisation de la table de séquence est terminée, l'étape suivante consiste à ajouter, supprimer, vérifier et modifier la table de séquence.

Avant d'implémenter la fonction d'ajout d'éléments à la liste de séquences, nous implémentons d'abord une vérification pour voir si la liste de séquences est pleine. S'il est plein, nous devons l'agrandir.

Jugement de capacité

//容量判断
void Check_Capacity(SeqList* ps)
{
	assert(ps);
	if (ps->capacity == ps->size) //判断顺序表中有效数据个数是否已经达到容量大小
	{
		int new_capacity = ps->capacity == 0 ? 4 : (ps->capacity) * 2;
        //如果容量为0的话,此时就是第一次向顺序表中添加元素,capacity就设为4
        //如果容量不为0,此时就是有效数据个数达到容量,就进行扩容,新容量设置为原容量的2倍
		SLDataType* tmp = (SLDataType*)realloc(ps->data, new_capacity * sizeof(SLDataType));
		if (tmp == NULL)  //如果扩容失败,就终止程序。
		{
			perror("ralloc fail");
			exit(-1);
		}
		ps->data = tmp;
		ps->capacity = new_capacity;
	}
}

La fonction realloc est utilisée pour l'expansion ici. Lorsque nous insérons pour la première fois, le pointeur ps->data est toujours un pointeur nul. À ce stade, nous pouvons également utiliser realloc. Lorsque la fonction realloc est utilisée, si le pointeur entrant est un pointeur nul, sa fonction est la même que celle de malloc. 

 Insérer à la fin de la table de séquence

//顺序表尾插
void SL_PushBack(SL* ps, SLDataType x)
{
	assert(ps);
	Check_Capacity(ps);
	ps->data[ps->size] = x;
	ps->size++;
}

 Supprimer à la fin de la table de séquence

//顺序表尾删
void SL_PopBack(SL* ps)
{
	assert(ps);
	assert(ps->size > 0); //如果顺序表中已经没有元素,那么就不用进行删除,所以
                          //这里需要检查顺序表中是否还有元素。
	ps->size--;
}

 Qu'il s'agisse d'une suppression de queue ou d'une suppression de tête, la table de séquence doit être vérifiée pour voir s'il y a des éléments dans la table.

Insertion d'en-tête de séquence

//顺序表头插
void SL_PushFront(SL* ps, SLDataType x)
{
	assert(ps);
	Check_Capacity(ps); //检查容量
    //将所有数据向后移动一位
	for (int i = ps->size - 1; i >= 0; i--)
	{
		ps->data[i + 1] = ps->data[i];
	}
	ps->data[0] = x;
	ps->size++;
}

Lors de l'insertion de la tête, nous devons non seulement vérifier la capacité, mais également reculer les données d'un bit avant l'insertion, sinon les données seront perdues.

Supprimer l'en-tête de la séquence

//顺序表头删
void SL_PopFront(SL* ps)
{
	assert(ps);
    //如果顺序表中只有一个数据,那么直接将数据个数-1
    //如果对数据进行挪动,会造成越界
	if (ps->size == 1)
	{
		ps->size--;
		return;
	}
    如果数据个数不为1,就将数据中第2个到最后一个都往前移动一位
	for (int i = 1; i < ps->size; i++)
	{
		ps->data[i - 1] = ps->data[i];
	}
	ps->size--;
}

Recherche dans la table de séquence

//顺序表查找
int SL_Find(SeqList* ps, SLDataType x)
{
	assert(ps);
	for (int i = 0; i < ps->size; i++)
	{
		if (ps->data[i] == x)
		{
            //找到就返回下标
			return i;
		}
	}
    //找不到就返回-1
	return -1;
}

Insérer à la position spécifiée dans la table de séquence

//顺序表指定位置插入
void SL_Insert(SeqList* ps, int pos, SLDataType x)
{
	assert(ps);
    //判定pos是否合法
	assert(pos <= ps->size);
	assert(pos >= 0);
	Check_Capacity(ps); //检查容量是否够用
    //将pos位置后的元素全部都向后移动一位
	for (int i = ps->size-1; i >= pos; i--)
	{
		ps->data[i + 1] = ps->data[i];
	}
	ps->data[pos] = x;
	ps->size++;
}

Supprimer la position spécifiée dans la table de séquence

//顺序表指定位置删除
void SL_Erase(SeqList* ps, int pos)
{
	assert(ps);
    //检查pos位置是否合法
	assert(pos >= 0);
	assert(pos < ps->size);
    //将pos位置后面的元素全都向前移动一位
	for (int i = pos; i < ps->size; i++)
	{
		ps->data[i] = ps->data[i + 1];
	}
	ps->size--;
}

Avec l'insertion et la suppression à la position spécifiée dans la table de séquence, nous pouvons réécrire l'insertion et la suppression de la queue et la suppression du bouchon de tête :

//尾插
void SL_PushBack(SeqList* ps, SLDataType x)
{
	SL_Insert(ps, ps->size, x);
}

//尾删
void SL_PopBack(SeqList* ps)
{
	SL_Erase(ps, ps->size - 1);
}
//头插
void SL_PushFront(SeqList* ps, SLDataType x)
{
	SL_Insert(ps, 0, x);
}
//头删
void SL_PopFront(SeqList* ps)
{
	SL_Erase(ps,0);
}

Tableau de séquence d'impression

//打印顺序表
void SLPrint(SeqList* ps)
{
	assert(ps);
	for (int i = 0; i < ps->size; i++)
	{
		printf("%d ", ps->data[i]);
	}
	printf("\n");
}

Tableau de séquence de destruction

//销毁顺序表
void SL_Destroy(SeqList* ps)
{
	assert(ps);
	free(ps->data);
	ps->data = NULL;
	ps->capacity = ps->size = 0;
}

Code complet de la table de séquence

ListeSeq.h

#pragma once
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>

typedef int SLDataType;
typedef struct SeqList
{
	SLDataType* data;
	int size;
	int capacity;
}SeqList;

//初始化顺序表
void SLInit(SeqList* ps);

//删除顺序表
void SL_Destroy(SeqList* ps);

//打印顺序表
void SLPrint(SeqList* ps);

//检查容量
void Check_Capacity(SeqList* ps);

//尾插尾删
void SL_PushBack(SeqList* ps,SLDataType x);
void SL_PopBack(SeqList* ps);

//头插头删
void SL_PushFront(SeqList* ps, SLDataType x);
void SL_PopFront(SeqList* ps);

//顺序表查找
int SL_Find(SeqList* ps, SLDataType x);

//顺序表指定位置插入
void SL_Insert(SeqList* ps, int pos, SLDataType x);

//顺序表指定位置删除
void SL_Erase(SeqList* ps, int pos);

SeqList.c

#include "SeqList.h"

void SLInit(SeqList* ps)
{
	assert(ps);  
	ps->data = NULL; 
	ps->capacity = ps->size = 0;
}

void SL_Destroy(SeqList* ps)
{
	assert(ps);
	free(ps->data);
	ps->data = NULL;
	ps->capacity = ps->size = 0;
}

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

void Check_Capacity(SeqList* ps)
{
	assert(ps);
	if (ps->capacity == ps->size) 
	{
		int new_capacity = ps->capacity == 0 ? 4 : (ps->capacity) * 2;
		SLDataType* tmp = (SLDataType*)realloc(ps->data, new_capacity * sizeof(SLDataType));
		if (tmp == NULL)
		{
			perror("ralloc fail");
			exit(-1);
		}
		ps->data = tmp;
		ps->capacity = new_capacity;
	}
}

void SL_PushBack(SeqList* ps, SLDataType x)
{
	//assert(ps);
	//Check_Capacity(ps);
	//ps->a[ps->size] = x;
	//ps->size++;
	SL_Insert(ps, ps->size, x);
}

void SL_PopBack(SeqList* ps)
{
	//assert(ps);
	//assert(ps->size > 0);
	//ps->size--;
	SL_Erase(ps, ps->size - 1);
}

void SL_PushFront(SeqList* ps, SLDataType x)
{
	//assert(ps);
	//Check_Capacity(ps);
	//for (int i = ps->size - 1; i >= 0; i--)
	//{
	//	ps->a[i + 1] = ps->a[i];
	//}
	//ps->a[0] = x;
	//ps->size++;
	SL_Insert(ps, 0, x);
}

void SL_PopFront(SeqList* ps)
{
	//assert(ps);
	//if (ps->size == 1)
	//{
	//	ps->size--;
	//	return;
	//}
	//for (int i = 1; i < ps->size; i++)
	//{
	//	ps->data[i - 1] = ps->data[i];
	//}
	//ps->size--;
	SL_Erase(ps,0);
}

int SL_Find(SeqList* ps, SLDataType x)
{
	assert(ps);
	for (int i = 0; i < ps->size; i++)
	{
		if (ps->data[i] == x)
		{
			return i;
		}
	}
	return -1;
}

void SL_Insert(SeqList* ps, int pos, SLDataType x)
{
	assert(ps);
	assert(pos <= ps->size);
	assert(pos >= 0);
	Check_Capacity(ps);
	for (int i = ps->size-1; i >= pos; i--)
	{
		ps->data[i + 1] = ps->data[i];
	}
	ps->data[pos] = x;
	ps->size++;
}

void SL_Erase(SeqList* ps, int pos)
{
	assert(ps);
	assert(pos >= 0);
	assert(pos < ps->size);
	for (int i = pos; i < ps->size; i++)
	{
		ps->data[i] = ps->data[i + 1];
	}
	ps->size--;
}

Ce qui précède est tout le contenu lié à la table de séquence, j'espère que cela pourra aider tout le monde.

Je suppose que tu aimes

Origine blog.csdn.net/m0_74459723/article/details/128512663
conseillé
Classement