Как исправить ошибку Сегментации связанного списка C - PullRequest
0 голосов
/ 26 января 2019

Я пытаюсь исправить эту проблему 'ошибки сегментации' в следующих кодах. Возможно, я думаю, что я не получил полную картину, поэтому я продолжаю получать ошибку сегментации поверх ошибки сегментации, Любая помощь глубокоПонимание этого вдохновит меня на разработку самоанализа.

Код должен быть простым: учитывая два списка, я хочу стереть из первого все элементы, которые появляются во втором, и мои усилия были:

typedef struct EL {
    int info;
    struct EL *next;
} ElementoLista;

typedef ElementoLista *ListaDiElementi;

void filterLists(ListaDiElementi *lista1,ListaDiElementi *lista2) {

  ListaDiElementi aux = *lista1,aus = *lista2,corr;

  while(aux != NULL) {
    if(aux->info == aus->info) {    // Erase from the first
      corr = aux;
      aux = aux->next;
      free(corr);
    }           
    else {              
      if(aus != NULL)       //Increase the second
        aus = aus->next;
      else {
        aus = *lista2;          //Restart
        aux = aux->next;
      }
    }       
  }
}

Ответы [ 2 ]

0 голосов
/ 26 января 2019

Есть несколько проблем с вашим кодом:

  • Вы получите ошибку сегмента, когда второй список короче другого, потому что вы не проверяете, если aus имеет значение NULL в первом операторе if.

  • Вы получите еще один segfault позже, если элемент в середине первого списка будет удален, поскольку предшественник удаленного элементавсе еще указывает на оригинальную, но освобожденную память.

  • Я не знаю, является ли это проблемой, но ваш алгоритм работает только для отсортированных списков, взгляните на эти двасписки, например, [1,2] и [2,1].

Чтобы помочь вам с вашим алгоритмом, нам нужно знать, как вы хотите обрабатывать дубликаты элементов и есть ли спискиотсортированы или нет.

0 голосов
/ 26 января 2019

Я ничего не думаю о порядке элемента в двух списках, решение может быть:

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

typedef struct EL {
    int info;
    struct EL *next;
} ElementoLista;

ElementoLista * make(int i, ElementoLista * n)
{
  ElementoLista * r = malloc(sizeof(ElementoLista));

  if (r == NULL) {
    /* change that code with what you want */
    puts("out of memory");
    exit(-1);
  }

  r->info = i;
  r->next = n;
  return r;
}

/* I suppose nothing about the order of the element in the two lists */
void filterLists(ElementoLista ** plista1, ElementoLista * lista2) {
  /* have to work on plista1, not on a var valuing *plista1,
     to be able to update it when a cell is removed */
  while (*plista1 != NULL) {
    ElementoLista * p;

    /* is the info present in the second list ? */
    for (p = lista2; p != NULL; p = p->next) {
      if ((*plista1)->info == p->info) {
        /* remove the cell */
        ElementoLista * rmv = *plista1;

        *plista1 = (*plista1)->next;
        free(rmv);
        break;
      }
    }

    if (p == NULL)
      /* the current cell was not removed, go to the next */
      plista1 = &(*plista1)->next;
  }
}

void pr(ElementoLista * l)
{
  putchar('{');
  while (l != NULL) {
    printf(" %d", l->info);
    l = l->next;
  }
  puts(" }");
}

int main()
{
  ElementoLista * l1 = make(1, make(2, make(3, make(4, 0))));
  ElementoLista * l2 = make(3, make(1, 0));

  pr(l1);
  filterLists(&l1, l2);
  pr(l1);

  return 0;
}

Я удалил typedef скрытый указатель, это плохая идеясделать это, потому что это мешает читателю

Как видите, бесполезно указывать адрес указателя для второго списка, потому что он не изменен

Выполнение:

{ 1 2 3 4 }
{ 2 4 }
...