Listy jednokierunkowe- porównywanie dwóch list.

0

Cześć, mam pewien problem z przedstawioną niżej funkcją, po prostu nie działa- pojawia się komunikat o błędzie SIGSEGV, ale nie wiem dlaczego, bo wydaje mi się, że nie ma problemu z alokacją pamięci. Przedstawiona przeze mnie funkcje porównuje dwa listy kiednokierunkowe ze wskaźnikiem na pierwszy element, gdy znajdzie takie same węzły, usuwa je zarówno z jednej listy, jak i z drugiej. I tak dalej, aż druga lista pozostanie pusta.
(Funkcja remove- usuwa dany węzeł, funkcja change- zmienia ostatni węzeł według schematu).
Proszę o pomoc i z góry dziękuję za wszystkie wskazówki.

void crossout(node *&head1, node *&head2)
{
	node *temp1=head1;
	node *temp2=head2;
	while(head2!=NULL)
{
	while(temp2!=NULL)
	{
		while(temp1!=NULL)
		{
			if(temp1->x==temp2->x)
			{

				remove(head1,temp1);
				remove(head2,temp2);
				temp1=head1;
				temp2=head2;

			}
			else{
			temp1=temp1->next;	
			}
		}temp2=temp2->next; 
		temp1=head1;
	}
	change(head1);
	temp1=head1;
	temp2=head2;
}
} 
1

Sformatuj kod po ludzku oraz podaj treść funkcji remove() i change().

0

Co to znaczy "sformatuj kod po ludzku"? Co tu jest nie tak?
Remove:

 
void remove(node *&head, node *x)
{
	if(head!=x)
	{
		node *temp=head;
		while(temp->next!=x)	temp=temp->next;
		temp->next=x->next;
		delete x;
	}
	else
	{
		node *temp=head;
		if(temp==NULL) return;
		head=temp->next;
		delete temp;
	}
}

change

void change(node *&head)
{
	node *temp=head;
	while(temp->next!=NULL)
	{
		temp=temp->next;
	}
	switch(temp->x)
	{
		case 'M': {removeLast(head);addBack(head,'D');addBack(head,'D');}break;
		case 'D': {removeLast(head);addBack(head,'C');addBack(head,'C');addBack(head,'C');addBack(head,'C');
				addBack(head,'C');}break;
		case 'C': {removeLast(head);addBack(head,'L');addBack(head,'L');}break;
		case 'L': {removeLast(head);addBack(head,'X');addBack(head,'X');addBack(head,'X');addBack(head,'X');
				addBack(head,'X');}break;
		case 'X': {removeLast(head);addBack(head,'V');addBack(head,'V');}break;
		case 'V': {removeLast(head);addBack(head,'I');addBack(head,'I');addBack(head,'I');addBack(head,'I');
				addBack(head,'I');}break;
		default: return;break;
}
} 
0

W kodzie masz użyte kolejne funkcje removeLast() i addBack() podaj ich treść również.
Podpowiadam że jeżeli oni wywołują jakieś inne funkcje to ich również należy podać.

0
void removeLast(node *&head)
{
	node *temp=head;
	if(temp==NULL) return;
	if(temp->next!=NULL)
	{
		while(temp->next->next!=NULL)	temp=temp->next;
		delete temp->next;
		temp->next=NULL;
	}
	else
	{
		delete temp;
		head=NULL;
	}
} 
void addBack(node *&head,char x)
{
	node *N=new node;
	N->x=x;
	N->next=NULL;
	node *temp=head;
	if(temp!=NULL)
	{
		while(temp->next!=NULL)
		{
			temp=temp->next;
		}
		temp->next=N;
	}else
	{
		head=N;
	}
} 

struktura:

 
{
	char x;
	node *next;
};
0

to: case 'M': {removeLast(head);addBack(head,'D');addBack(head,'D');}break;
zamień na: case 'M': {temp->x='D';addBack(head,'D');}break;
Analogicznie resztę.

Usuwanie z końca oraz dodawanie na koniec listy jednokierunkowej to poroniony pomysł no chyba że trzymasz wskaźnik na ostatni element.
Usuwanie ze środka listy jednokierunkowej to zawsze poroniony pomysł - potrzebna lista dwukierunkowa.
Wytłumacz mi czemu nie działasz na zwykłym string'u - tak jak zorganizowałeś listę na string'u będzie o wiele krótszy kod a przy tym o wiele szybszy.
Aby zrobić porządnie na strukturach potrzebujesz:

struct node { char x; node *next,*prev; }
struct list { node *head,*tail; }
0

Zamień:

while(head2!=NULL)

Na:

if(head2!=NULL)

lub zrób coś żeby head2 się zmieniało.

0

_13th_Dragon: to faktycznie przy tym switchu troszkę głupio zrobiłem. Ale już to poprawiłem, co do reszty, próbowałem z listą dwukierunkową- faktycznie usprawni to mój program, lecz mimo tego, coś jest nie tak w funkcji crossout (tak sądzę). Nie działa ona tak jak bym tego chciał.
vpiotr: wydaje mi się, że ten while jest tam ok. Bo po właściwym wykonaniu operacji, lista nr 2 powinna zostać pusta i wtedy opuszczamy pętle.

0

To po zamianie na listy na stringa wygląda to tak:

void change(string roman)
{

	switch(roman[roman.length()-1])
	{
		case 'M': {roman[roman.length()-1]='D';roman+='D';}break;
		case 'D': {roman[roman.length()-1]='C';roman+='C';roman+='C';roman+='C';roman+='C';}break;
		case 'C': {roman[roman.length()-1]='L';roman+='L';}break;
		case 'L': {roman[roman.length()-1]='X';roman+='X';roman+='X';roman+='X';roman+='X';}break;
		case 'X': {roman[roman.length()-1]='V';roman+='V';}break;
		case 'V': {roman[roman.length()-1]='I';roman+='I';roman+='I';roman+='I';roman+='I';}break;
		default: return;break;
}
}
string crossout(string rom1, string rom2)
{
	while(rom2.length()>0)
	{
	for(int i=0;i<rom1.length();i++)
	{
		for(int j=0;rom2.length();j++)
		{
			if(rom1[i]==rom2[j])
			{
				rom1.erase(i);
				rom2.erase(j);
			}
		}
	}
	change(rom1);
	}
	return rom1;
}
 

Ale niestety wciąż nie działa.

0
  1. zamiast: roman[roman.length()-1]='D'; użyj: roman.back()='D';
  2. do change() przekazuj przez referencje
  3. po erase() nie powinieneś inkrementować pozycji.
0
  1. jak wpiszę roman.back()='D'; to pojawia sie błąd "[Error] 'std::string' has no member named 'back'"
  2. zmieniłem funckja change() na:
void change(string roman)
{
	if(roman[roman.length()-1]=='M')
	{
		roman[roman.length()-1]='D';
		roman+='D';
	}
	else if(roman[roman.length()-1]=='D')
	{
		roman[roman.length()-1]='C';
		roman+='C';
		roman+='C';
		roman+='C';
		roman+='C';
	}
	else if(roman[roman.length()-1]=='C')
	{
		roman[roman.length()-1]='L';
		roman+='L';
	}
	else if(roman[roman.length()-1]=='L')
	{
		roman[roman.length()-1]='X';
		roman+='X';
		roman+='X';
		roman+='X';
		roman+='X';
	}
	else if(roman[roman.length()-1]=='X')
	{
		roman[roman.length()-1]='V';
		roman+='V';
	}
	else if(roman[roman.length()-1]=='V')
	{
		roman[roman.length()-1]='I';
		roman+='I';
		roman+='I';
		roman+='I';
		roman+='I';
	}
	else
	{
		return;
	}
} 

Wiem, troszkę miejsca zajmuję. I tu jak przekazuję referencje- to mi w ogóle nie działa.
3. Tzn, że jak inkrementowac pozycji? W jaki sposób mógłbym to zastąpić?

Dzięki za rady.

0

http://www.cplusplus.com/reference/string/string/back/
możesz użyć: *(str.rbegin())='D';

0
void change(string roman)
{
	if(roman[roman.length()-1]=='M')
	{
		roman[roman.length()-1]='D';
		roman+='D';
	}
	else if(roman[roman.length()-1]=='D')
	{
		roman[roman.length()-1]='C';
		roman+='C';
		roman+='C';
		roman+='C';
		roman+='C';
	}
	else if(roman[roman.length()-1]=='C')
	{
		roman[roman.length()-1]='L';
		roman+='L';
	}
	else if(roman[roman.length()-1]=='L')
	{
		roman[roman.length()-1]='X';
		roman+='X';
		roman+='X';
		roman+='X';
		roman+='X';
	}
	else if(roman[roman.length()-1]=='X')
	{
		roman[roman.length()-1]='V';
		roman+='V';
	}
	else if(roman[roman.length()-1]=='V')
	{
		roman[roman.length()-1]='I';
		roman+='I';
		roman+='I';
		roman+='I';
		roman+='I';
	}
	else
	{
		return;
	}
}
string crossout(string rom1, string rom2)
{
	while(rom2.length()>0)
	{
	for(int i=0;i<rom1.length();i++)
	{
		for(int j=0;j<rom2.length();j++)
		{
			if(rom1[i]==rom2[j])
			{
				rom1.erase(i,1);
				rom2.erase(j,1);
			}
		}
	}
	change(rom1);
 }
	return rom1;
}
string shorten(string roman)
{
	for(int i=0;i<roman.size();i++)
	{
		int it=1;
		for(int j=i+1;j<roman.size();j++)
		{
			if(roman[i]==roman[j])
			{
				it++;
			}
		}
		if(it==2)
		{
			if(roman[i]=='D')
			{
				roman.erase(i,1);
				roman.insert(i,1,'M');
				roman.erase(i+1,1);
				
			}
			if(roman[i]=='L')
			{
				roman.erase(i,1);
				roman.insert(i,1,'C');
				roman.erase(i+1,1);
				
			}
				if(roman[i]=='V')
			{
				roman.erase(i,1);
				roman.insert(i,1,'X');
				roman.erase(i+1,1);
				
			}
		}
		if(it==3)
		{
			if(roman[i]=='D')
			{
				roman.erase(i,1);
				roman.insert(i,"MD");
				roman.erase(i+2,1);	
				roman.erase(i+3,1);	
			}
			if(roman[i]=='L')
			{
				roman.erase(i,1);
				roman.insert(i,"CL");
				roman.erase(i+2,2);	
			}
			if(roman[i]=='V')
			{
				roman.erase(i,1);
				roman.insert(i,"XV");
				roman.erase(i+2,2);	
			}
		}
		if(it==4)
		{
			if(roman[i]=='C')
			{
				roman.erase(i,1);
				roman.insert(i,"CD");
				roman.erase(i+2,3);	
			}
			if(roman[i]=='L')
			{
				roman.erase(i,1);
				roman.insert(i,"CC");
				roman.erase(i+2,3);	
			}
			if(roman[i]=='X')
			{
				roman.erase(i,1);
				roman.insert(i,"XL");
				roman.erase(i+2,3);	
			}
			if(roman[i]=='V')
			{
				roman.erase(i,1);
				roman.insert(i,"XX");
				roman.erase(i+2,3);	
			}
			if(roman[i]=='I')
			{
				roman.erase(i,1);
				roman.insert(i,"IV");
				roman.erase(i+2,3);	
			}
		}
		if(roman[i]=='D' && roman[i+1]=='C' && roman[i+2]=='D')
		{
			roman.erase(i,1);
			roman.insert(i,"CM");
			roman.erase(i+2,2);
		}
		if(roman[i]=='L' && roman[i+1]=='X' && roman[i+2]=='L')
		{
			roman.erase(i,1);
			roman.insert(i,"XC");
			roman.erase(i+2,2);
		}
			if(roman[i]=='V' && roman[i+1]=='I' && roman[i+2]=='V')
		{
			roman.erase(i,1);
			roman.insert(i,"IX");
			roman.erase(i+2,2);
		}
	}

	return roman;
}
 

Co tu jest nie tak? zwłaszcza z funkcją crossout()?

0

już ci mówiłem, jak zrobiłeś .erase() to i czy tam j wskazuje na następny element, i jak robisz i++ ...
UWAGA: nie stosuj i++ tam gdzie możesz zastosować ++i.
... to pomijasz jeden element.
Może podaj pełną treść zadania bo z tego bajzlu trudno wywnioskować cokolwiek.

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