Lista dwukierunkowa

0

Witam,
Mam takie zadanko:
Dana jest lista dwukierunkowa liczb całkowitych o głowie w Head zawierająca losowe liczby. Napisz funkcję, która podzieli tę listę na dwie listy Head1 i Head2, w taki sposób, aby w pierwszej liście znalazły się liczby ujemne a w drugiej liczby dodatnie (w funkcji nie jest znana ilość elementów listy pobrana przez użytkownika w main). W main() pobrać od użytkownika ilość elementów listy (n>0) i utworzyć listę Head losując do niej klucze z przedziału <-100;100> oraz wypisać na ekran. Następnie wywołać swoją funkcję i wypisać na ekran dwie listy Head1 i Head2 (w main(), a nie w funkcji).
Póki co moje podejście do tego tematu wygląda następująco, chciałem zapytać o ewentualne poprawki, porady itp.:

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

typedef struct Node {
int key;
struct Node *next;
struct Node *prev;
} Node;

Node *createNode(int key) {
Node *newNode = (Node *) malloc(sizeof(Node));
newNode->key = key;
newNode->next = NULL;
newNode->prev = NULL;
return newNode;
}

Node *createList(int n) {
srand(time(NULL));
Node *head = createNode(rand() % 201 - 100);
Node *temp = head;
for (int i = 1; i < n; i++) {
temp->next = createNode(rand() % 201 - 100);
temp->next->prev = temp;
temp = temp->next;
}
return head;
}

void splitList(Node *head, Node **head1, Node **head2) {
*head1 = NULL;
*head2 = NULL;
Node *temp = head;
while (temp != NULL) {
if (temp->key < 0) {
if (*head1 == NULL) {
*head1 = createNode(temp->key);
} else {
Node *newNode = createNode(temp->key);
newNode->next = *head1;
(*head1)->prev = newNode;
*head1 = newNode;
}
} else {
if (*head2 == NULL) {
*head2 = createNode(temp->key);
} else {
Node *newNode = createNode(temp->key);
newNode->next = *head2;
(*head2)->prev = newNode;
*head2 = newNode;
}
}
temp = temp->next;
}
}

void printList(Node *head) {
Node *temp = head;
while (temp != NULL) {
printf("%d ", temp->key);
temp = temp->next;
}
printf("\n");
}

int main() {
int n;
printf("Wpisz liczbę elementów tablicy: ");
scanf("%d", &n);
Node *head = createList(n);
printf("Oryginalna lista: ");
printList(head);
Node *head1, *head2;
splitList(head, &head1, &head2);
printf("Lista z elementami ujemnymi: ");
printList(head1);
printf("Lista z elementami dodatnimi: ");
printList(head2);
return 0;
}

Z góry dziękuję za pomoc!

0

Podstawowy błąd: - Nie masz obiektu reprezentującego listę, tylko obiekty reprezentujące węzły.
http://forum.4programmers.net/1221015
Tak a propos, po ch..ińskiego ci tu lista dwukierunkowa?

0

a prowadzacy tak zarzadzil :DD

0

Wsadzenie na siłę niepasujących konstrukcji to jest autodydaktyczne, przecież nawet nie zauważysz że skopałeś drugi kierunek!

0

int main() {
a powinno być int main( void );

Node *newNode = (Node *) malloc(sizeof(Node));
Piszemy bez (Node *);
Nie sprawdzasz błędu na malloc.
sizeof *newNode <- jeszcze łądniej ;-)

srand wystarczy wezwać jeden raz.. Np. na starcie main.

for (int i = 1; i < n; i++) {
temp->next = createNode(rand() % 201 - 100);
temp->next->prev = temp;
temp = temp->next;
}

czytelniej:

for (int i = 1; i < n; i++) {
  temp->next = createNode(rand() % 201 - 100);
  temp->next->prev = temp;
  temp = temp->next;
}

Tutaj:

void printList(Node *head) {
Node *temp = head;
while (temp != NULL) {
printf("%d ", temp->key);
temp = temp->next;
}
printf("\n");
}

*head jest kopią, możesz sobie go do woli zmieniać i nie naruszy przekazanego w mainie/

void printList( Node *head ) {
  
  while ( head != NULL) {

    printf("%d ", head->key);
    head = head->next;
  }

  printf("\n");

}

Nie sprawdzam czy to się kompiluje ale z grubsza to pewnie miało być to:

void splitList(Node *head, Node **head1, Node **head2) {

  *head1 = NULL;
  *head2 = NULL;
  Node *temp = head;
  Node *hp, *hp1 = NULL. *hp2 = NULL;
  while ( temp != NULL ) {

    hp = createNode( temp->key );

    if( temp->key < 0 )  {

      if( *head1 == NULL )  *head1 = hp;
      hp->prev = hp1;
      if( hp1 != NULL )  hp1->next = hp;
      hp1 = hp;

    }  else  {

      if( *head2 == NULL )  *head2 = hp;
      hp->prev = hp2;
      if( hp2 != NULL )  hp2->next = hp;
      hp2 = hp;
      
    }

    temp = temp->next;

  }
    
}

Nie czyścisz pamięci ( free )

0

Ja bym Ci dał inne zadanie. Utworzyć właśnie taką listę jak ta, tylko zamiast liczb losowych kazał operować na takiej strukturze:

struct osoba{
             char imie[20];
             char nazwisko[30];
             char wiek;
             osoba *nast;
             osoba *poprz;
             };

I poprosił o dodanie sortowania uwzględniając różne kryteria, dodawanie - usuwanie - edycja elementów.

Tak na rozgrzewkę.

Mógłbyś mi podziękować, że nie każę robić zapisu/odczytu z/ do pliku
(ale żadnego całowania po rękach, nie lubie kontaktu fizycznego z innymi facetami).

Teraz rozumiesz, jak dobrym jestem człowiekiem?

1
johnny_Be_good napisał(a):

Ja bym Ci dał inne zadanie. Utworzyć właśnie taką listę jak ta, tylko zamiast liczb losowych kazał operować na takiej strukturze:

struct osoba{
             char imie[20];
             char nazwisko[30];
             char wiek;
             osoba *nast;
             osoba *poprz;
             };

I poprosił o dodanie sortowania uwzględniając różne kryteria, dodawanie - usuwanie - edycja elementów.

Tak na rozgrzęwkę.

Bezsensowne zadanie na bezsensownej strukturze.
Jak już wspomniałem wcześniej w tym wątku: - Nie masz obiektu reprezentującego listę, tylko obiekty reprezentujące węzły.
Sortowanie listy jest mało sensownym zabiegiem bo ma koszt O(N*N) natomiast przekopiowanie do wektora, posortowanie, przekopiowanie z powrotem do listy ma koszt O(N*log(N)) czyli dla miliona elementów - różnica 1000-krotna.
Trzymanie nadmiarowych bajtów w strukturze to poziom sprzed listami, więc znowu się zbłaźniłeś, ma być char *name,*surname;
To do poczytania: http://forum.4programmers.net/1208091
Więc wszystko co zaproponowałeś ponad to co jest już w pod podanym przeze mnie linkiem jest zwycięstwem technologii nad zdrowym rozsądkiem.
Ach zapomniałem nie masz pojęcia co to takiego ten zdrowy rozsądek ...
Czy umówić cię na spotkanie z dwoma innymi ojcami Luka?

0

A mam pytanie , nie mógłbyś w tym małym czymś

Node *createNode(int key) {//...
//...
temp->next = createNode(rand() % 201 - 100);

przekazywać od razu węzła poprzedniego w parametrze funkcji? (head masz chyba od razu i cały czas, więc nawet z rozpoczęciem byś nie miał problemu)

Node *createNode(Node *poprzedni, int key) {//...

// przy pierwszym  elemencie byś miał

head->next = createNode(head, rand() % 201 - 100);

?

0
johnny_Be_good napisał(a):

A mam pytanie ...
... przekazywać od razu węzła poprzedniego w parametrze funkcji? (head masz chyba od razu i cały czas)

Warto też następny przekazać, do listy dwukierunkowej dodaje się nie tylko na koniec na początek również.

0
_13th_Dragon napisał(a):
johnny_Be_good napisał(a):

A mam pytanie ...
... przekazywać od razu węzła poprzedniego w parametrze funkcji? (head masz chyba od razu i cały czas)

Warto też następny przekazać, do listy dwukierunkowej dodaje się nie tylko na koniec na początek również.

Przy tworzeniu listy?
Wydawało mi się, że zawsze następny to będzie NULL.
A jak już wszystkie zostaną dodane to przejechanie pętlą, żeby szybko ustawić "poprzedniki".
Jak na razie chłopak tworzy listę, nic nie dodaje w trakcie, chyba, że się zapaliłeś do mojego pomysły, tak wtedy to by miało sens.

0
johnny_Be_good napisał(a):

Wydawało mi się, że zawsze następny to będzie NULL.
A jak już wszystkie zostaną dodane to przejechanie pętlą, żeby szybko ustawić "poprzedniki".
Jak na razie chłopak tworzy listę, nic nie dodaje w trakcie, chyba, że się zapaliłeś do mojego pomysły, tak wtedy to by miało sens.

Masz 100% racje, wydawało ci się, do listy można dodawać na początek.
Nie ma czegoś takiego jak: - "...jak już wszystkie zostaną dodane..." bo to się robi często iteracyjnie: - dodano, usunięto, zliczono.
Może jednak zajrzyj pod linka co podałem wyżej.

0
_13th_Dragon napisał(a):
johnny_Be_good napisał(a):

Wydawało mi się, że zawsze następny to będzie NULL.
A jak już wszystkie zostaną dodane to przejechanie pętlą, żeby szybko ustawić "poprzedniki".
Jak na razie chłopak tworzy listę, nic nie dodaje w trakcie, chyba, że się zapaliłeś do mojego pomysły, tak wtedy to by miało sens.

Masz 100% racje, wydawało ci się, do listy można dodawać na początek.
Nie ma czegoś takiego jak: - "...jak już wszystkie zostaną dodane..." bo to się robi często iteracyjnie: - dodano, usunięto, zliczono.
Może jednak zajrzyj pod linka co podałem wyżej.

Twoje prawo, zacząć i od końca i od środka, takie rzeczy proponuj ludziom którzy zaczynają się uczyć.
Ja zawsze robotę zaczynam od początku(chyba, że coś kończę).

0

Ty nie dzielisz listy na dwie, tylko tworzysz dwie dodatkowe listy. Skoro operuje się na węzłach to przypuszczam, że celem zadania jest utworzenie nowych list z istniejących węzłów.

0
void splitList(Node **head, Node **head_neg, Node **head_pos) {
	Node *node = *head;
	*head = NULL;
	while (node != NULL) {
		Node *next = node->next;
		head = node->key < 0 ? head_neg : head_pos;
		if (*head != NULL) {
			(*head)->prev = node;
		}
		node->next = *head;
		node->prev = NULL;
		*head = node;
		node = next;
	}
}

Node *head_neg = NULL;
Node *head_pos = NULL;
splitList(&head, &head_neg, &head_pos);
0
#include <time.h>
#include <stdio.h>
#include <stdlib.h>

typedef struct node
{
	int value;
	struct node *prev,*next;
} node;
 
typedef struct
{
	node *head,*tail;
} list;
 
node *makeNode(int value,node *prev,node *next)
{
	node *tmp=(node*)malloc(sizeof(node));
	tmp->value=value;
	tmp->next=next;
	tmp->prev=prev;
	return tmp;
}
 
void addTail(list *lst,int value)
{
	node *tmp=makeNode(value,lst->tail,NULL);
	if(lst->tail) lst->tail->next=tmp;
	else lst->head=tmp;	
	lst->tail=tmp;
}
 
void addHead(list *lst,int value)
{
	node *tmp=makeNode(value,NULL,lst->head);
	if(lst->head) lst->head->prev=tmp;
	else lst->tail=tmp;
	lst->head=tmp;
}

void removeNode(list *lst,node *fnd)
{
	if(fnd)
	  {
		if(fnd->prev) fnd->prev->next=fnd->next;
		else lst->head=fnd->next;
		if(fnd->next) fnd->next->prev=fnd->prev;
		else lst->tail=fnd->prev;
		free(fnd);
	  }
}

void clean(list *lst)
{
	while(lst->head)
	{
		lst->tail=lst->head;
		lst->head=lst->head->next;
		free(lst->tail);
	}
	lst->tail=NULL;
}
 
void showHead(const char *msg,list *lst)
{
	node *i;
	printf("%s = { ",msg);
	for(i=lst->head;i;i=i->next) printf("%d ",i->value);
	printf("}\n");
}
 
void showTail(const char *msg,list *lst)
{
	node *i;
	printf("%s = { ",msg);
	for(i=lst->tail;i;i=i->prev) printf("%d ",i->value);
	printf("}\n");
}

void addTailRand(list *lst,size_t n,int min,int max)
{
	while(n--) addTail(lst,rand()%(max-min+1)+min);
}

typedef int cond(int value);
int isNegative(int value) { return value<0; }
int isPositive(int value) { return value>0; }

void copyIf(list *dst,cond *is,list *src)
{
	node *i;
	for(i=src->head;i;i=i->next) if(is(i->value)) addTail(dst,i->value);
}

void moveIf(list *dst,cond *is,list *src)
{
	node *i,*next=NULL;
	for(i=src->head;i;i=next)
	{
		next=i->next;
		if(is(i->value))
		{
			addTail(dst,i->value);
			removeNode(src,i);
		}
	}
}

void copyBy(list *dst1,cond *is1,list *dst2,cond *is2,list *src)
{
	copyIf(dst1,is1,src);
	copyIf(dst2,is2,src);
}

void moveBy(list *dst1,cond *is1,list *dst2,cond *is2,list *src)
{
	moveIf(dst1,is1,src);
	moveIf(dst2,is2,src);
}

int main()
{
	//srand(time(0));
	srand(318); // 2 zeros
	int i;
	list lst={NULL,NULL};
	showHead("lst",&lst);
	for(i=0;i<5;++i) addTail(&lst,i);
	showHead("lst",&lst);
	for(i=1;i<5;++i) addHead(&lst,-i);
	showHead("lst",&lst);
	showTail("lst",&lst);
	clean(&lst);
	addTailRand(&lst,20,-100,100);
	showHead("lst",&lst);
	list lst1={NULL,NULL},lst2={NULL,NULL};
	copyBy(&lst1,&isNegative,&lst2,&isPositive,&lst);
	showHead("lst1",&lst1);
	showHead("lst2",&lst2);
	clean(&lst1);
	clean(&lst2);
	moveBy(&lst1,&isNegative,&lst2,&isPositive,&lst);
	showHead("lst",&lst);
	showHead("lst1",&lst1);
	showHead("lst2",&lst2);	
	clean(&lst1);
	clean(&lst2);
	clean(&lst);
	return 0;
}
0

Daj 2 heady, jeden do dodatnich a drugi do ujemnych. To chyba ma sens.

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