2025(e)ko martxoaren 21(a), ostirala

10. jarduera | Txertaketa array batean

ZER DAKIDAN:
Arrayekin lan egiteko hainbat algoritmo ezagutzen dut.



ZER IKASIKO DUDAN:
Orain ikasiko dut elementu berri bat nola sartu arrayaren posizio jakin batean. Ondoren, elementu batzuk arrayan txertatzeko algoritmoak ikasiko ditut.


Irudian zenbaki errealen afNotak array bat daukagu, bere luzera efektiboa iLuzera aldagaiak adierazten du eta 4 balio du. Irudian ikusten da ere afNotak array hori bete-beterik ez dagoela. Demagun 66.6 balioa txertatu nahi dugulua arrayaren 2 posizioan.

Balio berria arrayan gorde aurretik, tokia egin behar zaio for agindu baten bitartez, eta tokia egina dagoenean balio berria txertatuko da eta, noski, iLuzera aldagaia inkrementatu beharko da.

Irudia handiago ikusteko bere gainean klik egin, non txertaketaren
algoritmo bera bi lengoaietan ematen den: C eta Pascal

Programa nagusiak lau parametro pasatzen dizkio funtzioari, lehenengo biak sarrera/irteerakoak eta azken biak sarrerakoak. Irudiko adibidean for kontrol-egiturari esker hiru iterazi emango dira adibide honetan:

  1. iterazioan: iIndizea=4 eta libre dagoen afNotak[5] posizioan afNotak[5] balioa kopiatzen delako 56.8 datua bikoiztuta geratzen da
  2. iterazioan: iIndizea=3 eta bikoiztuta dagoen afNotak[4]posizioko balioa zapaldurik suertatzen da afNotak[3] balioa bere gainean kopiatuz, horregatik 52.9 datua bikoiztuta geratzen da
  3. iterazioan: iIndizea=2 eta bikoiztuta dagoen afNotak[3]posizioko balioa zapaldurik suertatzen da afNotak[2] balioa bere gainean kopiatuz, horregatik 17.1 datua bikoiztuta geratzen da

Irudiaren adibidean 3. iterazioarekin bukatzen da prozesu errepikakorra, hots, txertaketa burutzeko prestakizunak egin dira baina oraindik txertaketa egin gabe dago. Txertaketa gauzatzeko ondoko bi hauek egin behar dira:

  • Eskatzen zen afNotak[3] posizioan 66.6 balioa gorde
  • Luzera efektiboa aldatu denez iLuzera=5 jarri behar da (bigarren parametroa irteerakoa izatearen arrazoia hauxe da)

Adibidez, tokia egin eta iNon posizioan fElementua txertatu:

// -------------- Txertaketa edo Tartekaketa ---------------
// afNotak: sarrera/irteerako parametroa, zenbaki errealen
//          array bat da
// iLuzera: sarrera/irteerako parametroa, arrayaren luzera
//          logikoa adierazten du (irtetean bat gehiago)
// fElementua: sarrerako parametroa, arrayan txertatu behar
//             den elementu berriaren balioa
// iNon: sarrerako parametroa, txertatu behar den elementu
//       berriaren posizioa adierazten du   
void Tartekaketa(tafZerrenda afNotak,
                 int *iLuzera,
                 float fElementua,
                 int iNon)
{
    for (int iIndizea = *iLuzera; iIndizea >= iNon; iIndizea--)
    {
        afNotak[iIndizea + 1] = afNotak[iIndizea];
    }
    afNotak[iNon] = fElementua;
    (*iLuzera)++;
}

Elementu bakar bat txertatzeaz gain, array baten elementu guztiak banan-banan txerta daitezke array ordenatu bat prestatzeko, ikusi Ariketa 60 | Mediana eta media adibidea.

Array batean elementu berri bat txertatzeko algoritmoa ulertuz gero, erraza da ulertzea array batean elementu bakar bat nola kentzen den (ikusi 9. jarduera | Ezabaketa array batean irudia eta azalpena).

Eta arrayan elementu bat baino gehiago txertatu behar baditugu? Arrayan elementu bat baino gehiago txertatu behar baditugu bi aukera ditugu:

  1. Goiko algoritmoa hainbat aldiz errepikatzea (ikusi 10b-Txertaketa-HainbatElementu.cbp programa)
  2. Array laguntzaile bat erabiltzea. Zenbat elementu berri eta non sartuko diren teklatuz emaniko datuak ditugula array berria lortzen da 10c-Txertaketa-ArrayLaguntzailez.cbp programan

Ezaguna den iNon posizioko elementua arrayan sartu. Arraya auzaz bete ondoren, txertatuko den elementuaren fElementua balioa eta iNon posizioa ematen dira teklatuz. Arraya beterik ez dagoela frogatu ondoren, elementu berria txertatzen da Txertaketa() delako funtzioan, for agindu bati esker elementu berriari tokia egiten zaio arrayan eta jarraian fElementua esleitu egiten da iNon posizioan. Argi dago, arrayaren iLuzera luzera efektiboa inkrementatu beharko dela unitate batean.

/* 10a-Txertaketa-ElementuBakarra: Txertaketaren algoritmoa elementu bakar bati aplikatuta. */

// Arraya auzaz bete ondoren, txertatuko den elementuaren balioa eta posizioa ematen
// dira teklatuz. Arraya beterik ez dagoela frogatu ondoren, elementu berria txertatzen
// da Txertaketa() delako funtzioan, for bati esker elementu berriari tokia egiten zaio
// arrayan eta jarraian esleitu egiten da iNon posizioan. Argi dago, arrayaren iLuzera
// luzera efektiboa inkrementatu beharko dela unitate batean.

#include <stdio.h>
#include <stdlib.h>   // rand() eta srand() funtzioetarako
#include <time.h>     // time() funtzioarako

#define BEHEMUGA 0
#define GOIMUGA 19

typedef float tafZerrenda[GOIMUGA];   // gehienez 20 zenbakiren arrayak, indizeak 0-tik 19-ra

void ArrayaBete(tafZerrenda afNotak, int *iLuzera);
void ArrayaIkusi(const tafZerrenda afNotak, int iLuzera);
void Tartekaketa(tafZerrenda afNotak,
                 int *iLuzera,
                 float fElementua,
                 int iNon);

int main()
{
    tafZerrenda afNotak;
    int iLuzera, iNon;
    float fElementua;

    srand(time(NULL));

    ArrayaBete(afNotak, &iLuzera);
    ArrayaIkusi(afNotak, iLuzera);

    if (iLuzera < GOIMUGA)
    {
        do
        {
            printf("Eman zenbaki berriaren balioa (0.00 eta 9.99 artekoa): ");
            scanf("%f", &fElementua);
        } while (fElementua < 0.0 || fElementua > 9.99);

        do
        {
            printf("Zenbaki berriaren posizioa arrayan (%d eta %d artekoa): ", BEHEMUGA, iLuzera+1);
            scanf("%d", &iNon);
        } while (iNon < BEHEMUGA || iNon > iLuzera+1);

        Tartekaketa(afNotak, &iLuzera, fElementua, iNon);
        ArrayaIkusi(afNotak, iLuzera);
    }
    else
        printf("Arraya beterik dago, ezin da elementu berririk txertatu.\n");

    return 0;
}


// ArrayaBete funtzioa
void ArrayaBete(tafZerrenda afNotak, int *iLuzera)
{
    *iLuzera = rand() % GOIMUGA + 1;  // 0 eta 19 arteko balioak
    printf("Arrayan %d datu gordetzen...\n", *iLuzera + 1);
    for (int iIndizea = BEHEMUGA; iIndizea <= *iLuzera; iIndizea++)
    {
        afNotak[iIndizea] = 10.0 * rand() / RAND_MAX;  // 0.00 eta 9.99 arteko balioak
    }
}


// ArrayaIkusi funtzioa
void ArrayaIkusi(const tafZerrenda afNotak, int iLuzera)
{
    printf("Arrayaren edukia:\n");
    for (int iIndizea = BEHEMUGA; iIndizea <= iLuzera; iIndizea++)
    {
        printf("%2d. nota = %.3f\n", iIndizea, afNotak[iIndizea]);
    }
    printf("\n");
}


// -------------- Txertaketa edo Tartekaketa ---------------
// afNotak: sarrera/irteerako parametroa, zenbaki errealen
//          array bat da
// iLuzera: sarrera/irteerako parametroa, arrayaren luzera
//          logikoa adierazten du (irtetean bat gehiago)
// fElementua: sarrerako parametroa, arrayan txertatu behar
//             den elementu berriaren balioa
// iNon: sarrerako parametroa, txertatu behar den elementu
//       berriaren posizioa adierazten du   
void Tartekaketa(tafZerrenda afNotak,
                 int *iLuzera,
                 float fElementua,
                 int iNon)
{
    for (int iIndizea = *iLuzera; iIndizea >= iNon; iIndizea--)
    {
        afNotak[iIndizea + 1] = afNotak[iIndizea];
    }
    afNotak[iNon] = fElementua;
    (*iLuzera)++;
}


Arraya auzaz bete ondoren elementu berri sorta bat sartuko dugu arrayaren iNondik posizio jakin batetik aurrera. Jakin beharra dago ere zenbatekoa den elementu berrien iZenbat kopurua.

HainbatTartekaketa() funtzioan iZenbat iterazio egiten dira eta iterazio bakoitzean dagokion elementu berriaren balioa irakurtzen da teklatutik. Txertaketaren lana BatTartekakatu() funtzioak betetzen du eta iLuzera aldagaia unitate batez inkrementatzen du.

/* 10b-Txertaketa-HainbatElementu: Txertaketaren algoritmoa hainbat elementui aplikatuta. */

// Arraya auzaz bete ondoren elementu berri sorta bat sartuko dugu arrayaren
// iNondik posizio jakin batetik aurrera. Jakin beharra dago ere zenbatekoa
// den elementu berrien iZenbat kopurua.

// HainbatTartekaketa() funtzioan iZenbat iterazio egiten dira eta iterazio
// bakoitzean dagokion elementu berriaren balioa irakurtzen da teklatutik.
// Txertaketaren lana BatTartekakatu() funtzioak betetzen du eta iLuzera
// aldagaia unitate batez inkrementatzen du.

#include <stdio.h>
#include <stdlib.h>   // rand() eta srand() funtzioetarako
#include <time.h>     // time() funtzioarako

#define BEHEMUGA 0
#define GOIMUGA 19

typedef float tafZerrenda[GOIMUGA];   // gehienez 20 zenbakiren arrayak, indizeak 0-tik 19-ra

void ArrayaBete(tafZerrenda afNotak, int *iLuzera);
void ArrayaIkusi(const tafZerrenda afNotak, int iLuzera);
void BatTartekakatu(tafZerrenda afNotak,
                    int *iLuzera,
                    float fElementua,
                    int iNon);
void HainbatTartekaketa(tafZerrenda afNotak,
                        int *iLuzera,
                        int iNondik,
                        int iZenbat);

int main()
{
    tafZerrenda afNotak;
    int iLuzera, iZenbat, iNondik;

    srand(time(NULL));

    ArrayaBete(afNotak, &iLuzera);
    ArrayaIkusi(afNotak, iLuzera);

    if (iLuzera < GOIMUGA)
    {
        do
        {
            printf("Eman zenbat nota berri txertatuko diren (gehienez %d nota): ", GOIMUGA - iLuzera);
            scanf("%d", &iZenbat);
            if (iZenbat > GOIMUGA - iLuzera)
                printf("Arrayan gehienez %d elementu berri txerta daitezke.\n", GOIMUGA - iLuzera);
        } while (iZenbat < 1 || iZenbat > GOIMUGA - iLuzera);

        do
        {
            printf("Zenbaki berrien sortaren hasierako posizioa arrayan: ");
            scanf("%d", &iNondik);
            if (iNondik < BEHEMUGA || iNondik > iLuzera + 1)
                printf("Hasierako posizioa %d eta %d artekoa izan dadila.\n", BEHEMUGA, iLuzera + 1);
        } while (iNondik < BEHEMUGA || iNondik > iLuzera + 1);

        HainbatTartekaketa(afNotak, &iLuzera, iNondik, iZenbat);
        ArrayaIkusi(afNotak, iLuzera);
    }
    else
        printf("Arraya beterik dago, ezin da elementu berririk txertatu.\n");

    return 0;
}


// ArrayaBete() funtzioa
void ArrayaBete(tafZerrenda afNotak, int *iLuzera)
{
    *iLuzera = rand() % GOIMUGA + 1;  // 0 eta 19 arteko balioak
    printf("Arrayan %d datu gordetzen...\n", *iLuzera + 1);
    for (int iIndizea = BEHEMUGA; iIndizea <= *iLuzera; iIndizea++)
    {
        afNotak[iIndizea] = 10.0 * rand() / RAND_MAX;  // 0.00 eta 9.99 arteko balioak
    }
}


// ArrayaIkusi() funtzioa
void ArrayaIkusi(const tafZerrenda afNotak, int iLuzera)
{
    printf("Arrayaren edukia:\n");
    for (int iIndizea = BEHEMUGA; iIndizea <= iLuzera; iIndizea++)
    {
        printf("%9d. nota = %.3f\n", iIndizea, afNotak[iIndizea]);
    }
    printf("\n");
}


// BatTartekakatu() funtzioa
void BatTartekakatu(tafZerrenda afNotak,
                    int *iLuzera,
                    float fElementua,
                    int iNon)
{
    for (int iIndizea = *iLuzera; iIndizea >= iNon; iIndizea--) {
        afNotak[iIndizea + 1] = afNotak[iIndizea];
    }
    afNotak[iNon] = fElementua;
    (*iLuzera)++;
}


// HainbatTartekaketa() funtzioa
void HainbatTartekaketa(tafZerrenda afNotak,
                        int *iLuzera,
                        int iNondik,
                        int iZenbat)
{
    int iNon = iNondik;
    float fElementuBerria;

    for (int iIndizea = 1; iIndizea <= iZenbat; iIndizea++)
    {
        printf("Eman sortaren %d. zenbaki berriaren balioa: ", iIndizea);
        scanf("%f", &fElementuBerria);
        BatTartekakatu(afNotak, iLuzera, fElementuBerria, iNon);
        iNon++;
    }
}


Arraya auzaz bete ondoren elementu berri sorta bat sartuko dugu arrayaren iNondik posizio jakin batetik aurrera. Jakin beharra dago ere zenbatekoa den elementu berrien iZenbat kopurua.

HainbatTartekaketa() funtzioan afLaguntzailea[] arraya elikatuko da hiru zatiekin:

  1. afNotaka[] arrayaren BEHEMUGA-iNondik zatia
  2. Sorta berriaren iZenbat zatia
  3. afNotaka[] arrayaren iNondik-iLuzera zatia

Azkenean, afLaguntzailea[] arrayaren edukia afNotaka[] arrayan gordeko da eta iLuzera zaharraren balioa ordezkatuko da iLuzeraLagunt baliogatik.

/* /* 10c-Txertaketa-ArrayLaguntzailez: Txertaketaren algoritmoa hainbat elementui aplikatuta. */

// Arraya auzaz bete ondoren elementu berri sorta bat sartuko dugu arrayaren
// iNondik posizio jakin batetik aurrera. Jakin beharra dago ere zenbatekoa
// den elementu berrien iZenbat kopurua.

// HainbatTartekaketa() funtzioan afLaguntzailea[] arraya elikatuko da hiru
// zatiekin:
//      1. BEHEMUGA-iNondik zatia
//      2. Sorta berriaren iZenbat zatia
//      3. iNondik-iLuzera zatia
// Azkenean, afLaguntzailea[] arrayaren edukia afNotak[] arrayan gordeko da
// eta iLuzera zaharraren balioa ordezkatuko da iLuzeraLagun baliogatik.

#include <stdio.h>
#include <stdlib.h>   // rand() eta srand() funtzioetarako
#include <time.h>     // time() funtzioarako

#define BEHEMUGA 0
#define GOIMUGA 19

typedef float tafZerrenda[GOIMUGA];   // gehienez 20 zenbakiren arrayak, indizeak 0-tik 19-ra

void ArrayaBete(tafZerrenda afNotak, int *iLuzera);
void ArrayaIkusi(const tafZerrenda afNotak, int iLuzera);
void HainbatTartekaketa(tafZerrenda afNotak,
                        int *iLuzera,
                        int iNondik,
                        int iZenbat);

int main()
{
    tafZerrenda afNotak;
    int iLuzera, iZenbat, iNondik;

    srand(time(NULL));

    ArrayaBete(afNotak, &iLuzera);
    ArrayaIkusi(afNotak, iLuzera);

    if (iLuzera < GOIMUGA)
    {
        // Txertatzeko zenbat elementu eskatzen du
        do
        {
            printf("Eman zenbat nota berri txertatuko diren (gehienez %d nota): ", GOIMUGA - iLuzera);
            scanf("%d", &iZenbat);
            if (iZenbat > GOIMUGA - iLuzera)
                printf("Arrayan gehienez %d elementu berri txerta daitezke.\n", GOIMUGA - iLuzera);
        } while (iZenbat < 1 || iZenbat > GOIMUGA - iLuzera);

        // Txertatzeko posizioa eskatzen du
        do
        {
            printf("Zenbaki berrien sortaren hasierako posizioa arrayan: ");
            scanf("%d", &iNondik);
            if (iNondik < BEHEMUGA || iNondik > iLuzera + 1)
            printf("Hasierako posizioa %d eta %d artekoa izan dadila.\n", BEHEMUGA, iLuzera + 1);
        } while (iNondik < BEHEMUGA || iNondik > iLuzera + 1);

        HainbatTartekaketa(afNotak, &iLuzera, iNondik, iZenbat);
        ArrayaIkusi(afNotak, iLuzera);
    }
    else
        printf("Arraya beterik dago, ezin da elementu berririk txertatu.\n");

    return 0;
}


// ArrayaBete() funtzioa
void ArrayaBete(tafZerrenda afNotak, int *iLuzera)
{
    *iLuzera = rand() % GOIMUGA + 1;  // 0 eta 19 arteko balioak
    printf("Arrayan %d datu gordetzen...\n", *iLuzera + 1);
    for (int iIndizea = BEHEMUGA; iIndizea <= *iLuzera; iIndizea++)
    {
        afNotak[iIndizea] = 10.0 * rand() / RAND_MAX;  // 0.00 eta 9.99 arteko balioak
    }
}


// ArrayaIkusi() funtzioa
void ArrayaIkusi(const tafZerrenda afNotak, int iLuzera)
{
    printf("Arrayaren edukia:\n");
    for (int iIndizea = BEHEMUGA; iIndizea <= iLuzera; iIndizea++)
    {
        printf("%9d. nota = %.3f\n", iIndizea, afNotak[iIndizea]);
    }
    printf("\n");
}


// HainbatTartekaketa funtzioa
void HainbatTartekaketa(tafZerrenda afNotak,
                        int *iLuzera,
                        int iNondik,
                        int iZenbat)
{
    tafZerrenda afBerriak, afLaguntzailea;
    int iLuzeraLagun = -1;

    // Berria den balioak hartzea
    for (int iIndizea = 0; iIndizea < iZenbat; iIndizea++)
    {
        printf("Eman sortaren %d. zenbaki berriaren balioa: ", iIndizea);
        scanf("%f", &afBerriak[iIndizea]);
    }

    // Hasierako array kopiatzea laguntzailean iNondik posizioraino
    for (int iIndizea = BEHEMUGA; iIndizea < iNondik; iIndizea++)
    {
        iLuzeraLagun++;
        afLaguntzailea[iLuzeraLagun] = afNotak[iIndizea];
    }

    // Berria den balioak laguntzailean kopiatzea
    for (int iIndizea = 0; iIndizea < iZenbat; iIndizea++)
    {
        iLuzeraLagun++;
        afLaguntzailea[iLuzeraLagun] = afBerriak[iIndizea];
    }

    // Arrayko geratzen diren elementuak kopiatu laguntzailean
    for (int iIndizea = iNondik; iIndizea <= *iLuzera; iIndizea++)
    {
        iLuzeraLagun++;
        afLaguntzailea[iLuzeraLagun] = afNotak[iIndizea];
    }

    // Laguntzaileko edukia hasierako arrayra kopiatzea
    for (int i = BEHEMUGA; i <= iLuzeraLagun; i++)
        afNotak[i] = afLaguntzailea[i];

    *iLuzera = iLuzeraLagun;
}






  • 10a-Txertaketa-ElementuBakarra.cbp | main.c  
  • 10b-Txertaketa-HainbatElementu.cbp | main.c  
  • 10c-Txertaketa-ArrayLaguntzailez.cbp | main.c  


 

iruzkinik ez:

Argitaratu iruzkina