Podział listy dwukierunkowej na cztery mniejsze

0

Cześć,mam do napisania program który wczytuje z pliku do listy dynamicznej dwukierunkowej trochę rekordów gdzie 1 rekord to
numer pomiaru,numer czujnika wykonującego pomiar(ich jest 4),data i czas,temperatura. A następnie dzieli te listę źródłową na cztery mniejsze(1 czujnik=1lista) po przez wyjmowanie elementu z listy głównej i dodawaniu go do jeden z pozostałych 4 list. I tu mam problem z funkcja podziel_liste() bo z tego co zaobserwowałem to wykonuje sie tylko 4 razy,czyli pewnie działa tylko alokacja głów każdej z listy a dalej już nie :/ Elementy dodaje na koniec listy. Bede bardzo wdzięczny za jakieś tipy :)

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

struct pomiar {
	unsigned int nr_pomiaru;
	unsigned int nr_czujnika;
	char data_i_czas[20];
	double temp;
	struct pomiar *nast;
	struct pomiar *poprz;
}*glowa = NULL, *glowa1 = NULL, *glowa2 = NULL, *glowa3 = NULL, *glowa4 = NULL;

struct pomiar* nowy_el(int nr_pom, int nr_czuj, char *data, double temp);
void umiesc(int nr_pom, int nr_czuj, char *data, double temp);
void wypisz_liste();
void podziel_liste();


int main()
{
	unsigned int nr_pomiaru;
	unsigned int nr_czujnika;
	char data_i_czas[20];
	double temp;
	char nazwa_pliku[20];
	printf("Podaj nazwe pliku z danymi:\n");
	scanf("%s", nazwa_pliku);
	strcat(nazwa_pliku, ".txt");

	FILE *plik;
	if ((plik = fopen(nazwa_pliku, "r")) == NULL)
	{
		printf("Nie otwarto pliku");
		exit(0);
	}
	else
		printf("Otwarto plik\n");

	while (!feof(plik))
	{	
		fscanf(plik, "%d %d %s %lf", &nr_pomiaru, &nr_czujnika, data_i_czas, &temp);
		umiesc(nr_pomiaru, nr_czujnika, data_i_czas,temp);
	}
	fclose(plik);
	
    wypisz_liste();

	podziel_list();
	
	return 0;
}

struct pomiar* nowy_el(int nr_pom, int nr_czuj, char *data, double temp)
{
	struct pomiar *nowy = malloc(sizeof(struct pomiar));
	nowy->nr_pomiaru = nr_pom;
	nowy->nr_czujnika = nr_czuj;
	strcpy(nowy->data_i_czas, data);
	nowy->temp = temp;
	nowy->poprz = NULL;
	nowy->nast = NULL;

	return nowy;
}

void umiesc(int nr_pom, int nr_czuj, char *data, double temp)
{
	struct pomiar *tmp = glowa;
	struct pomiar *nowy = nowy_el(nr_pom, nr_czuj, data, temp);
	if (glowa == NULL)
	{
		glowa = nowy;
		return;
	}
	while (tmp->nast != NULL) tmp = tmp->nast;
	tmp->nast = nowy;
	nowy->poprz = tmp;
}

void podziel_liste()
{
	struct pomiar *tmp = glowa;
	int lista1=0, lista2=0, lista3=0, lista4 = 0;
	struct pomiar *tmp1=glowa1, *tmp2=glowa2, *tmp3=glowa3, *tmp4=glowa4;

	while (tmp != NULL)
	{
		if (tmp->nr_czujnika == 1)
		{
			if (glowa1 == NULL)
			{
				glowa1=tmp1 = tmp;
				lista1++;
			}
			else
			{
				while (tmp1->nast != NULL) tmp1 = tmp1->nast;
				tmp1->nast = tmp;
				tmp->poprz = tmp1;
				lista1++;
			}
		}
		if (tmp->nr_czujnika == 2)
		{
			if (glowa2 == NULL)
			{
				glowa2 =tmp2= tmp;
				lista2++;
			}
			else
			{
				while (tmp2->nast != NULL) tmp2 = tmp2->nast;
				tmp2->nast = tmp;
				tmp->poprz = tmp2;
				lista2++;

			}
		}
		if (tmp->nr_czujnika == 3)
		{
			if (glowa3 == NULL)
			{
				glowa3 =tmp3= tmp;
				lista3++;
			}
			else
			{
				while (tmp3->nast != NULL) tmp3 = tmp3->nast;
				tmp3->nast = tmp;
				tmp->poprz = tmp3;
				lista3++;
			}
		}
		if (tmp->nr_czujnika == 4)
		{
			if (glowa4 == NULL)
			{
				glowa4 =tmp4= tmp;
				lista4++;
			}
			else
			{
				while (tmp4->nast != NULL) tmp4 = tmp4->nast;
				tmp4->nast = tmp;
				tmp->poprz = tmp4;
				lista4++;
			}
		}
		tmp = tmp->nast;
	}
	
	printf("Liczba elementow w liscie 1:%d",lista1);
	printf("Liczba elementow w liscie 2:%d",lista2);
	printf("Liczba elementow w liscie 3:%d",lista3);
	printf("Liczba elementow w liscie 4:%d",lista4);
}


void wypisz_liste()
{
	struct pomiar *tmp = glowa;
	printf("1 element listy: %d %d %s %0.1lf\n", tmp->nr_pomiaru, tmp->nr_czujnika, tmp->data_i_czas, tmp->temp);
	while (tmp->nast != NULL)
	{
		tmp = tmp->nast;
	}
	printf("Ostatni element listy: %d %d %s %0.1lf\n", tmp->nr_pomiaru, tmp->nr_czujnika, tmp->data_i_czas, tmp->temp);	
}
0

Funkcja dzielenia listy jest strasznie długa, choć podział listy na mniejsze części jest dość prostą operacją. Poza tym ułatwiłbyś sobie życie, gdybyś użył tablicy czterech wskaźników zamiast czterech osobnych zmiennych – nie musiałbyś produkować drabinek ifów.

Podstawowe pytanie – chcesz główną listę podzielić na cztery mniejsze fragmenty, czy skopiować dane z głównej listy do czterech mniejszych, zachowując oryginalną?

0

Chodzi o to żeby lista główna była pusta po podzieleniu jej na 4.

0

Jeszcze kilka ważnych pytań:

  • Czy lista źródłowa zawsze zawiera dane z czterech czujników, co najmniej po jednym odczycie z każdego?
  • Czy dane w liście są zawsze posortowane względem numerów czujników? Chodzi o to, czy najpierw w liście są węzły z danymi najpierw pierwszego czunika, następnie drugiego, trzeciego i czwartego na końcu?
0

Przykladowe 15 pierwszych rekordów(jest ich okolo 30tys)

1	1	2018-02-10.17:20:22	25
2	2	2018-02-10.17:20:27	24.44
3	3	2018-02-10.17:20:30	25.56
4	4	2018-02-10.17:20:36	24.06
5	1	2018-02-10.17:25:13	25.31
6	2	2018-02-10.17:25:16	25.37
7	3	2018-02-10.17:25:20	25.37
8	4	2018-02-10.17:25:26	24.69
9	1	2018-02-10.17:30:04	24.5
10	2	2018-02-10.17:30:04	24.5
11	3	2018-02-10.17:30:12	23.19
12	4	2018-02-10.17:30:16	23.56
13	2	2018-02-10.17:34:50	20.19
14	1	2018-02-10.17:34:51	20.25
15	3	2018-02-10.17:34:58	15.81

1

O kurka… wszystkie je ładujesz do pamięci?

W sumie najprostszym rozwiązaniem w tym przypadku jest przenoszenie węzłów jeden po drugim, skoro lista nie jest posortowana i może czegoś nie zawierać. Aby samo przenoszenie było efektywne, dla każdej sublisty potrzebujesz wskaźnika na głowę i na ogon. Na głowę zawsze się trzyma wskazanie (oczywiście jeśli jest wymagane – w przypadku listy dwukierunkowej niekoniecznie, bo istnieje możliwość przeiterowania od ogona do głowy), a na ogon potrzebne jest do szybkiego dodania nowego węzła do listy. Pary wskaźników na te cztery sublisty opakuj w macierz, tak abyś mógł na podstawie liczbowego indeksu pobrać wskaźnik na konkretną sublistę.

To co jeszcze potrzebujesz to metoda wstawiająca węzeł do sublisty. Całą operację można przeprowadzić na podstawie źródłowego węzła – on zawiera numer czujnika, który również określa numer sublisty. Możesz przekazać do tej funkcji wyłącznie sam węzeł źródłowy, a możesz też dodatkowo przekazać wskaźnik na konkretną sublistę (jak wolisz).

W pseudokodzie główna pętla wygląda tak:

  • w pętli od pierwszego węzła głównej listy do ostatniego:
    • odczytaj numer czujnika (określi indeks sublisty),
    • przekaż do funkcji dodającej wskaźnik na bieżący węzeł oraz wskaźnik na konkretną sublistę,
  • wpisz NULL do wskaźnika na główną listę (poprawnie zakańcza główną listę),
  • w pętli dla każdej sublisty:
    • jeśli głowa/ogon nie zawiera NULLa (czyli sublista nie jest pusta):
      • ustaw adres na następny węzeł w ogonie na NULL (poprawnie zakańcza sublistę).

Natomiast funkcja dodająca węzeł do sublisty tak:

  • jeśli głowa sublisty zawiera NULL:
    • wpisz do głowy węzeł z parametru,
    • wpisz do ogona węzeł z parametru,
    • ustaw w głowie wskazanie na poprzedni węzeł jako NULL,
  • w przeciwnym razie:
    • ustaw w ogonie wskazanie na następny węzeł na węzeł z parametru,
    • ustaw w węźle z parametru wskazanie na poprzedni węzeł na ogon,
    • wpisz do ogona węzeł z parametru.

To chyba wszystko – mam nadzieję, że o niczym nie zapomniałem.

0

dzieki wielkie za pomoc furious :)

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