Merge_sort na listach - przepisywanie pamięci przy dzieleniu

0

Witam. Jestem na etapie pisania funkcji, która zwróci dwie funkcje będące podziałem pierwszej (procedura "dziel" w merge sort). Mam problem z przepisywaniem pamięci. Jako parametr przekazujemy listę główną, i dwie puste, do których będziemy przepisywać pamięć. Od pierwszego wskaźnika pojawia się problem z przepisaniem pamięci do wskaźników - są po prostu puste, kompilator informuje, że niemożliwy jest odczyt pamięci. Kod jeszcze nie jest dokończony, ale na tym etapie, wydaje mi się, powinno wszystko działać. Prosiłbym o pomoc.

#include <iostream>
#include <cstdlib>
#include <iomanip>
#include <time.h>
#include <cmath>
using namespace std;
struct mode
{
	int vol;
	mode *next;
};
void push(mode *&head, int x)
{
	mode *pon = new mode;
	pon->vol = x;
	pon->next = head;
	head = pon;
}
void show(mode *head)
{
	cout << "head-> ";
	mode *p = head;

	while (p != NULL)
	{
		cout << p->vol << " -> ";
		p = p->next;
	}
	cout << "NULL" << endl;
}

void split_list(mode*& p, mode*& p2, mode*& p3)
{
	int srodek, licznik = 0;
	mode* p_head = p;

	while (p->next)
	{
		licznik = licznik + 1;
		p = p->next;
	}

	licznik = licznik + 1;
	srodek = licznik / 2;

	licznik = 0;
	p = p_head;
	p3 = p;

	while (licznik != srodek)
	{
		p3 = p3->next;
		licznik = licznik + 1;
	}

	p2 = p_head;

	while (p2 != p3->next)
	{
		p2 = p->next;
	}

	p2->next = NULL;
	p2 = p;

	while (p2) // funkcja tymczasowa, do sprawdzenia, czy lista dochodzi do połowy.
	{
		cout << p2->vol << "->";
		p2 = p->next;
	}

}

int main()
{
	mode* head = NULL;
	mode* head2 = NULL;
	mode* head3 = NULL;

	push(head, 5);
	push(head, 103);
	push(head, 100);
	push(head, 12);
	push(head, 1052);
	push(head, 10);


	show(head);
	split_list(head, head2, head3);
	show(head);

	system("pause");
}

 
1
p2 = p->next;

słabe to przechodzenie po liście.

Na oko to pociąłeś listę mniej więcej w połowie, ale nie trzymasz żadnego wskaźnika do drugiej połowy, przez co potem stracisz do niej dostęp.

0

Faktycznie, leci łapka. Chciałbym jeszcze spytać, czy w trakcie merga bazować na jednej liście połączonej wskaźnikami (dzięki którymi ustalimy środek, początek, koniec w jednej liście, jak w klasycznym mergu), czy powstawiać przy ostatnich elementach nulle w taki sposób, żeby dwie listy stały się osobne?

1

Zrób tak jak Ci wygodnie. Jak te nulle upraszczają jakąś operację, to je wstaw. A jak nie to po co.

1

No masz wymiary: pamięć, moc obliczeniowa, złożoność algorytmu, konieczność dostępu do danych na dysku. Tu raczej nie ma jakiś większych kosztów (coś kosztem czegoś) bo lista i tak jest kiepska jeśli chodzi o gospodarkę w cache. Wg. mojej oceny, jak kolega pisał, zrób wg. wygody.

0

Elegancko, postaram się ją uprościć. Spytałbym jeszcze o zwracanie dwóch głów, zakładając, że skorzystamy z podziału listy. Poprawniej byłoby skorzystać z void bez zwracania, która po prostu utworzy nam listy w miejsce dwóch pustych początkowo wskaźników, czy stworzyć funkcję typu mode zwracającą nam dwa elementy? (osobna sprawa, czy to jest w ogóle możliwe).

1

A masz powód aby je zwracać? Tj. coś będziesz z nimi robił wariantowo czy zawsze to samo (bo nie wiem gdzie jest ostateczny cel Twojej implementacji... jakieś predykaty będą)? Wtedy albo zwróć pair albo tuple (c++11). A jeśli nie to funkcja z void i tyle :-)
No i przemyślał bym jeszcze implementację. Naprawdę nie wszędzie potrzebny wskaźnik. Lepiej referencją a tam gdzie masz mieć NULL (a jeszcze lepiej nullptr z c++11) to owszem wskaźnik..

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