El concepto básico y la realización de la tabla lineal.
1. Definición de tabla lineal
Una tabla lineal es una secuencia finita de elementos de datos con las mismas características .
El número de elementos se denomina longitud de la tabla lineal, n (n> = 0) significa, n = 0 (tabla vacía)
2. Características lógicas de tablas lineales.
Solo hay un elemento de encabezado y solo un elemento de cola. No hay predecesor en el encabezado ni sucesor en la cola. Excepto el encabezado y el pie de página, los otros elementos tienen un solo precursor directo y un solo sucesor directo.
3. Estructura de almacenamiento de la mesa lineal.
Hay dos tipos de estructura de almacenamiento secuencial (lista de secuencias) y estructura de almacenamiento en cadena (lista vinculada).
Tabla de secuencia
Almacenamiento continuo, almacenamiento secuencial.
Lista vinculada
No solo la información de los elementos, sino también la información de la relación lógica (la información de dirección de los nodos posteriores).
Comparación de dos estructuras de almacenamiento.
Tabla de secuencia:
Función de acceso aleatorio, que ocupa espacio de almacenamiento continuo.
Insertar: Necesidad de mover múltiples elementos.
Lista vinculada
No se admite el acceso aleatorio, la tasa de utilización del espacio de almacenamiento es ligeramente inferior a la tabla de secuencia y se admite la asignación dinámica del espacio de almacenamiento.
Insertar: no es necesario mover elementos.
Cinco formas de listas vinculadas:
-
Lista vinculada individualmente:
Lista enlazada individual con nodo principal (no hay información almacenada en el nodo principal): cabeza-> siguiente == Nulo, la lista vinculada está vacía.
Lista vinculada individualmente sin encabezado: head == Nulo, la lista vinculada está vacía.
-
Lista doblemente vinculada: un nodo precursor más
-
Lista circular individualmente vinculada:
El último campo de puntero (puntero nulo) de la lista vinculada individualmente apunta al primer nodo. Si el nodo de bucle usa un nodo principal, el último campo de puntero (puntero nulo) apunta al nodo principal.
-
Lista circular de doble enlace:
head == Null, la lista circular de doble enlace sin nodo head está vacía.
El nodo inicial, en estado vacío, head-> next y head-> prior debe ser igual a head.
Cualquiera de las siguientes cuatro oraciones puede ser verdadera para determinar que la lista circular doblemente enlazada está vacía.
head->next==head; head->priot==head; head->next==head && head->priot==head; head->next==head || head->priot==head;
-
Lista enlazada estática
El puntero indica la dirección del siguiente elemento en la lista vinculada en la matriz.
En comparación con la tabla de secuencia, la ventaja es que es fácil de insertar y eliminar.
Nota: La comparación de la tabla de secuencia y la lista vinculada a menudo se toma en el examen de posgrado, y se da una respuesta integral.
Comparación basada en el espacio
-
Distribución de métodos de almacenamiento:
El espacio de almacenamiento de la tabla de secuencia se asigna una vez, y el espacio de almacenamiento de la lista vinculada se asigna varias veces.
-
Densidad de almacenamiento (densidad de almacenamiento = cantidad de almacenamiento ocupada por el dominio de valor del nodo / cantidad de almacenamiento total ocupada por la estructura del nodo)
La densidad de almacenamiento de la tabla de secuencia = 1 y la densidad de almacenamiento de la lista vinculada <1 (porque hay un campo de puntero en el nodo)
Comparación basada en el tiempo
-
Método de acceso
Se puede acceder aleatoriamente a la tabla de secuencia;
Solo se puede acceder a la lista vinculada secuencialmente (atravesando el elemento anterior)
-
Número de elementos para mover al insertar / eliminar:
La tabla de secuencia necesita mover casi la mitad de los elementos en promedio;
La lista vinculada no necesita mover elementos, solo se necesita cambiar el puntero.
N tabla de secuencia y eliminar elementos insertados y análisis de complejidad se aplica:
-
Encuentra la probabilidad
Posiciones de inserción aleatorias, n posiciones de inserción, probabilidad de inserción en cualquier posición p = 1 / n
-
El número de elementos que deben moverse en la posición correspondiente.
Después de insertar el elemento i-ésimo, mueva el elemento ni.
-
Expectativa matemática E de elementos móviles:
E = p (n + (n-1) + (n-2) + …… + 0) = (n-1) / 2; O (n)
2.2 Definición de estructura y funcionamiento básico de la tabla lineal.
Definición de estructura de tabla lineal
#define maxSize 100
1. Definición de estructura de la tabla de secuencia
typedef struct{ int data[maxSize]; int length; }Sqlist;
Nota: La definición de la tabla más lineal utilizada en el examen es la siguiente forma (por simplicidad):
int A[maxSize]; int n;//长度为n
2. Definición de nodos de lista enlazados individualmente
estructura typedef LNode{
datos int;
struct LNode * next;
}LNode;Recomiende esto Las líneas amarillas son tan buenas como las escritas.
3. Definición de lista doblemente vinculada
typedef struct LNode{ int data; struct LNode* prior; struct LNode* next; }LNode;
Nota: Al asignar el espacio de un nodo de lista vinculada, defina un puntero que apunte al nodo. El nombre de este puntero se usa a menudo como el nombre del nodo.
LNode *A = (LNode*)malloc(sizeof(LNode))
int p = (int)malloc(sizeof(int))
typedef struct node{ int x; int y; }node; int p = (int)malloc(sizeof(int));//ok node n = (node)malloc(sizeof(node));//不ok node no = new node;//不ok node *No = new node[5];//ok //上述几个不ok得原因没有想通。
La diferencia entre '*' y '->':
componente variable de estructura tomada por ''.
LNode a; a.data;
El puntero a la variable de estructura toma el componente con '->'
LNode *b; b->data; //(*b)就变成了结构体变量可以用'.' (*b).data;
Descripción y explicación:
"P apunta a q", p se refiere a un puntero, porque p es tanto un nombre de puntero como un nombre de nodo,Pero el nodo no puede apuntar al nodo, Entonces p se refiere al puntero. Otro ejemplo es "utilizar la función free () para liberar el espacio de p". En este momento, p se refiere al nodo, porque p es un nombre de puntero y un nombre de nodo , pero el sistema asigna el espacio de almacenamiento requerido por la variable de puntero en sí mismo sin requerir que el usuario llame a la función
free()
Liberación, solo el espacio de almacenamiento asignado por el usuario debe ser liberado por el usuario, por lo que p se refiere al nodo.Suplemento: (Solo para suplemento, para facilitar una comprensión más profunda).
Algunos compañeros de clase pueden tener las mismas dudas que yo. Este LNode, en la función principal, no lo declaro como un puntero LNode *, debo intentar declararlo como LNode;
Nuestra conclusión a través del código es:De hecho, el nodo no puede apuntar al nodo, Debido a que el siguiente atributo en Lnode es un puntero, solo podemos permitir que el puntero de LNode * apunte a LNode * next (¡la práctica lo sabe!);
#include <iostream> #include<stdlib.h> using namespace std; typedef struct LNode{ int data; struct LNode* next; }LNode; void creat_LNode(LNode &L); void print(LNode L); int main() { LNode L; creat_LNode(L); print(L); return 0; } void creat_LNode(LNode &L){ LNode *temp = &L; for(int i =0;i<10;i++){ temp->data = i; LNode* temp2 = (LNode*)malloc(sizeof(sizeof(LNode))); temp->next = temp2; temp = temp2; } temp->next = NULL; //free(temp);此处不能free(); } void print(LNode L){ LNode *temp = &L; while(temp->next!=NULL){ cout<<temp->data<<" "; temp = temp->next; } }
Inicialización de la tabla de secuencia:
void initList(Sqlist &L){ L.length = 0; }
"Análisis de cotizaciones y":
Inserción de la tabla de secuencia: después de insertar e en la posición p, p devuelve 0 incorrectamente.
void insertElem(Sqlist &L,int p,int e);
'&' Es una cita, no lo entiendo como una dirección, Debido a que L debe cambiarse, use una referencia para recuperar el valor modificado. Si no necesita cotizar, el valor modificado en la función no se puede recuperar.
//p的检查 if(p<0 || p>L.length || L.length == maxSize) return 0;
Inserción de lista vinculada:
Inserción de cola vinculada x
void insertElem(LNode *L,int x)
Hemos modificado la lista L individualmente vinculada, pero no es útil.
&L
void insertElem(LNode* &L,int x);
El cambio de datos internos L no tiene nada que ver con == & ==.
Se agrega una referencia para permitir que se modifique el puntero L y luego se lo devuelve a la función principal.
Si no se agrega ninguna referencia, incluso si insertamos la función y dejamos que L vuelva a apuntar a un nuevo puntero, el valor modificado de L no puede incorporarse a la función principal. Por ejemplo: en la siguiente función print (), la función se ha modificado
L=L->next
y el valor modificado no se recupera.#include <iostream> using namespace std; typedef struct LNode{ int data; struct LNode* next; }LNode; void insertElem(LNode *L,int x){ while(L->next!=NULL){ L=L->next; } //此时L的下一个为NULL L->next = (LNode*)malloc(sizeof(sizeof(LNode))); L->next->data = x; L->next->next = NULL; } void print(LNode *L){ while (L->next!=NULL){ L = L->next; cout<<L->data<<" "; } cout<<endl; } int main() { LNode *L; L->data = -1;//头结点 L->next = NULL; for(int i=0;i<10;i++){ insertElem(L,i); } print(L); return 0; }
Problema de inversión (408 sitios de prueba importantes)
void reverse(int a[],int left,int right,int k){ int temp; for(int i=left,j=right;i<left+k && i<j;i++,j--){ temp = a[i]; a[i] = a[j]; a[j] = temp; } }
-
Los elementos k (k <n) del extremo frontal de la matriz de longitud n se invierten en el extremo posterior de la matriz, los datos no se pierden y la posición de los elementos restantes no importa.
reverse(a,0,n - 1,k)
; -
Los elementos k (k <n) en el frente de la matriz de longitud n se mueven hacia la parte posterior de la matriz en el orden original, los datos no se pierden y la posición de los elementos restantes es irrelevante.
El proceso de k primero y luego 1 en orden inverso
reverse(a,0,k-1,k);
reverse(a,0,n-1,k);
-
Los elementos (X 0 , X 1 , ..., X n-1 ) en la matriz se convierten (X p , X p + 1 , ..., X n-1 , X 0 , X 1 , ..., X p-1 ), es decir Ciclo dejado por p posiciones.
"Antes de tirar"
Requisitos:
123456789 -> 456789123
O trata 123 en su conjunto
=> 321 456789
=> 321 987654
=> 456789123
reverse(a,0,p-1,p); reverse(a,p,n-1,n-p); reverse(a,0,n-1,n);
"Más tarde de antemano"
Requisitos:
123456789 -> 789123456
Tratar 123456 como un todo
=> 654321 789
=> 654321 987
=> 789123456
reverse(a,0,n-p-1,n-p); reverse(a,n-p,n-1,p); reverse(a,0,n-1,n);