• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

Usuwanie ostatniego elementu w liscie jednokierunkowej

Object Storage Arubacloud
0 głosów
560 wizyt
pytanie zadane 4 czerwca 2020 w C i C++ przez kamylmeister Nowicjusz (190 p.)
void lista::usun_osobe_nazwisko(string nazwisko)
{
	osoba* temp = pierwsza;

	while (temp)
	{
		if (temp->nazwisko == nazwisko)
		{
			if(temp==pierwsza)
			{
				pierwsza = temp->nastepna;
			}

			else
			{
				osoba* usuwana = temp;
				temp = temp->nastepna;
				delete usuwana;
			}	
		
		}
		temp = temp->nastepna;
	}
}

Dzień dobry, 

Muszę napisać usuwanie osoby po nazwisku w liscie jednokierunkowej, wszystko mi działa oprócz usuwania osoby, gdy jest ostatnia na liscie. Mógłby ktos pomóc?

komentarz 4 czerwca 2020 przez LuQ232 Mądrala (7,200 p.)

Czy tutaj jest potrzeba aby przesunąć wskaźnik?

else
            {
                osoba* usuwana = temp;
                temp = temp->nastepna;
                delete usuwana;
            }   

Po usunięciu jak wyjdziesz z ifa znowu go przesuniesz i wydaje mi się, że jeżeli w liscie beda dwie osoby o tym samym nazwisku koło siebie to skasujesz tylko jedną

 

komentarz 4 czerwca 2020 przez kamylmeister Nowicjusz (190 p.)
Dzięki za zwrócenie uwagi na błąd, racja
komentarz 4 czerwca 2020 przez LuQ232 Mądrala (7,200 p.)
Chociaż jeżeli usuniesz tą linijkę o której mówimy to tracisz wskaźnik temp...

Wydaje mi się, że wskaźnik po całym ifie powinniśmy przesunąć tylko wtedy gdy nie usuneliśmy już osoby, bo jeżeli usuneliśmy osobę to przesuwamy go podwójnie.

Podeślesz cały kod, wtedy lepiej wszystko będzie widać?
komentarz 4 czerwca 2020 przez LuQ232 Mądrala (7,200 p.)

void lista::usun_osobe_nazwisko(string nazwisko)
{
    osoba* temp = pierwsza;
    bool czy_usunieto_osobe = false;
    while (temp != NULL)
    {
        czy_usunieto_osobe = false;
        if (temp->nazwisko == nazwisko)
        {
            if(temp==pierwsza)
            {
                pierwsza = temp->nastepna;
            }
            else
            {
                osoba* usuwana = temp;
                temp = temp->nastepna;
                delete usuwana;
                czy_usunieto_osobe = true;
            }   
        }
        if(!czy_usunieto_osobe)
            temp = temp->nastepna;
    }
}

To chyba naprawia problem kasowania osób będących koło siebie z tymi samymi nazwiskami.

komentarz 4 czerwca 2020 przez kamylmeister Nowicjusz (190 p.)
#include <iostream>
#include <string>
#include <cstdlib>
#include <windows.h>

using namespace std;

struct osoba {
	string imie;
	string nazwisko;
	int wiek;
	osoba* nastepna; // wskaźnik na następny element
	osoba(); // konstruktor
};

osoba::osoba() {
	nastepna = 0; // konstruktor
}

struct lista {
	osoba* pierwsza; // wskaźnik na początek listy
	void dodaj_osobe(string imie, string nazwisko, int wiek);
	void usun_osobe(int nr);
	void wyswietl_liste();
	void usun_osobe_nazwisko(string nazwisko);
	void znajdz_osobe_nazwisko(string nazwisko);
	lista();
};

lista::lista() {
	pierwsza = 0; // konstruktor
}

void lista::wyswietl_liste()
{
	// wskaznik na pierszy element listy
	osoba* temp = pierwsza;

	// przewijamy wskazniki na nastepne elementy
	while (temp)
	{
		cout << "imie: " << temp->imie << ", nazwisko: " << temp->nazwisko << ", wiek: " << temp->wiek << endl;
		temp = temp->nastepna;
	}
}

void lista::usun_osobe(int nr)
{
	// jezeli to pierwszy element listy
	if (nr == 1)
	{
		osoba* temp = pierwsza;
		pierwsza = temp->nastepna; //ustawiamy poczatek na drugi element
		delete temp; // usuwamy stary pierwszy element z pamieci
	}

	// jeżeli nie jest to pierwszy element
	else if (nr >= 2)
	{
		int j = 1;

		// do usuniecia srodkowego elemetnu potrzebujemy wskaznika na osobe n-1
		// wskaznik *temp bedzie wskaznikiem na osobe poprzedzajaca osobe usuwana
		osoba* temp = pierwsza;

		while (temp)
		{
			// sprawdzamy czy wskaznik jest na osobie n-1 niz usuwana
			if ((j + 1) == nr) break;

			// jezeli nie to przewijamy petle do przodu
			temp = temp->nastepna;
			j++;
		}

		// wskaznik *temp wskazuje teraz na osobe n-1
		// nadpisujemy wkaznik n-1 z osoby n na osobe n+1
		// bezpowrotnie tracimy osobe n-ta

		// jezeli usuwamy ostatni element listy
		if (temp->nastepna->nastepna == 0) {
			delete temp->nastepna;
			temp->nastepna = 0;
		}
		// jezeli usuwamy srodkowy element
		else {
			osoba* usuwana = temp->nastepna;
			temp->nastepna = temp->nastepna->nastepna;
			delete usuwana;
		}
	}
}

void lista::dodaj_osobe(string imie, string nazwisko, int wiek)
{
	osoba* nowa = new osoba; // tworzy nowy element listy

	// wypełniamy naszymi danymi
	nowa->imie = imie;
	nowa->nazwisko = nazwisko;
	nowa->wiek = wiek;

	if (pierwsza == 0) // sprawdzamy czy to pierwszy element listy
	{
		// jeżeli tak to nowy element jest teraz początkiem listy
		pierwsza = nowa;
	}
	else
	{
		// w przeciwnym wypadku wędrujemy na koniec listy
		osoba* temp = pierwsza;

		while (temp->nastepna)
		{
			// znajdujemy wskaźnik na ostatni element
			temp = temp->nastepna;
		}

		temp->nastepna = nowa; // ostatni element wskazuje na nasz nowy
	}
}

void lista::znajdz_osobe_nazwisko(string nazwisko)
{
	// wskaznik na pierszy element listy
	osoba* temp = pierwsza;

	// przewijamy wskazniki na nastepne elementy, wyswietlajac tylko osoby z danym nazwiskiem
	while (temp)
	{
		if (nazwisko == temp->nazwisko)
		{
			cout << "imie: " << temp->imie << ", nazwisko: " << temp->nazwisko << ", wiek: " << temp->wiek << endl;
		}
		temp = temp->nastepna;
	}
	Sleep(5000);
}

void lista::usun_osobe_nazwisko(string nazwisko)
{
	osoba* temp = pierwsza;

	while (temp)
	{
		if (temp->nazwisko == nazwisko)
		{
			if(temp==pierwsza)
			{
				pierwsza = temp->nastepna;
			}

			else
			{
				osoba* usuwana = temp;
				delete usuwana;
			}	
		}
		temp = temp->nastepna;
	}
}

int main()
{
	lista* baza = new lista; // tworzymy liste

	int wybor;

	string n_imie, n_nazwisko;
	int n_wiek;

	int do_usuniecia;

	string nazwisko_usuwane;

	string nazwisko_szukane;

	do
	{
		cout << "Co chcesz zrobic?" << endl;
		cout << "1. Dodac osobe" << endl;
		cout << "2. Usunac osobe po numerze" << endl;
		cout << "3. Usunac osobe po nazwisku" << endl;
		cout << "4. Wypisac wszystkich" << endl;
		cout << "5. Wyszukac osobe po nazwisku" << endl;
		cout << "6. Zakonczyc program" << endl;

		cin >> wybor;

		switch (wybor)
		{
		case 1:
			cout << "Podaj imie osoby: ";
			cin >> n_imie;
			cout << "Podaj nazwisko osoby: ";
			cin >> n_nazwisko;
			cout << "Podaj wiek osoby: ";
			cin >> n_wiek;
			baza->dodaj_osobe(n_imie, n_nazwisko, n_wiek);
			break;
		case 2:
			cout << "Podaj numer osoby: ";
			cin >> do_usuniecia;
			baza->usun_osobe(do_usuniecia);
			break;
		case 3:
			cout << "Podaj nazwisko: ";
			cin >> nazwisko_usuwane;
			baza->usun_osobe_nazwisko(nazwisko_usuwane);
			break;
		case 4:
			baza->wyswietl_liste();
			Sleep(3000);
			break;
		case 5:
			cout << "Podaj nazwisko do odszukania: ";
			cin >> nazwisko_szukane;
			baza->znajdz_osobe_nazwisko(nazwisko_szukane);
			break;
		case 6:
			exit;
		}

		system("CLS");

	} while (wybor != 6);

	return 0;
}

Bez Twojego kodu samemu napisałem cos takiego

komentarz 4 czerwca 2020 przez kamylmeister Nowicjusz (190 p.)

@LuQ232, Wszystko super działa, zaimplementowałem Twój kod, tylko dalej nie chce usuwać ostatniej osoby na liście. Sam "proces" usuwania się kończy, ale gdy chcę wyświetlić listę, to program się wykrzacza, jakas porada? 

komentarz 4 czerwca 2020 przez LuQ232 Mądrala (7,200 p.)
Chwilowo nie mam czasu, aby głęboko wejść w twój kod. Patrząc powierzchownie to usuwając daną osobę (załóżmy ze ma numer n) musisz umieścić wskaźnik next  poprzedniej osoby (n-1) na osobę kolejną czyli na (n+1). Bo z tego co widzę tego nie robisz. Program dlatego sie wywala. Bo usuwasz osobę i nie ma już "połączenia" między kolejnymi osobami.

Zaloguj lub zarejestruj się, aby odpowiedzieć na to pytanie.

Podobne pytania

0 głosów
1 odpowiedź 111 wizyt
+1 głos
1 odpowiedź 128 wizyt
0 głosów
1 odpowiedź 470 wizyt
pytanie zadane 8 maja 2020 w C i C++ przez Dyali56 Nowicjusz (150 p.)

92,570 zapytań

141,422 odpowiedzi

319,643 komentarzy

61,958 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Kolejna edycja największej imprezy hakerskiej w Polsce, czyli Mega Sekurak Hacking Party odbędzie się już 20 maja 2024r. Z tej okazji mamy dla Was kod: pasjamshp - jeżeli wpiszecie go w koszyku, to wówczas otrzymacie 40% zniżki na bilet w wersji standard!

Więcej informacji na temat imprezy znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...