Estructura de datos y algoritmo (1): estructura de datos básica (concepto de algoritmo, matriz, lista enlazada, pila, cola)

Conceptos de algoritmos, arreglos, listas enlazadas, pilas, colas

¿Determinar si un número es 2 elevado a la N-ésima potencia?

N & (N-1) == 0  (N > 0)

Problema de calculo:

algoritmo

concepto de algoritmo

Representante del algoritmo: alta eficiencia y bajo almacenamiento, pequeña huella de memoria, pequeña huella de CPU, velocidad informática rápida

Alta eficiencia y bajo almacenamiento de algoritmos: memoria + CPU

Dos indicadores para evaluar algoritmos

  • Complejidad del tiempo: el tiempo que lleva ejecutar un programa O()
  • Complejidad espacial: la memoria OOM requerida para ejecutar el programa

complejidad del tiempoO(1,logn,n,nlogn,n^2,n^x)

  • Constante: O(1) 1 significa que es una constante, usamos O(1) para todos los números que se pueden determinar, O(10000)=>O(1)
  • Logaritmo: O(registro), O(registro)
  • Lineal: O(N) n debe ser desconocido; si n es conocido O(1)
  • Logaritmo lineal: O(nlogn)
  • Cuadrado: O(n^2)
  • N-dimensional: O(n^n)

cómo encontrar la complejidad del tiempo

  • Hay un mal lugar
  • Donde hay solicitudes de red (RPC, llamadas remotas, distribuidas, bases de datos)

Imprimir registro en el momento de la prueba

inserte la descripción de la imagen aquí

O(1) > O(logn) > O(n) > O(nlogn) > O(n^2) > O(n^n)

Cuanto más cerca de O(1), menor es la complejidad del tiempo

Constante: O(1)

int a = 1; // 1次O(1)
for(int i = 0; i < 3; i++) {
    
     //这里运行4次
  a = a + 1; //这里运行3次
}

Logaritmo: O(registro), O(registro)

//对数 2^x=n  x就是我们运行的次数 => 对数 x=log2(n) = log2n = 计算机忽略常数 => logn => O(logn)
int n = Integer.MAX_VALUE;
int i = 1;

//O(logn)
while (i <= n) {
    
    
    i = i * 2;
}

//O(nlogn)
for (int j = 0; j < n; j++) {
    
    
    while (i <= n) {
    
    
        i = i * 3;
    }
}

Lineal: O(N)

//线性: O(N) n一定是未知的; 如果n是已知的O(1)
for (i = 0; i < n; i++) {
    
    
    a = a + 1;
}

Cuadrado: O(n^2)

for (i = 0; i < n; i++) {
    
    
    for (int j = 0; j < n; j++) {
    
    
        a = a + 1; // O(n^2)  n*(n+1)/2 => O(n^2) = 1+2+3+4+..+n=n*(n+1)/2
    }
}

Afinación

Ordenación de lista Ordenación de burbujas < Ordenación rápida Ordenación de combinación Ordenación de montón

Clásico: lista enlazada, algoritmo de clasificación, árbol binario, árbol rojo-negro, B-Tree, B+Tree

Avanzado: teoría de números, teoría de grafos

estructura de datos

formación

Preguntas para pensar:

  • Pregunta 1: proporcione un archivo que contenga los datos de edad (0 ~ 180) de 1.400 millones de personas en el país, ¿cuántas personas de cada edad cuentan?
    Limite la memoria de una sola máquina a 2G + 2G y no utilice contenedores prefabricados, como mapas, etc.

int edad[] = new int[180];
a[0]++; // 0 significa 0 años

Usando el subíndice de matriz, también puede usar el subíndice para ubicar aleatoriamente ciertos datos en la matriz

  • Pregunta 2: ¿Por qué el subíndice del valor comienza desde 0 y la característica de la matriz es una dirección de memoria continua?

int arr[] = new int[5];

La dirección de memoria solicitada es, por ejemplo: 10001, 10002, 10003, 10004, 10005

保存数据:a[0] => 10001 ===> 10001 + 0
保存数据:a[1] => 10002 ===> 10001 + 1
保存数据:a[2] => 10003 ===> 10001 + 2
保存数据:a[3] => 10004 ===> 10001 + 3
保存数据:a[4] => 10005 ===> 10001 + 4
  • Pregunta 3: ¿Cuál es la dirección de memoria de una matriz bidimensional?
1 2 3
4 5 6  =>  1 2 3 4 5 6 => i*n + j (i是一维数组的长度、j是在列的位置) => 4 => 1*3 + 0 = 3

Cómo elegir entre ArrayList y matriz

  • ArrayList está empaquetado por JDK y no necesita expandirse
  • La eliminación y adición de arreglos son lentas O(n), la modificación y adquisición son rápidas O(1)
  • acceso aleatorio
  • subíndice

¿como escoger?

  • Si no conoce el tamaño de los datos, seleccione ArrayList
  • Si conoce el tamaño de los datos y está muy preocupado por el rendimiento de la matriz de selección, debe prestar atención a los límites (cabeza y cola)

La memoria de Java se divide en memoria de pila y memoria de pila

Memoria de pila: almacene nuevos objetos y matrices
Memoria de pila: variables de referencia

Tanto el montón como la pila se utilizan para almacenar datos.

Diferencia de pila:

  • La pila es más rápida
  • Los datos de memoria de la pila se pueden compartir, almacenando principalmente algunos tipos de datos básicosint a = 3; 在栈中创建变量a, 然后给a赋值,先不会创建一个3而是先在栈中找有没有3
String s1 = "ja";
String s2 = "va";
String s3 = "java";
String s4 = s1 + s2; // java 里面重装了+, 其实调用了 stringBuild, 会new对象
System.out.println(s3 == s4); //false
System.out.println(s3.equals(s4)); //true

lista enlazada

Preguntas para pensar:

  1. Cómo diseñar un algoritmo de eliminación de caché LRU (lista enlazada)
  2. Problema de Joseph (lista circular enlazada): N personas forman un círculo, empiezan a contar desde la primera, la M-ésima será eliminada, y la última quedará, y el resto serán asesinados. Por ejemplo, N=6, M=5, el orden de muerte es 5, 4, 6, 2, 3, 1

Características de la lista enlazada

  • No requiere espacio de memoria contigua
  • tiene una referencia de puntero
  • Estructuras de listas enlazadas comunes: lista enlazada simple, lista enlazada doble, lista enlazada circular

Lista enlazada individualmente LinkList

consulta O(n)
inserción borrar O(1)

lista de doble enlace

El nodo hoja Mysql del árbol B+ es una lista doblemente enlazada,
la tabla de salto es muy similar al árbol Mysql B+

lista enlazada circular

Una lista enlazada circular es un tipo especial de lista enlazada simple. La única diferencia entre ella y una lista enlazada simple es el nodo final. El nodo final
de una lista enlazada simple es una dirección vacía.
El nodo final de una lista enlazada circular es el nodo de cabeza.

Comparación de listas enlazadas y matrices

Preguntar

formación

  • O(1)

lista enlazada

  • En)

insertar/eliminar

inserción de matriz

  • Cola O(1)
  • De frente)

inserción de lista enlazada

  • cabeza O(1)
  • Cola O(1)
  • Intermedio O(1*2)

Diferencia importante:

  1. La matriz es simple y fácil de usar. La implementación utiliza un espacio de memoria continuo. Los datos en la matriz se pueden leer de antemano con la ayuda del mecanismo de caché de la CPU, por lo que la eficiencia de acceso es mayor.
  2. La lista enlazada no se almacena de forma continua en la memoria, por lo que no es compatible con la memoria caché de la CPU y no hay forma de leer con eficacia.
  3. La desventaja de una matriz es que su tamaño es fijo y, una vez que se declara, ocupará todo el espacio de memoria continua. Si la matriz declarada es demasiado grande, es posible que el sistema no tenga suficiente espacio de memoria contiguo asignado, lo que
    resultará en "memoria insuficiente". Si la matriz declarada es demasiado pequeña, puede que no sea suficiente.
  4. Expansión dinámica: la matriz debe solicitar un espacio de memoria más grande, y copiar la matriz original en ella lleva mucho tiempo. La lista vinculada en sí no tiene límite de tamaño y, naturalmente, admite la expansión dinámica.

Pila - último en entrar, primero en salir - LILO

Preguntas para pensar:

  1. ¿Cómo diseñar una función de coincidencia de corchetes? la pila
  2. ¿Cómo diseñar una función de avance y retroceso del navegador? (Dos pilas, una hacia adelante y otra hacia atrás)
  3. ¿Cómo implementar cuatro fórmulas aritméticas como 3+2*5-3? (dos pilas, un número, un símbolo)
  4. Secuencia de llamada de función de código

funciones de pila

Una pila es una lista lineal limitada a operaciones de inserción y eliminación solo al final de la tabla, llamada la parte superior de la pila, y el otro extremo es la parte inferior de la pila.

La inserción de nuevos elementos en una pila se denomina empujar, empujar y empujar, y
la eliminación de elementos se denomina extracción y desapilamiento.

La pila es en realidad una lista o matriz vinculada especial. La lista vinculada de la matriz expone demasiadas interfaces y es propensa a errores.

public class KuoHaoStack {
    
    
    public static boolean isOk(String s) {
    
    
        MyStack<Character> brackets = new ArrayStack<>(20);
        char c[] = s.toCharArray();
        Character top = null;
        for (char x : c) {
    
    
            switch (x) {
    
    
                case '{':
                case '(':
                case '[':
                    brackets.push(x);
                    break;
                case '}':
                    top = brackets.pop();
                    if (top == null) return false;
                    if('{' == top) {
    
    
                        break;
                    } else {
    
    
                        return false;
                    }
                case ')':
                    top = brackets.pop();
                    if (top == null) return false;
                    if('(' == top) {
    
    
                        break;
                    } else {
    
    
                        return false;
                    }
                case ']':
                    top = brackets.pop();
                    if (top == null) return false;
                    if('[' == top) {
    
    
                        break;
                    } else {
    
    
                        return false;
                    }
                default:
                    break;
            }
        }
        return brackets.isEmpty();
    }

    public static void main(String[] args) {
    
    
        Scanner scanner = new Scanner(System.in);
        while (scanner.hasNext()) {
    
    
            System.out.println("S的输出结果:" + isOk(scanner.next()));
        }
    }
}

Cola – primero en entrar, primero en salir – FIFO

preguntas de pensamiento

  • Cuando la tarea en el grupo de subprocesos está llena, aparece una nueva tarea en este momento. ¿Cómo lo maneja el grupo de subprocesos? ¿Cuáles son las estrategias específicas? ¿Cómo se implementan estas estrategias?
  1. Cola: Cola de bloqueo. Tómalo cuando seas libre, ¿no es tomar y poner? Si es justo, debe ser el primero en entrar, el primero en salir. Esta es la cola de la que estamos hablando hoy. En este momento tenemos dos formas, una es una cola infinita. (Lista vinculada, no la use. LinkedBlockingQueue, JDK), hay otro tipo que está acotado (implementado por matrices), solo trata con el tamaño del espacio que abrimos y continúa arrojando más. Integer.MAX=?2^32-1=Más de 2100 millones, pero preste atención al tamaño de esta cola, no la haga pequeña. Si no es suficiente, se desperdiciará si es demasiado grande. En algunos sistemas pequeños, sabe que la cantidad de datos solicitados no es grande y se puede utilizar.
  2. Descartar: No se ocupe de él, simplemente deséchelo.

Una cola es una tabla lineal especial, que es especial porque solo permite operaciones de eliminación en el extremo frontal de la tabla y operaciones de inserción en el extremo posterior de la tabla.

clasificación de colas

  1. Cola secuencial (unidireccional): (Cola) solo puede insertar datos en un extremo y eliminar datos en el otro extremo
    inserte la descripción de la imagen aquí
  2. Cola circular (bidireccional) (Deque): cada extremo puede realizar operaciones de inserción y eliminación de datos
    para determinar si está lleno
  • Método 1: agregar tamaño
  • Método 2: (cola+1)%n == cabeza

inserte la descripción de la imagen aquí

public class CircleArrayQueue<Item> {
    
    

    private Item data[];
    private int head = 0;
    private int tail = 0;
    private int n = 0; //数组最大空间
    private int size; //当前队列已存个数

    public CircleArrayQueue(int cap) {
    
    
        data = (Item[]) new Object[cap];
        n = cap;
    }

    public void push(Item item) {
    
    
        if ((tail + 1)%n == head) return; //关键点

        data[tail] = item;
        tail = (tail + 1) % n; //关键点
    }

    public Item pop() {
    
    
        if (isEmpty()) return null;

        Item item = data[head];
        head = (head + 1) % n;
        return item;
    }

    public boolean isEmpty() {
    
    
        return head == tail;
    }
}

Supongo que te gusta

Origin blog.csdn.net/menxu_work/article/details/129048556
Recomendado
Clasificación