2016-11-02 7 views
1

단일 링크 된 목록의 첫 번째 요소와 마지막 요소를 서로 바꾸려고합니다. 지금까지 나는 목록을 만들고 그것에 숫자를 추가하는 다음 코드를 가지고있다. 내 문제는 swapElements1 함수입니다.C - 단일 링크 된 목록의 첫 번째 요소와 마지막 요소 교환

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

struct node 
{ 
    int number; 
    struct node *next; 
}; 

void addNodeSingle(struct node **head, int num, int thesi) //Function to insert new node at the beginning or the end of the list, depending on the value of "thesi" 
{ 
    if (*head == NULL) 
    { 
     struct node *current; 
     current = (struct node*) malloc (1*sizeof(struct node)); 
     current -> number = num; 
     current -> next = NULL; 
     *head = current; 
    } 

    else 
    { 
     if (thesi == 0) 
     { 
      struct node *current; 
      current = (struct node*) malloc (1*sizeof(struct node)); 
      current -> number = num; 
      current -> next = *head; 
      *head = current; 
     } 

     else 
     { 
      struct node *current, *temp; 
      current = (struct node*) malloc (1*sizeof(struct node)); 
      current -> number = num; 
      temp = *head; 
      while (temp -> next != NULL) 
       temp = temp -> next; 

      temp -> next = current; 
      current -> next = NULL; 
     } 
    } 
} 

void displayList(struct node **head) //Function to display the list 
{ 
    struct node *current; 
    if(*head == NULL) 
     printf("I lista einai adeia!\n"); 

    else 
    { 
    current= *head ; 
     while(current != NULL) 
     { 
      printf("%d ",current -> number); 
      current = current -> next; 
     } 
    } 
} 

void swapElements1(struct node **head) //(not working)Function to swap first and last element of the list 
{ 
    struct node *current, *temp; 
    current = temp = *head; 

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

    *head = (*head)->next; 
    *head = temp; 
    current = NULL; 
} 

int main() 
{ 
    struct node *head; 
    head = NULL; 

    addNodeSingle(&head,5,1); 
    addNodeSingle(&head,6,1); 
    addNodeSingle(&head,2,0); 
    addNodeSingle(&head,7,0); 
    addNodeSingle(&head,8,0); 

    printf("List is: "); 
    displayList(&head); 
    swapElements1(&head); 
    printf("\nNew list is: "); 
    displayList(&head); 
} 

내가 얻을 출력은 다음과 같습니다

목록은 다음과 같습니다 8 7 2 5 6

새 목록은 다음과 같습니다 6

내가이 필요한 것 :

목록은 다음과 같습니다 8 7 2 5 6

새 목록 : 6 7 2 5 8

,

여기이 분명히 잘못이다 demo

+4

머리글, 첫 번째 항목의 다음 포인터, 두 번째 - 마지막 항목의 다음 포인터 및 마지막 항목의 다음 포인터는 업데이트 할 수있는 포인터가 4 개 있습니다. – user3386109

+2

노드 대신 데이터의 직선 스와핑을 고려 했습니까? 아니면 이것을 필요로하는 학교 운동입니까? –

+0

@WeatherVane 불행히도, 나는 노드뿐만 아니라 데이터를 교환하고 싶습니다. – user3120283

답변

4

입니다 : 단지 temp의 값이 이전 값을 덮어 씁니다

*head = (*head)->next; 
*head = temp; 

합니다. 첫 번째 문장은 거기에있을 수도 있습니다.

당신은 근본적으로

  • 두 개의 노드를 두 노드에 next 포인터
  • 이 ISN의 후자를 가리키는 두 개의 스왑 (기술적 과제 더한 및 종료)

    • 포인터가 필요합니다 기술적으로는 필요하지 않지만 직접 할당 이고 새 꼬리에는 next이 있어야 새 목록이 종료됩니다.

      전체 예제가 아래에 표시되어 있으며, 진행중인 알고리즘을 공개하기 위해 자유롭게 댓글을 달았습니다.

      #include <stdio.h> 
      #include <stdlib.h> 
      
      struct node 
      { 
          int data; 
          struct node *next; 
      }; 
      
      void swapFirstAndLast(struct node **head) 
      { 
          // don't bother unless we have a list of at least two nodes 
          if (!*head || !(*head)->next) 
           return; 
      
          // start with the head's next pointer (the second node in the list) 
          struct node **pp = &(*head)->next; 
      
          // walk the pointer-to-pointer down the list, each time grasping 
          // the next node's "next" pointer address until we reach a node 
          // whose 'next' is NULL. When that happens, `pp` will hold the 
          // address of the pointer pointing to the last node in the list 
          while (*pp && (*pp)->next) 
           pp = &(*pp)->next; 
      
          // swap the pointer held in *head with *pp 
          struct node *tmp = *head; 
          *head = *pp; 
          *pp = tmp; 
      
          // save new head's next pointer to be the old head's next 
          (*head)->next = (*pp)->next; 
      
          // and finally, terminate the list. 
          (*pp)->next = NULL; 
      } 
      
      void print_list(const struct node *head) 
      { 
          while (head) 
          { 
           printf("%d ", head->data); 
           head = head->next; 
          } 
          fputc('\n', stdout); 
      } 
      
      int main() 
      { 
          struct node *head = NULL, **pp = &head; 
          for (int i=1; i<=5; ++i) 
          { 
           *pp = malloc(sizeof **pp); 
           (*pp)->data = i; 
           pp = &(*pp)->next; 
          } 
          *pp = NULL; 
      
          print_list(head); 
      
          swapFirstAndLast(&head); 
      
          print_list(head); 
      } 
      

      내가 당신을 위해 목록 정리를 왼쪽으로 한

      1 2 3 4 5 
      5 2 3 4 1 
      

      출력 (당신이 그런 알고리즘이 이미 코딩이 의심의 여지). 이 핵심은 포인터에 포인터를 사용하여 연결된 목록의 포인터를 조작하는 방법입니다. 임시 포인터 만이 아닙니다. 디버거에서 교환 기능을 단계별로 실행하여 각 단계에서 어떤 일이 일어나고 있는지 살펴 보는 것이 좋습니다.

    +0

    흠, 코드가 작동하고 내 문제를 해결합니다. 그러나 나는 당신이 정확히 무엇을하는지 이해하지 못합니다. 더 자세히 설명해 주시겠습니까? 왜냐하면 나는 이중 연결된 목록과 순환 연결된 목록에서 동일한 작업을 수행해야하기 때문입니다. – user3120283

    +0

    솔직히 말해서, 나는 할 수 없다. 나는 코드 주석과 게시물에 작은 소설을 썼다. 그 사이에 내가 포스트의 마지막 문장에서 설명한 것을 수행하고 (디버거에서 한 단계 씩 진행하고 변수를 검사하여 정확히 무슨 일이 일어나는지), 알고리즘을 이해할만큼 충분해야합니다. 그렇지 않다면, 포인터에 익숙해 져야하고 코드에서 볼 수 있듯이 포인터에 대한 포인터가 있어야합니다. – WhozCraig

    +0

    그리고 그 기능의 시간 복잡도는 얼마입니까? 이중 연결된 목록과 순환 연결된 목록과 동일합니까? – user3120283

    1

    WhozCraig의 답변은 이미 완벽하지만 일부 조정을 통해 자신의 코드를 볼 수도 있습니다. 기본적으로, 내가 한 일은 마지막 요소 반복을위한 검색을 일찍 멈추고, 임시 직원은 5시에 현재 6시에 끝날 것입니다. 또한 WhozCraig와 같은 포인터를 사용하여 네 가지 변경 작업을 수행해야합니다. 여기에 약간 수정 된 코드입니다 :

    void swapElements1(struct node **head) //(not working)Function to swap first and last element of the list 
    { 
        struct node *current, *temp; 
        current = temp = *head; 
    
        while(current->next != NULL) 
        { 
         temp = current; 
         current = current -> next; 
        } 
        temp->next = *head; 
        current->next = (*head)->next; 
        (*head)->next = NULL; 
        *head = current; 
    } 
    

    내 컴퓨터에서 일했다. while 루프 상태를 current에서 current-> 다음으로 변경하고 올바른 "포인터 변경"을 수행했습니다. 이 포인터 변경은 설명하기 어렵습니다. 보통 종이로 작성한 다음 코드로 작성합니다.

    +0

    위의 내용을 시각적으로 보여줄 수 있습니까? 그것은 매우 도움이 될 것입니다. 이제 이중 연결된 목록과 순환 연결된 목록에 대해 동일한 작업을 수행하려고하지만 지금까지 성공하지 못했습니다. [This] (http://ideone.com/aVnwEu)는 이중 연결리스트를 얻었지만 오류가납니다. – user3120283

    +0

    안녕하세요! 자, 이제 각 명령을 시각적으로 표현했습니다. 다음은 [link] (https://postimg.org/image/3x5mnpswz/)입니다. –

    +0

    흠, 시각적 인 프리젠 테이션은 실제로 도움이되지만, 이중 연결된 목록 또는 순환 연결된 목록을 사용하여 동일한 작업을 수행하는 방법을 여전히 파악할 수 없습니다. 도울 수 있니? [이] (http://ideone.com/00gEGb) 내가 가진 것입니다. – user3120283