Estructura de datos y fundamentos de algoritmos (Wang Zhuo) (28) Búsqueda de tabla lineal (2): búsqueda secuencial (búsqueda binaria, búsqueda de bloques)

Tabla de contenido

2. Búsqueda binaria (búsqueda binaria o bisecada)

Proyecto 1:

El resultado corregido es el siguiente:

Proyecto 2:

Pregunta (1): [ST.R[mid].key]

Pregunta (2): igual a: (==) no (=)

Pregunta (3): Acerca de la división, la división por y la división entera

1. Sobre la diferencia entre división y división:

En segundo lugar, sobre el problema de la divisibilidad:

Pregunta (4): ¿Qué debemos hacer cuando lo bajo es igual a lo alto?

Entonces, para esta situación, es más apropiado para nosotros ponerlo en el ciclo while.

Proyecto 3: (resultado final)

La versión de respuesta estándar escrita en el PPT (tiene méritos)

Suplemento en PPT: versión de implementación recursiva

Tres, búsqueda de bloque


2. Búsqueda binaria (búsqueda binaria o bisecada)

Las condiciones previas son las mismas que antes.

El marco del programa escrito basado en el ejemplo PPT (ejemplo) al principio:

Al principio:

bajo : el primero

alto : el último dígito

medio : justo en el medio

Encuentra números menores que la mitad:

Mover alto al frente de la mitad (-1)

Luego toma el nuevo mid = new [justo en el medio]

Encuentra números mayores que la mitad:

Mover bajo a un bit detrás del medio (+ 1)

Luego toma el nuevo mid = new [justo en el medio]

Sin embargo, aquí, lo que escribí son solo algunas reglas básicas del marco, y no he resuelto el flujo lógico de cómo funciona realmente el programa.

Entonces, lo que está escrito es diferente de lo que está escrito en la respuesta estándar:

Proyecto 1:

int Seaarch_Bin(SSTable ST, KeyType key)
//binary:二进制的; 仅基于两个数字的; 二元的; 由两部分组成的;
{
    int low = 1, high = ST.length, mid = (low + high) / 2;
    while (key != mid)
    {
        if (key < mid)
        {
            high = mid - 1;
            mid = (low + high) / 2;
        }
        else if (key < mid)
            //else
        {
            low = mid + 1;
            mid = (low + high) / 2;
        }
    }
    if (low > high)
        return false;
    else
        return mid;
}

Además de resolver la lógica, hay muchos otros problemas, por supuesto:

Antes de escribir el programa, es mejor ordenar el flujo lógico de cómo se ejecuta el programa, esto es seguro.

Todavía hay muchos problemas en la versión anterior:

  • Al comparar la clave, no debe escribir [mid] y cambiarlo a [ST.R[mid].key] (haremos un análisis detallado y una explicación de esto en el Proyecto 2)
  • No importa en qué caso (rama) en el ciclo while, (todos) siempre ejecutan la declaración [mid = (low + high) / 2;], debe (puede) considerar fusionar la declaración fuera de la declaración [if]

El resultado corregido es el siguiente:

(Creo que después de modificarlo al siguiente resultado, el resultado no está mal, pero no estoy tan seguro de que sea correcto)

int Seaarch_Bin(SSTable ST, KeyType key)
//binary:二进制的; 仅基于两个数字的; 二元的; 由两部分组成的;
{
    int low = 1, high = ST.length, mid = (low + high) / 2;
    while (key != ST.R[mid].key)
    {
        if (key < ST.R[mid].key)
            high = mid - 1;
        else if (key < ST.R[mid].key)//else
            low = mid + 1;
        mid = (low + high) / 2;
    }
    if (low > high)
        return false;
    else
        return mid;
}

Además, lo primero que debemos hacer es ordenar el flujo lógico de cómo funciona el programa.

Convierta el programa en una forma lógica similar a la del PPT: (pero esto no significa que lo que escribí esté mal)

Proyecto 2:

int Seaarch_Bin(SSTable ST, KeyType key)
//binary:二进制的; 仅基于两个数字的; 二元的; 由两部分组成的;
{
    //不是从R开始吗???
    int low = 1, high = ST.length, mid = (low + high) / 2;
    while (low<=high)
        //一开始我们是想写(key != mid)的判断语句的,但是如果这样写的话我们最后就无法判断他有没有找到
    {
        if (key = mid)
            return mid;
        else if (key < mid)
        {
            high = mid - 1;
            mid= (low + high) / 2;
        }
        else if (key > mid)
            //else
        {
            low = mid + 1;
            mid = (low + high) / 2;
        }
    }
    return 0;
}

Pregunta (1): [ST.R[mid].key]

Al comparar la clave, no debe escribir [mid] y cambiarlo a [ST.R[mid].key]

(También hay un problema similar en el Proyecto 1)

Explicación específica:


Primero, debemos darnos cuenta de que:

El objeto a comparar con nuestra clave es el valor específico en una secuencia de bits específica (una determinada celda) dentro de la tabla de secuencias ST (matriz)

 En este momento, cuando observemos la estructura de la tabla de secuencia, nos daremos cuenta de:

De hecho, la tabla de secuencia real ST es diferente del programa que originalmente dimos por sentado.

typedef int tipo de clave ;

// Definición del tipo de elemento de datos

struct ElemType

{

    KeyType clave;  // campo clave

    //... // otros dominios

};

estructura SSTable

    //Tabla de búsqueda secuencial

{

    ElemType * R;  // dirección base de la tabla

    longitud int ;   // longitud de la tabla

}; 

SSTable ST;  // Definir la tabla de secuencia ST

De hecho, el efecto del programa que escribimos anteriormente es:

Deje que [clave] se compare con [el número de bit del elemento señalado por el puntero]

Y lo que realmente necesitamos lograr es:

Deje que [clave] se compare con [los datos del elemento señalados por el puntero]

Y estos datos del elemento KeyType (datos de palabras clave) están en:

En el campo clave clave de la dirección base de la tabla R (aunque no sé cuál es la dirección base de la tabla )

Más el tipo de datos:

En el campo de clave [( KeyType ) type] clave de la dirección base de la tabla [ ( ElemType * ) type ] R

Por lo tanto, mid debe cambiarse a: ST.R[mid].key


Y tal explicación en realidad resuelve el problema cuando escribimos programas:

¿El orden de direcciones de la matriz no comienza desde R? ? ?

El problema


Pregunta (2): igual a: (==) no (=)


Pregunta (3): Acerca de la división, la división por y la división entera

1. Sobre la diferencia entre división y división:

6 dividido por 2: dividido por

6÷2=3

6 dividido por 2: dividir

2÷6=⅓

2 dividido por 6: dividir

6÷2=3

2 dividido por 6: dividido por

2÷6=⅓

En segundo lugar, sobre el problema de la divisibilidad:

Redondeo por divisibilidad:

Toma el número entero, redondea el decimal

Nota: no redondeado

En las computadoras, solo hay un símbolo de operador para la división, que es "/".

Y sobre si es divisible:

Ya sea que signifique el resultado del redondeo de la división entera [nota: no redondeado] o el resultado final de la operación con decimales depende del divisor y el dividendo. Más precisamente, es la cantidad de cálculos durante el proceso de división.

Si todos los operandos [todos los divisores y dividendos] son ​​de tipo entero (tipo int):

El resultado se redondea y los decimales se redondean (nota: no redondeado)

Si solo un operando entre todos los operandos [todos los divisores y dividendos] es de tipo real (tipo de número real: flotante, doble)

El resultado retiene decimales (el formato de retener el número de lugares decimales está alineado con el tipo de número real, y es más preciso si es más preciso)


Pregunta (4): ¿Qué debemos hacer cuando lo bajo es igual a lo alto?

En el ejemplo anterior, escribimos el caso donde bajo y alto son mayores que y menores que

Entonces, ¿qué debemos hacer cuando lo bajo y lo alto son iguales?

Trate de diseñar un ejemplo específico, asumiendo:

secuencia de bits 1 2 3
datos 22 23 24
puntero bajo medio alto

 Así que nuestra conclusión final es que:

Cuando bajo es igual a alto:

Si la clave no es igual a [baja, alta y media], entonces la búsqueda falla

Si es igual, el puntero de salida

Entonces, para esta situación, es más apropiado para nosotros ponerlo en el ciclo while.


Proyecto 3: (resultado final)

int Seaarch_Bin(SSTable ST, KeyType key)
//binary:二进制的; 仅基于两个数字的; 二元的; 由两部分组成的;
{
    int low = 1, high = ST.length, mid = (low + high) / 2;
    while (low <= high)
    {
        if (key == ST.R[mid].key)
            return mid;
        else if (key < ST.R[mid].key)
            high = mid - 1;
        else if (key > ST.R[mid].key)//else
            low = mid + 1;

        mid = (low + high) / 2;
    }
    return 0;
}

Adjunto:

La versión de respuesta estándar escrita en el PPT (tiene méritos)

Es equivalente a simplificar el programa que escribimos antes:

No es necesario asignar un valor a mid al principio, solo hay que asignar un valor a mid al principio de cada ciclo

int Seaarch_Bin(SSTable ST, KeyType key)
//binary:二进制的; 仅基于两个数字的; 二元的; 由两部分组成的;
{
    int low = 1, high = ST.length,mid; 
    while (low <= high)
    {
        mid = (low + high) / 2;
        if (key == mid)
            return mid;
        else if (key < ST.R[mid].key)
            high = mid - 1;
        else
            //else if (key > ST.R[mid].key)
            low = mid + 1;   
    }
    return 0;
}

Suplemento en PPT: versión de implementación recursiva

int Search_bin(SSTable& S, KeyType e, int low, int high)
{
    if (low > high)
        return -1;
    int mid = (high + low) / 2;
    if (e == S.R[mid].key)
        return mid;
    if (e < S.R[mid].key)
        return Search_bin(S, e, low, mid - 1);
    else
        return Search_bin(S, e, mid + 1, high);
}

 Referencia de derivación de longitud de búsqueda promedio: Capítulo 5 "Árboles y árboles binarios" P34

Tres, búsqueda de bloque


No examina el código.

Sin embargo, cómo implementar el código de búsqueda de bloques se puede estudiar más adelante si tiene tiempo, es bastante interesante.

Supongo que te gusta

Origin blog.csdn.net/Zz_zzzzzzz__/article/details/130122116
Recomendado
Clasificación