Estructura de datos y fundamentos de algoritmos (Wang Zhuo) (9): aplicación de tablas lineales (combinación de tablas ordenadas) (ordenadas, repetibles)

Tabla de contenido

Fusionar en un nuevo todo: Fusión de listas ordenadas (ordenadas, repetibles)

Mesa lineal:

Diseño de procesos para la implementación específica de esta operación: (cada módulo)

Módulo uno:

Módulo dos:

Módulo Tres:

Pulido de revisión final:

Con respecto a las tablas lineales: la operación de combinación (ordenada, repetible) de tablas ordenadas es la siguiente:

lista enlazada:

uno,

dos, 

tres,

Proyecto final:


PPT: Capítulo 2 P176; 

 


Fusionar en un nuevo todo: Fusión de listas ordenadas (ordenadas, repetibles)

Mesa lineal:

Diseño de procesos para la implementación específica de esta operación: (cada módulo)

  1. Crear una tabla vacía C
  2. A su vez, "extraiga" nodos con valores de elementos más pequeños de A o B (medio) e insértelos al final de la tabla C hasta que el

    Una mesa queda vacía

  3. Continúe insertando los nodos restantes de una de las tablas A o B al final de la tabla C


Módulo uno:

Para el módulo uno aquí, necesitamos:

Para conocer todo el proceso de aprendizaje y los problemas de la operación de creación de una nueva tabla para devolver el resultado de la fusión de las dos tablas (la tabla fusionada final), consulte:

Estructura de datos y fundamentos de algoritmos (Wang Zhuo) (8) Anexo: Parte 2 de la explicación detallada sobre el uso de new;

En este programa, usamos la declaración, a saber:

    C.elem = new Elemtype[100]; 

Módulo dos:

Entre ellos, la realización del proceso del módulo 2 se subdivide en:

  1.  Extraiga el nodo con el valor de elemento más pequeño en las dos tablas
  2. Insertar un nodo al final de la lista C
  3. Repita los pasos "1" y "2" hasta que una de las mesas quede vacía

Proyecto 1:

    //不用指针,直接硬钢判断语句
    int i = 0,//对应A表
        j = 0,//对应B表
        k = 0;//对应C表
    while (i < A.length || j < B.length)
    {
        if (A.elem[i] > B.elem[j])
        {
            C.elem[k] = B.elem[i];
            i++;
            k++;
        }

        if (A.elem[i] == B.elem[j])
        {
            C.elem[k] = A.elem[i];
            C.elem[++k] = B.elem[j];
            i++;
            j++;
            k++;
        }

        else//        if (A.elem[i] < B.elem[j])

        {
            C.elem[k] = A.elem[i];
            i++;
            k++;
        }
//当然,也可以先大于小于再等于

ilustrar:

(1):

En el módulo 2, la afirmación de que los valores de los elementos de los dos nodos comparados entre las dos tablas son iguales también se puede escribir como:

        if (A.elem[i] == B.elem[j])
        {
            C.elem[k] = A.elem[i];
            C.elem[++k] = B.elem[j];
            i++;
            j++;
            k++;
        }

(2):

Es necesario prestar atención (recordar), originalmente (al principio), para la instrucción de juicio de ejecución de bucle (de), originalmente queríamos escribirlo como

    while(A.elem[i] != 0 || B.elem[j] != 0)

Sin embargo, los resultados muestran:

En primer lugar, lo primero que es seguro (conclusión) es:

Aquí, nuestro programa no puede completar el juicio "!=" en la declaración

Aquí, si queremos que el programa implemente con éxito el juicio, podemos tener las siguientes dos soluciones:

  • Ejecute manualmente una expresión de definición de juicio sobre <Poly type> != <int type>
  • Cuando el nodo de definición está vacío, el contenido del nodo vacío, es decir: definir dicho nodo vacío

Por supuesto, si realmente desea escribirlo así, puede hacerlo, pero es demasiado problemático, por lo que no elegimos este método aquí.


Proyecto 2: (usando las propiedades de almacenamiento de matriz lineal de dirección de tabla lineal)

    //利用指针
    Poly* pa, * pb, * pc;
    pa = A.elem;
    pb = B.elem;
    pc = C.elem;

    //*pa = A.elem[0];
    //*pb = B.elem[0];

    while (pa <= &A.elem[A.length - 1] || pb < &B.elem[B.length - 1])
    {
        if (*pa > *pb)
        {
            *pc = *pb;
            pa++;
            pc++;
        }

        if (*pa == *pb)
        {
            *pc = *pa;
            *(++pc) = *pb;
            pa++;
            pb++;
            pc++;
        }

        else
        {
            *pc = *pa;
            pa++;
            pc++;
        }

Módulo Tres:

    if (A.length > B.length)
    {
        //while (i < A.length)  同理,后面不再赘述
        while (pa <= &A.elem[A.length - 1])    
        {
            *pc = *pa;
            pc++;
            pa++;
        }
    }
    else
    {
        while (pb <= &B.elem[B.length - 1])
        {
            *pc = *pb;
            pc++;
            pb++;
        }
    }

Pulido de revisión final:

De acuerdo con la respuesta estándar en (referencia) PPT (178), encontramos que todavía hay espacio para modificaciones en los siguientes lugares:


Módulo 1:

Por un lado:

No asignamos un valor al elemento de longitud de la tabla C recién creada

por otro lado:

La longitud de la mesa C es la suma de las longitudes de la mesa A y la mesa B

Si todavía es fijo, sería un poco inapropiado abrir un espacio con un tamaño fijo de 100 como la Tabla A y la Tabla B:

  C.length = A.length + B.length; 
  C.elem = new Elemtype[C.length];

Además, las condiciones de calificación que escribimos aquí en el módulo dos:

    while (pa <= &A.elem[A.length - 1] || pb < &B.elem[B.length - 1])

Escrito como:

    while (pa <= A.elem + A.length - 1 || pb < B.elem + B.length - 1)

La misma razón (la misma); (la respuesta estándar está escrita de acuerdo con este último, pero siento que no hay nada especial en escribir de esta manera)


Pero otro problema es serio:

En C++:

y:&&

o: ||

No:!

Por lo tanto, debe cambiarse a:

    while (pa <= A.elem + A.length - 1 && pb < B.elem + B.length - 1)

 o:

    while (pa <= &A.elem[A.length - 1] && pb < &B.elem[B.length - 1])

además:

Con respecto al cuerpo del ciclo de este ciclo en el módulo dos, no hay un gran error en lo que escribí

Pero es demasiado engorroso y la respuesta estándar es más concisa y conveniente.

Por supuesto, no es tan riguroso como escribí: escribe específicamente el proceso de operación cuando los valores de los elementos de los dos nodos son iguales, lo que puede reducir la cantidad de ciclos.

Pero desde la perspectiva de una gran complejidad temporal, en realidad no hay mucha diferencia entre n ciclos y (n-5) ciclos.

Así que aquí todavía elegimos la forma de escribir en la respuesta estándar:

    while (pa <= &A.elem[A.length - 1] && pb < &B.elem[B.length - 1])
    {
        if (*pa < *pb)
            *pc++ = *pa++;
        else
            *pc++ = *pb++;
    }

Esta forma de escribir, es decir:

Primero (hasta el último nodo en la tabla C (*pc)) asignación y luego autoincremento; una declaración para lograr


Finalmente, sobre el módulo tres:

De hecho, no necesitamos configurar la declaración de juicio para ver qué tabla es más larga en A o B.

Porque, de hecho, incluso si escribimos directamente dos declaraciones de bucle, todavía no afecta la operación del programa.

Debido a que el puntero de una tabla ha alcanzado el nodo final de la tabla, naturalmente no cumple con la condición de juicio de bucle del bucle:

        while (pa <= &A.elem[A.longitud - 1])    

        while (pb <= &B.elem[B.longitud - 1])

Además, el cuerpo de la función aquí también se puede escribir en la forma de " primero asigne un valor al último nodo (*pc) en la tabla C y luego incremente; "

        while (pa <= &A.elem[A.length - 1])    
        {
            *pc++ = *pa++;
        }
        while (pb <= &B.elem[B.length - 1])
        {
            *pc++ = *pb++;
        }

En resumen:

Con respecto a las tablas lineales: la operación de combinación (ordenada, repetible) de tablas ordenadas es la siguiente:

int Merge(Sqlist A, Sqlist B, Sqlist& C)
{//合并; 融入; (使)结合; 并入; 相融;

    typedef Poly Elemtype;

    C.length = A.length + B.length;
    C.elem = new Elemtype[C.length];

    //利用指针
    Poly* pa, * pb, * pc;
    pa = A.elem;
    pb = B.elem;
    pc = C.elem;
    //*pa = A.elem[0];
    //*pb = B.elem[0];

    while (pa <= &A.elem[A.length - 1] && pb < &B.elem[B.length - 1])
    {
        if (*pa < *pb)
            *pc++ = *pa++;
        else
            *pc++ = *pb++;
    }
    //
    while (pa <= &A.elem[A.length - 1])
    {
        *pc++ = *pa++;
    }
    while (pb <= &B.elem[B.length - 1])
    {
        *pc++ = *pb++;
    }
    //
    return true;
}







lista enlazada:

Proyecto 1:

int Merge(LinkList &A, LinkList& B, LinkList& C )
{
    //给指针赋初值
    LinkList
        pa = A->next,
        //注意:这里的指针指向的是AB表的首元结点而不是头结点
        pb = B->next,
        pc = C = A;
    //pc = A;
    //pc = &C = A;
 
    //比较并插入
    while(pa&&pb)
        //while (pa->next!=0&& pa->next != 0)
    {
        if (pb->data > pa->data)
        {
            pc->next = pa;
            pa = pa->next;
            //pc = pc->next;
        }
        else
        {
            pc->next = pb;
            pb = pb->next;
        }
    }
    //插入剩余段
    while(pa||pb)
    {
        pa ? pa : pb;
    }
    //返回操作成功信号
    return true;
}

además:

struct K
{
    float a;
    int b;
    string c;
    bool operator==(K& t)
    {
        return t.a == a && t.b == b;
        //&& t.c = c;
    }
    bool operator!=(K& t)
    {
        return t.a != a || t.b != b;
        //|| t.c = c;
    }
    bool operator>(K& t)
    {
        return t.a > a && t.b > b;
        //&& t.c = c;
    }
    bool operator<(K& t)
    {
        return t.a < a || t.b < b;
        //|| t.c = c;
    }
};

asuntos:

uno,

acerca de

        pc = C = A;
    //pc = A;
    //pc = &C = A;

(1): ¿Expresión de asignación continua? ? ?

        pc = C = A; es equivalente a: pc = (C = A); <C++ libro P25>

(2): ¿Por qué no funcionan los dos estilos (formularios) en los comentarios?

1,

pc = A;

Si lo escribimos así, terminamos con:

Modificamos (escribimos) la nueva tabla durante mucho tiempo, y finalmente se vinculó con la tabla C, o nuestro puntero a la tabla C & C (la primera dirección de C)

No hay conexión (relación), es decir:

La creación es crear una nueva lista ordenada fusionada, pero no hay forma de volver atrás y crear una nueva lista solitaria.


2,

pc = &C = A;

resultado: 

Aquí podemos realmente relacionarnos con el problema en (1), donde:

C representa el puntero de cabecera de la tabla C de tipo Lnode, que también puede considerarse como un puntero de tipo LinkList

Y después de su operación de dirección, &C representa la dirección del puntero de este tipo LinkList

La dirección de este puntero es un valor fijo (constante)

Y una constante (un valor fijo) no debe ser asignada por ninguna otra variable, por lo que es razonable reportar un error


También el mismo:

No creemos que esta constante (valor invariable) esté bien si está en el extremo izquierdo de la expresión (la operación de la expresión)

Además del hecho de que las constantes deben colocarse en el extremo izquierdo, también debemos prestar atención a la unificación de tipos:


Del mismo modo, aquí hacemos un resumen sistemático del formato LinkList & A que nos ha estado molestando durante mucho tiempo:

 ¿Qué significa &A? ?

Lnode A: variable A del tipo de nodo de lista enlazada


Lnode &A: Todavía representa la variable A del tipo de nodo de lista enlazada, pero (solo) representa el método de paso de valor por referencia


LinkList A: apunta a la variable de puntero A cuyo objeto de destino es el tipo de nodo de la lista enlazada

LinkList &A: todavía indica que el objeto de destino es una variable de puntero A del tipo de nodo de lista enlazada

Simplemente
significa que la dirección se transmite (entrega) utilizando el método de valor por referencia


dos, 

Acerca de la declaración de juicio de bucle

    while(pa&&pb)
        //while (pa->next!=0&& pa->next != 0)

¿Por qué aquí solo es necesario juzgar si el valor del puntero es 0 para determinar si el programa ejecuta un bucle?

¿Cómo sabes que las direcciones dispuestas por el programa para los nodos vacíos que no se asignan más tarde son todas 0? ? ?


primero:

No podemos decir aquí (al menos por ahora) que no podemos decir la declaración

        //mientras (pa->siguiente!=0&& pa->siguiente!= 0)

¿Es factible, y la afirmación

    mientras (pa&&pb)

entonces simplemente significa:

Si tanto pa como pb son verdaderos, no falsos (vacíos), entonces el programa se ejecutará; de lo contrario, no se ejecutará

Aquí no hay duda sobre la relación entre 0 y falso. Por supuesto, si 0 puede representar falso es una pregunta que vale la pena entender (buscar)


Sobre el cuerpo del bucle:

El flujo de ejecución del cuerpo del bucle:

Conecte los nodos con valores de elementos más pequeños al final de la tabla C (último, siguiente)

Deje que el puntero de la tabla C (nueva tabla) apunte al nodo recién insertado en la tabla C

(Porque todos los nodos posteriores se insertan después del nodo recién insertado)

Haga que el puntero a la lista cuyo elemento se acaba de extraer apunte al siguiente nodo de la lista

En el proceso de escritura del cuerpo del bucle, por un lado:

Después de insertar cada nodo, el puntero a la tabla A y la tabla B se modifica en lugar del puntero a la tabla C:

            pa = pa->next;
            //pc = pc->next;

lo más importante es:

Olvidamos el segundo paso de los pasos del cuerpo del bucle que escribimos aquí: pc = pa / pb;

Y de hecho, en la operación real, ¡ el segundo paso no puede escribirse antes del tercer paso! ! !


tres,

No olvides que hay un paso más antes del final final:

    delete B;

Proyecto final:

int Merge(LinkList &A, LinkList& B, LinkList& C)
{
    //给指针赋初值
    LinkList
        pa = A->next,
        //注意:这里的指针指向的是AB表的首元结点而不是头结点
        pb = B->next,
        pc = C = A;
 
    //比较并插入
    while(pa&&pb)

    {
        if (pb->data > pa->data)
        {
            pc->next = pa;
            pc = pa;
            pa = pa->next;
        }
        else
        {
            pc->next = pb;
            pc = pb;
            pb = pb->next;
        }
    }
    //插入剩余段
    while(pa||pb)
    {
        pa ? pa : pb;
    }

    delete B;
    //返回操作成功信号
    return true;
}

FIN

Supongo que te gusta

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