【Estructura de datos】Tabla lineal|C/C++ realiza la asignación dinámica y estática y las operaciones básicas de la tabla de secuencia|Disposición de notas de estructura de datos de Wang Dao 2021

La estructura física/de almacenamiento de la tabla de secuencia de tabla lineal

[Escrito en el frente] Este blog son las notas del autor organizadas de acuerdo con el curso de video de la Guía de revisión de PubMed de estructura de datos de Wangdao de 2021. Todos ellos han sido probados y factibles con un compilador. Algunas funciones se han mejorado en la solidez del código de acuerdo con las indicaciones del maestro, por lo que puede usarlas con confianza.

1. Conocimiento relevante de la tabla de secuencia

1.1 El concepto de almacenamiento secuencial

almacenamiento secuencial: Se refiere al almacenamiento de elementos lógicamente adyacentes en unidades de almacenamiento físicamente adyacentes, y la relación entre elementos se refleja en la relación de adyacencia de las unidades de almacenamiento.

1.2 Cómo saber el tamaño de un elemento de datos

en lenguaje C comotamaño de (ElemType)
ElemType es el tipo de elemento de datos almacenado en su tabla de secuencia.
p.ej:

sizeof(int)=4B;   
sizeof(Customer)=8B;//Customer为包含两个整型元素的结构体                                                                                                  

En segundo lugar, la implementación de la tabla de secuencia: asignación estática

2.1, asignación estática

 使用数组的方式来存放顺序表,数组的长度大小一旦确定了之后就不可以改变,这是静态数组的特点。
 分配一整片连续的存储空间,大小为MaxSize*sizeof(ElemType)。
#define Maxsize 10           //宏定义一个常量,定义最大长度
typedef struct{
    
    
    ElemType data[MaxSize];  //定义了一个静态数组,大小为Maxsize,用来存放数据元素
    int length;              //顺序表的当前长度
}SqList;                     //Sq表示sequence(顺序、序列)
//自己写代码的时候ElemType是什么类型吧ElemType替换掉就可以了。

2.2 Asignar estáticamente una tabla de secuencias para almacenar datos enteros, inicializar la tabla de secuencias y generar

#include<stdio.h>
#define Maxsize 10 //定义最大长度
typedef struct {
    
    
	int data[Maxsize];  //定义一个长度为Maxsize的数组用来存放数据元素
	int length;         //顺序表的当前长度
}SqList;  

//基本操作——初始化一个顺序表
void InitList(SqList &L) {
    
    
	for (int i = 0;i < Maxsize;i++) {
    
    
		L.data[i] = 0;  //将所有数据元素设置为默认初始值0
	}
	L.length = 0;
}

void PrintList(SqList L) {
    
    
	for (int i = 0;i < Maxsize;i++) {
    
    
		printf("%d  ",L.data[i]);
	}
	printf("\n%d  ", L.length);
}

int main() {
    
    
	SqList L;    //声明一个顺序表
	InitList(L);  //初始化顺序表
	PrintList(L);
	return 0;
}

Contenido de la impresión:
inserte la descripción de la imagen aquí

2.3 [Nota] Si el valor inicial no se asigna a los datos [i], se enviarán los datos sucios que quedan en la memoria.

La prueba es la siguiente. Cambie la función de inicialización en el código anterior a la siguiente, compile y pruebe, y el resultado es el siguiente.

//基本操作——初始化一个顺序表
void InitList(SqList &L) {
    
    
	//for (int i = 0;i < Maxsize;i++) {
    
    
	//	L.data[i] = 0;  //将所有数据元素设置为默认初始值0
	//}
	L.length = 0;
}

Imprimir contenido de salida:
inserte la descripción de la imagen aquí
[Nota] De hecho, el método anterior para acceder a la matriz con i<Maxsize es ilegal, pero se debe acceder con i<longitud, porque no debe acceder desde el primer elemento hasta el último elemento, pero debe acceder al último elemento de la longitud real almacenada actualmente.

2.4, otras notas

1. 给各个数据元素设置默认值的步骤可以省略,因为按正常的访问方式的话,
   其实不应该访问超过顺序表实际长度的数据元素。
   这种访问方式也不够好,更好的做法是使用基本操作来访问各个数据元素。
3. Q:C语言不是会自动给int型的变量设置初始值为0吗?
   A:设置初始值是编译器做的事情,换一个C语言的编译器可能不会帮你做初始化的工作。
      所以当我们声明一个顺序表的时候,把它的length值设置为0这一步是必须做的。
4. Q:如果数组存满了怎么办?
   A:直接放弃治疗,顺序表的表长一旦确定了就无法更改。(存储空间是静态的)
5. Q:如果刚开始就声明一块很大的存储空间,存在什么问题?
   A:很浪费。

3. Implementación de tabla de secuencia: asignación dinámica

3.1, asignación dinámica

La tabla de secuencia para definir una asignación dinámica con código es la siguiente:

#define InitSize 10     //定义顺序表的初始长度
typedef struct {
    
        
ElemType *data;     //指示动态分配数组的指针      
int MaxSize;        //顺序表的最大容量    
int length;         //顺序表的当前长度
 }SeqList;         //顺序表的定义类型(动态分配方式) 

3.2 La clave de la asignación dinámica: aplicación dinámica y liberación de espacio de memoria - el uso de malloc y funciones libres

El lenguaje C proporciona funciones malloc y free para aplicar y liberar espacio de memoria dinámicamente.Las dos funciones malloc y free están contenidas enstdlib.hen este archivo de cabecera. En C++, las palabras clave new y delete se utilizan para realizar las funciones anteriores.

2.1 función malloc

L.data=(ElemType*)malloc(sizeof(ElemType)*InitSize);

Formato: L.data=(Tipo de elemento*)malloc(sizeof(ElemType)*InitSize);

Función: Asignar una pieza completa de espacio de memoria contiguo. Luego devuelva un puntero a la dirección inicial de este espacio de almacenamiento. Debe convertirse en un puntero al tipo de elemento de datos que defina. data es un puntero a la dirección inicial de este espacio de almacenamiento.

Los parámetros de la función malloc: especifican cuánto espacio de memoria continua asignar. Por ejemplo, lo anterior es para asignar el espacio de memoria de los elementos InitSize cuyo tamaño es sizeof(ElemType).

3.3 Ampliar el espacio de memoria de la tabla de secuencia de asignación dinámica

Asigne dinámicamente una tabla de secuencia para almacenar datos enteros, inicialice la tabla de secuencia, expanda el espacio de memoria de la tabla de secuencia en 5 y genere

#include<stdio.h>
#include<stdlib.h>
#define InitSize 10 //定义最大长度
typedef struct {
    
    
	int *data;          //指示动态分配数组的指针  
	int MaxSize;        //顺序表的最大容量
	int length;         //顺序表的当前长度
}SeqList;               //顺序表的定义类型(动态分配方式)  

//基本操作——初始化一个顺序表
void InitList(SeqList &L) {
    
    
	//用malloc函数申请一片连续的存储空间
	L.data = (int *)malloc(sizeof(int)*InitSize);
	L.length = 0;
	L.MaxSize = InitSize;
}

//增加动态数组的长度
void IncreaseSize(SeqList &L,int len) {
    
    
	int *p = L.data;
	L.data = (int *)malloc(sizeof(int)*(L.MaxSize+len));//新申请一篇长度为Maxsize+len的区域
	for (int i = 0;i < L.length;i++) {
    
    
		L.data[i] = p[i];//将数据复制到新区域
	}
	L.MaxSize = L.MaxSize + len;
	free(p); //free(p)用来释放p指向的内存空间,由于p是在函数内的局部指针变量,在函数执行完后,存放指针p的内存空间也会被自动释放。
}


void PrintList(SeqList L) {
    
    
	for (int i = 0;i < L.MaxSize;i++) {
    
    
		printf("%d  ",L.data[i]);
	}
	printf("\n%d  ", L.length);
}

int main() {
    
    
	SeqList L;    //声明一个顺序表
	InitList(L);  //初始化顺序表
	IncreaseSize(L,5);
	PrintList(L);
	return 0;
}

El contenido de la impresión compilado en VS:
inserte la descripción de la imagen aquí
proceso de creación de memoria:
inserte la descripción de la imagen aquí

En cuarto lugar, las características de la tabla de secuencia.

  1. Acceso aleatorio: el i-ésimo elemento se puede encontrar en el tiempo O(1) (el código se implementa como datos[i-1], la asignación estática y la asignación dinámica son las mismas).
  2. Alta densidad de almacenamiento: cada nodo solo almacena elementos de datos (mientras que el almacenamiento encadenado también almacena punteros al siguiente elemento de datos).
  3. Es un inconveniente expandir la capacidad (el método de asignación estática no puede expandir la capacidad, incluso si se usa el método de asignación dinámica, la complejidad del tiempo para expandir la longitud es relativamente alta).
  4. Las operaciones de inserción y eliminación son inconvenientes y es necesario mover una gran cantidad de elementos.

Cinco, el funcionamiento básico de la tabla de secuencia.

5.1, operación de inserción (asignación estática)

//基本操作:插入元素
void ListInsert(SqList &L, int i, int e) {
    
    
	for (int j = L.length;j >= i;j--) {
    
    
		L.data[j] = L.data[j - 1];
	}
	L.data[i - 1] = e;
	L.length++;
}

Para aumentar la robustez del código, después de la modificación:

//基本操作:插入元素
bool ListInsert(SqList &L, int i, int e) {
    
    
	if(i<1|| i>L.length+1){
    
      //判断i的范围是否有效,无效返回false
		return false;
	}
	if (L.length >= Maxsize) {
    
       //当前存储空间已满,不能插入
		return false;
	}
	for (int j = L.length;j >= i;j--) {
    
    
		L.data[j] = L.data[j - 1];
	}
	L.data[i - 1] = e;
	L.length++;
	return true;
}

Análisis de complejidad temporal: bucle más profundo L.data[j] = L.data[j - 1],
mejor O(1), peor O(n), promedio O(n).

5.2 Operación de borrado

//基本操作:删除位序为i的元素
bool ListDelete(SqList &L, int i, int &e) {
    
    
	if (i<1 || i>L.length) {
    
    
		return false;
	}
	e = L.data[i - 1];
	for (int j = i;j < L.length;j++) {
    
    
		L.data[j - 1] = L.data[j];
	}
	L.length--;
	return true;
}

Análisis de complejidad temporal:
mejor O(1), peor O(n), promedio O(n).

5.3 Búsqueda bit a bit: complejidad temporal O(1)

//基本操作:按位查找
int GetElem(SqList L,int i) {
    
    
	return L.data[i - 1];//动态和静态都是用这一条查找
}

5.4 Búsqueda por valor: mejor tiempo complejidad O(1), peor O(n), promedio O(n)

int LocateElem(SeqList L, int e) {
    
    
	for (int i = 0;i < L.length;i++) {
    
    
		if (L.data[i] == e)   //基本数据类型如bool、double等都可以直接用==来比较但是结构体不可以,结构体需要写专门的判断语句来逐一判断其中的元素是否相等
			return i + 1;
	}
	return 0;
}

6. Código de prueba

Por razones de espacio, el autor pone el código de prueba en otra publicación de blog, y el enlace es [Estructura de datos (2)] Tabla lineal | Tabla de secuencia | Código de prueba (completo) | Use lenguaje C/C++ para implementar operaciones básicas como definición, inserción, eliminación, búsqueda e impresión de tablas de secuencia dinámicas y estáticas . Todos han sido probados y ejecutados en el compilador VS, incluidas las pruebas para todas las operaciones básicas anteriores.

Supongo que te gusta

Origin blog.csdn.net/dxy1128/article/details/107951674
Recomendado
Clasificación