2017-08-24 63 views
0

我正在做一些有关链接列表的练习,并且遇到了这个问题:我需要编写一个函数,该函数删除链接列表中素数为索引的节点。例如,如果链表是:删除链接列表中的主要索引中的节点C

6->3->5->2->7->1->NULL 

返回列表必须是:

6->2->1->NULL. 

我写功能delete(Node* list)isPrime(int n)帮助我,我需要写函数。但我不断收到分段错误。 delete(Node* list)函数和isPrime(int n)函数的工作,相信问题是在primes(Node* list)

这里是我的代码:

typedef struct Node { 
int data; 
struct Node* next; 
}Node; 

void printList(Node* list) { 
    if(list->next == NULL) { 
     printf("%d\n", list->data); 
    } 
    else { 
     printf("%d ", list->data); 
     printList(list->next); 
    } 
} 

Node* addLast(Node* list, int x) { 
    Node* head = list; 
    if(head == NULL) { 
     Node* new = (Node*) malloc(sizeof(Node)); 
     new->data = x; 
     new->next = NULL; 
     return new; 
    } 
    else { 

     while(head->next != NULL) { 
      head = head->next; 
     } 

     Node* new = (Node*) malloc(sizeof(Node)); 
     new->data = x; 
     new->next = NULL; 

     head->next = new; 
     return list; 
    } 
} 

void delete(int n, Node* head) { 
    Node* temp = head; 
    if(n == 0) { 
     head = temp->next; 
     free(temp); 
    } 
    else { 
      int i; 
      for(i = 0 ; i < (n-2); i++) { 
       temp = temp->next; 
      } 

      Node* temp1 = temp->next; 
      temp->next = temp1->next; 
      free(temp1); 
    } 
} 

bool isPrime(int n) { 
    int flag = 0; 
    if(n == 1) { 
     return false; 
    } 

    else { 
     int i; 
     for(i = 2; i < n; i++) { 
      if(n%i == 0) { 
       flag = 1; 
       break; 
      } 
     } 

     if(flag == 0) { 
      return true; 
     } 
     else { 
      return false; 
     } 
    } 
} 

Node* primes(Node* list) { 
    Node* temp = list; 
    int i = 1; 
    while(temp != NULL) { 

     if(isPrime(i)) { 
      delete(i-1, temp); 
     } 
     else { i++; } 
     temp = temp->next; 

    } 
    return list; 
} 

int main() { 
    int n, st, i; 
    scanf("%d", &n); 

    Node* head = NULL; 

    for(i = 0; i < n; i++) { 
     scanf("%d", &st); 
     head = addLast(head, st); 
    } 
    printList(head); 

    printList(primes(head)); 


    return 0; 
} 
+0

'无效删除(INT N,节点*头){...头= ...}'很可能是没有意义的;如果你删除了列表的第一个元素,那么列表的头部需要重定向到另一个元素,因此'delete'的签名应该是'void delete(int n,Node ** head)'。 –

+0

@StephanLechner。 OP正在删除素数为指数的节点。由于'1'不是素数,所以这不会成为问题。 –

+1

删除一个节点后,以下节点的数量将不再正确,因为它们将全部向前移动1. – interjay

回答

1

正如WhozCraig解释,从一开始计数,一旦你有删除一个单一的元素是没有意义的。

但是,您可以简单地迭代列表中的一个元素,一次计算从开始迭代的元素数量,并且只需删除元素(如果其索引为素数或仅跳过它)。 primes只会变成:

Node* primes(Node* list) { 
    Node* temp = list; 
    int i = 1;     // trick: we know 1 is not prime so skip it 
    while (temp->next != NULL) { // and it is easier to delete next element than current one 
     i++; 
     if (isPrime(i)) { 
      delete(1, temp);  // delete if index is prime 
     } 
     else temp = temp->next;  // else skip 
    } 
    return list;     // done with it... 
} 
+0

我建议在'IsPrime(i)'中使用DP – roottraveller