Jak usunąć trójki w sznurze?

0

Mam problem z zadaniem potrzebuje pomocy oto jego treść:

Funkcja usun rozpatrującą rozłączne trójki elementów sznura i usuwającą:

  • drugi element trójki jeśli średnia trójki jest większa od G (gdzie G jest liczbą całkowitą będącą parametrem funkcji),
  • w przeciwnym przypadku - całą trójkę oraz dwa, znajdujące się najbliżej za trójką (czyli pierwszy i drugi odpowiedni, idąc w kierunku końca sznura),
  • elementy przechowujące liczby występujące w tej trójce (o ile takie elementy istnieją; przy czym jeśli jest tylko jeden taki element, to też jest usuwany). Usunięte elementy za trójkami" nie wchodzą skład kolejnych sprawdzanych trójek.

Pamięć zajmowana przez usuwane elementy ma zostać zwolniona.
Funkcja nie może używać tablic, pomocniczych sznurów ani struktur danych dostępnych w bibliotece standardowej (wektorów, list, kolejek, itp.).

Przykład: dla G-100 sznur: 7,2,6,4,8,9,3,2,5,6,500,2,2,1,1,1,7 zostanie przekształcony do postaci 3,500,7 (pierwsza trójka to 7,2,6 jej średnia nie jest większa niż G, więc usuwamy całą trójkę i do tego 2 i 6 znajdujące się w dalszej części sznura (pierwsze znalezione w dalszej części sznura liczby z trójki); kolejna trójka to 4,8,9, jej średnia nie jest większa niż G, ale usuwamy tylko tę trójkę, bo w dalszej części sznura nie ma 4, 8 ani 9; kolejna trójka to 3,5,500 (2 i 6 zostały wcześniej usunięte), ma ona średnią większą od G, więc usuwamy z niej 5, kolejna trójka to 2,2,1, jej średnia nie jest większa od G, więc usuwamy całą trójkę i do tego 1,1 stojące za nią)

Oto mój kod:

void sznur::usun(int G)
{
    Node*tmp=pocz;
    int ilosc=1;
    int war=0;
    float srd=0;
    while(tmp!=nullptr)
    {
        if(tmp->dane%2==0)
        {
            srd+=tmp->dane;
            ilosc++;
        }
        tmp=tmp->nast;
        war++;
    }
    srd=srd/ilosc;
    Node*zaszuk=nullptr;
    Node*a=pocz;
    while(a!=nullptr && a->nast!=nullptr && a->nast->nast!=nullptr)
    {
        Node*jeden=a;
        Node*dwa=a->nast;
        Node*trzy=a->nast->nast;
        if(srd>G)
        {
            if(zaszuk!=nullptr)
            {
                zaszuk->nast=trzy->nast;
            }
            else
            {
                pocz=trzy->nast;
            }
            delete dwa;
            ileJest--;
            zaszuk=trzy;
            a=zaszuk->nast;
        }
        else
        {
            if(zaszuk!=nullptr)
            {
                zaszuk->nast=trzy->nast;
            }
            else
            {
                pocz=trzy->nast;
            }
            delete jeden;
            delete dwa;
            delete trzy;
            ileJest=ileJest-3;
            zaszuk=trzy;
            a=zaszuk->nast;
        }
    }
}
//7 2 6 4 8 9 3 2 5 6 500 2 2 1 1 1 7 -> 3,500,7

Problem polega na tym iż "Przykład: dla G-100 sznur 7,2,6,4,8,9,3,2,5,6,500,2,2,1,1,1,7 zostanie przekształcony do postaci 3,500,7 (pierwsza trójka to 7,2,6; jej średnia nie jest większa niż G, więc usuwamy całą trójkę i do tego 2 i 6 znajdujące się w dalszej części sznura" moje pytanie brzmi jak usinąć całą trójke (to akurat wiem) ale do tego elementy 2 i 6 znajdujące się w dalszej części szura bo nie za bardzo rozumiem jak mam to zrobić jak mam je usunąć z góry dzięki za pomoc

1

A widziałeś moją odpowiedź w twoim poprzednim pytaniu?
https://4programmers.net/Forum/C_i_C++/369217-zadanie_usun_podciagi_podzielne_przez_k_oraz_jeden_element_za_nim_z_listy_polaczonej?p=1920953#id1920953
Ta sama odpowiedź ma zastosowanie w tym przypadku.

Tak jak poprzedni ponarzekam, że nie dałeś całego kodu.


A jescze jedno. Mamy 2023 ergo używanie smart pointerów z C++11 takich jak std::unique_ptr powinno być już powszechną praktyką.

0
MarekR22 napisał(a):

A widziałeś moją odpowiedź w twoim poprzednim pytaniu?
https://4programmers.net/Forum/C_i_C++/369217-zadanie_usun_podciagi_podzielne_przez_k_oraz_jeden_element_za_nim_z_listy_polaczonej?p=1920953#id1920953
Ta sama odpowiedź ma zastosowanie w tym przypadku.

Tak jak poprzedni ponarzekam, że nie dałeś całego kodu.


A jescze jedno. Mamy 2023 ergo używanie smart pointerów z C++11 takich jak std::unique_ptr powinno być już powszechną praktyką.

Jeśli chodzi o cały kod to prosze
sznur.h

#ifndef SZNUR_H_INCLUDED
#define SZNUR_H_INCLUDED
struct sznur{
private:
    struct Node{
        int dane;
        Node*nast;
        Node(int d,Node*N=nullptr)
        {
            dane=d;
            nast=N;
        }
    };
    Node*pocz;
    int ileJest;
public:
    sznur();
    ~sznur();
    void wypisz();
    void wstaw(int a);
    void usun(int G);
};
#endif // SZNUR_H_INCLUDED

sznur.cpp
#include"sznur.h"
#include <iostream>
using namespace std;
sznur::sznur()
{
    pocz=nullptr;
    ileJest=0;
}
sznur::~sznur()
{
    Node*nowy=pocz;
    while(nowy!=nullptr)
    {
        Node*szuk;
        szuk=nowy->nast;
        delete nowy;
        nowy=szuk;
    }
}
void sznur::wypisz()
{
    Node*nowy=pocz;
    while(nowy!=nullptr)
    {
        cout<<nowy->dane<<" , ";
        nowy=nowy->nast;
    }
    cout<<endl;
}
void sznur::wstaw(int a)
{
    Node*nowy;
    nowy = new Node(a);
    if(pocz==nullptr)
    {
        pocz=nowy;
        return;
    }
    else
    {
        Node*szuk=pocz;
        while(szuk->nast!=nullptr)
        {
            szuk=szuk->nast;
        }
        szuk->nast=nowy;
    }
    ileJest++;
}
void sznur::usun(int G)
{
    Node*tmp=pocz;
    int ilosc=1;
    int war=0;
    float srd=0;
    while(tmp!=nullptr)
    {
        if(tmp->dane%2==0)
        {
            srd+=tmp->dane;
            ilosc++;
        }
        tmp=tmp->nast;
        war++;
    }
    srd=srd/ilosc;
    Node*zaszuk=nullptr;
    Node*a=pocz;
    while(a!=nullptr && a->nast!=nullptr && a->nast->nast!=nullptr)
    {
        Node*jeden=a;
        Node*dwa=a->nast;
        Node*trzy=a->nast->nast;
        Node* szukaj = trzy->nast;
        Node* poprzedni = trzy;
        int licznik = 2;
        if(srd>G)
        {
            if (zaszuk != nullptr) {
                zaszuk->nast = jeden;
            } else {
                pocz = jeden;
            }
            delete dwa;
            ileJest--;
            zaszuk = trzy;
            a = zaszuk->nast;
        } else {
            if (zaszuk != nullptr) {
                zaszuk->nast = szukaj->nast->nast;
            } else {
                pocz = poprzedni->nast->nast->nast->nast;
            }

            delete jeden;
            delete dwa;
            delete trzy;
            ileJest -= 3;
        while (szukaj != nullptr && licznik > 0) {
                if (szukaj->dane == jeden->dane || szukaj->dane == dwa->dane || szukaj->dane == trzy->dane) {
                    poprzedni->nast = szukaj->nast;
                    delete szukaj;
                    ileJest--;
                    szukaj = poprzedni->nast;
                    licznik--;
                } else {
                    poprzedni = szukaj;
                    szukaj = szukaj->nast;
                }
            }
            zaszuk = trzy;
            a = zaszuk->nast;
        }
    }
}
//7 2 6 4 8 9 3 2 5 6 500 2 2 1 1 1 7

main.cpp
#include"sznur.h"
#include <iostream>
using namespace std;

int main()
{
    sznur s;
    string x;
    int g;
    while(true)
    {
        cout<<"Podaj liczbe: "<<endl;
        cin>>x;
        if(x=="a")
        {
            cout<<"Podaj G: "<<endl;
            cin>>g;
            s.usun(g);
        }
        else
        {
            s.wstaw(stoi(x));
        }
        s.wypisz();
    }
    return 0;
}

1

https://godbolt.org/z/ee5ovKTTM

<source>: In member function 'void sznur::usun(int)':
<source>:125:44: error: pointer 'a' may be used after 'void operator delete(void*, std::size_t)' [-Werror=use-after-free]
  125 |                 if (szukaj->dane == jeden->dane || szukaj->dane == dwa->dane || szukaj->dane == trzy->dane) {
      |                                     ~~~~~~~^~~~
<source>:120:20: note: call to 'void operator delete(void*, std::size_t)' here
  120 |             delete jeden;
      |                    ^~~~~
<source>:125:44: error: pointer 'a' may be used after 'void operator delete(void*, std::size_t)' [-Werror=use-after-free]
  125 |                 if (szukaj->dane == jeden->dane || szukaj->dane == dwa->dane || szukaj->dane == trzy->dane) {
      |                                     ~~~~~~~^~~~
<source>:120:20: note: call to 'void operator delete(void*, std::size_t)' here
  120 |             delete jeden;
      |                    ^~~~~
<source>:140:1: error: pointer 'a' may be used after 'void operator delete(void*, std::size_t)' [-Werror=use-after-free]
  140 | }
      | ^
<source>:120:20: note: call to 'void operator delete(void*, std::size_t)' here
  120 |             delete jeden;

.....

1 użytkowników online, w tym zalogowanych: 0, gości: 1