循环链表

时间:2013-12-12 09:55:18

标签: c circular-list

我的圆形链表代码适用于添加,搜索,计数,查看但是一旦我删除列表中的条目,它就会与列表中的所有其他数据混淆。 我知道错误在 DeleteNode 函数中,但无法解决。 请帮帮我 - 谢谢。

#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
struct Node{
    int data;
    struct Node *next;
}*head,*temp,*curr,*prev,*p;
/*   Prototypes   */
void AddNode(int value);
int CountNode();
void SearchNode(int value);
void ViewAll();
void DeleteNode(int value);
/* Main */
int main(){
    int choice,value;
    printf("\n\n\n\t\t\tCircular Linked List\n\n\t\t\tSyed Danish Ali\n\n\t\t\tUBIT\n\n\n\t\t\t\tHit ENTER to continue...");
    while(getche() != '\r'){
    }
    do{
        system("cls");
        printf("\n\nMENU\n=====\n\n[1] ADD\n[2] COUNT\n[3] SEARCH\n[4] VIEW ALL [5] DELETE\n[6] EXIT\n\nCHOICE:\t");
        scanf("%d",&choice);
        if(choice == 1){
        printf("Enter data:\t"); scanf("%d",&value);
        AddNode(value);
        getch();
        } else if(choice == 2){
        printf("\n\n%d Node(s).",CountNode());
        getch();
        }else if(choice == 3){
        printf("Enter the data to search:\t");
        scanf("%d",&value);
        SearchNode(value);
        getch();
        } else if(choice == 4){
        ViewAll();
        getch();
        } else if(choice == 5){
        printf("Enter the data to search:\t");
        scanf("%d",&value);
        DeleteNode(value);
        getch();
        } else if(choice == 6){
            return 0;
        }

    }while(1);
}

void AddNode(int value){
    temp = (struct Node *) malloc (sizeof(struct Node));
    temp->data = value;

    if(head == NULL){
    head = temp;
    temp->next = head;
    } else {
    curr = head;
    while(curr->next != head){
        curr = curr->next;
    }
    p = curr;
    curr->next = temp;
    temp->next = head;
    }
    printf("\n\nNode added.");
}
int CountNode(){
    int k = 0;
    if(head == NULL){
    return 0;
    } else {
    curr = head;
    while(curr->next != head){
        k++;
        curr = curr->next;
    }
    return k;
    }
}
void SearchNode(int value){
    int flag = 0,k = 0;
    if (head == NULL){
    printf("\n\nList is empty.");
    } else {
    curr = head;
    while(curr->next != head){
        if (curr->data == value){
        flag = 1;
        printf("\n\n%d found at index # %d.",value,k);
        curr = curr->next;
        } else {
        curr = curr->next;
        k++;
        }
    }
    }
    if(flag == 0)
    printf("\n\nValue %d not found.",value);
}
void ViewAll(){
    int counter = 0;
    if(head == NULL)
    printf("\n\nList is empty.");
    else{
    curr = head;
    printf("LIST GENERATED:\n===============\n");
    while(curr->next != head){
        printf("\nElement # %d:\nData:\t%d",counter+1,curr->data);
        curr = curr->next;
        counter++;
    }
    }
}
void DeleteNode(int value){
    int flag = 0;
    if(head == NULL){
    printf("\n\nList is empty.");
    } else {
    curr = head;
    while(curr->next != head){
        if(curr->data == value){
        printf("\n\nValue found.");
        flag = 1;
        if(curr == head){
            curr->next = head;
            free(curr);

        } else {
            prev->next = curr->next;
            free(curr);
        }
        } else {
        prev = curr;
        curr = curr->next;
        }
    }
    printf("Node deleted.");
    }
    if(flag == 0)
    printf("\n\nValue not found.");
}

4 个答案:

答案 0 :(得分:2)

} else {
        prev->next = curr->next;  //here prev doesn't point to any memory address so
                                    we can't assign value to prev->next
        free(curr);
    }

答案 1 :(得分:0)

你有一个圆形清单。这意味着无论何时删除节点,无论是否为头,都会有前一个节点。

此代码可以缩短,也可以解决您的问题。

    if(curr == head){
        curr->next = head;
        free(curr);

    } else {
        prev->next = curr->next;
        free(curr);
    }

    prev->next = curr->next;
    if(curr == head)
         head = curr->next;
    free(curr);

您的原始代码设置了curr-&gt;紧靠头部而不是相反,从而最终进入curr-&gt;接下来指向curr(等于head)。

编辑:

但是,您还应该检查curr-&gt; next是否等于它本身,这意味着您要删除循环链接列表中的最后一个节点。

答案 2 :(得分:0)

你的代码很好,我完全看了它并发现了错误。 你只需要在释放节点后添加break。而已。 :) 在释放节点后,它再次移动并且当前为空..所以它会中断。

void DeleteNode(int value){
    int flag = 0;
    if(head == NULL){
    printf("\n\nList is empty.");
    } else {
    curr = head;
    while(curr->next != head){
        if(curr->data == value){
        printf("\n\nValue found.");
        flag = 1;
        if(curr == head){
            curr->next = head;
            free(curr);
            break;  // this is where it break

        } else {
            prev->next = curr->next;
            free(curr);
            break;  // this is where it break
        }
        } else {
        prev = curr;
        curr = curr->next;
        }
    }
    printf("Node deleted.");
    }
    if(flag == 0)
    printf("\n\nValue not found.");
}

要继续ittrating并删除具有相同值的所有节点,您可以在else语句中使用它。

else {
            prev->next = curr->next;
            free(curr);
            curr=prev; // this what you need
            break;  
        }

答案 3 :(得分:0)

很好的实施。 我发现了以下错误:

  1. 遍历列表时,忽略了头部。下面,while-loops已被替换为搜索,查看和删除功能的do-while。

  2. 如前所述,删除功能中未为prev分配有效值。

  3. 删除头部时,prev-&gt; next未更改。在这种情况下,无论如何都没有设置prev。在下面的代码中,添加了一个尾部变量。这样,prev可以在删除功能的开头设置。否则,列表也已经确定,像curr和prev这样的全局变量总是有一个有效的值。

  4. 我希望这可能有用。 干杯, 迈克尔

    修改后的代码:

    #include<stdio.h>
    #include<conio.h>
    #include<stdlib.h>
    
    struct Node
    {
      int data;
      struct Node *next;
    }*head,*temp,*curr,*prev,*tail;
    
    /*   Prototypes   */
    void AddNode(int value);
    int  CountNode();
    void SearchNode(int value);
    void ViewAll();
    void DeleteNode(int value);
    
    /* Main */
    int main()
    {
      int choice,value;
      printf("\n\n\n\t\t\tCircular Linked List\n\n\t\t\tSyed Danish Ali\n\n\t\t\tUBIT\n\n\n\t\t\t\tHit ENTER to continue...");
      while(getche() != '\r')
      {
      }
      do
      {
        system("cls");
        printf("\n\nMENU\n=====\n\n[1] ADD\n[2] COUNT\n[3] SEARCH\n[4] VIEW ALL\n[5] DELETE\n[6] EXIT\n\nCHOICE:\t");
        scanf("%d",&choice);
        if(choice == 1){
          printf("Enter data:\t"); scanf("%d",&value);
          AddNode(value);
          getch();
        } else if(choice == 2){
          printf("\n\n%d Node(s).",CountNode());
          getch();
        }else if(choice == 3){
          printf("Enter the data to search:\t");
          scanf("%d",&value);
          SearchNode(value);
          getch();
        } else if(choice == 4){
          ViewAll();
          getch();
        } else if(choice == 5){
          printf("Enter the data to search:\t");
          scanf("%d",&value);
          DeleteNode(value);
          getch();
        } else if(choice == 6){
          return 0;
        }
      } while(1);
    }
    
    void AddNode(int value)
    {
      temp = (struct Node *) malloc (sizeof(struct Node));
      temp->data = value;
    
      if(head == NULL)
      {
        head = temp;
        tail = temp;
        curr = temp;
        temp->next = head;
      } else {
        // remember prev if needed
        prev       = tail;
        prev->next = temp;
        tail       = temp;
        curr       = temp;
        temp->next = head;
      }
      // remember tail
      printf("\n\nNode added.");
      }
      int CountNode(){
      int k = 0;
      if(head == NULL){
        return 0;
      } else {
        temp = head;
        // count head, too
        do
        {
          k++;
          temp = temp->next;
        } while(temp != head);
        return k;
      }
    }
    
    void SearchNode(int value){
      int flag = 0,k = 0;
      if (head == NULL){
         printf("\n\nList is empty.");
      } else {
        curr = head;
        // search head, too
        do
        {
          if (curr->data == value){
            flag = 1;
            printf("\n\n%d found at index # %d.",value,k);
            curr = curr->next;
          } else {
            curr = curr->next;
            k++;
          }
        } while(curr != head);
      }
      if(flag == 0)
      {
        printf("\n\nValue %d not found.",value);
      }
    }
    
    void ViewAll(){
      int counter = 0;
      if(head == NULL)
      {
        printf("\n\nList is empty.");
      } else {
        curr = head;
        printf("LIST GENERATED:\n===============\n");
        // show head, too
        do
        {
          printf("\nElement # %d:\nData:\t%d",counter+1,curr->data);
          curr = curr->next;
          counter++;
        } while(curr != head);
      }
    }
    
    void DeleteNode(int value){
      int flag = 0;
      if(head == NULL)
      {
        printf("\n\nList is empty.");
      } else {
        curr = head;
        prev = tail;
        // delete head, too, if it contains the searched value
        do{
          if(curr->data == value)
          {
            printf("\n\nValue found.");
            flag = 1;
            if(curr == head)
            {
              if(tail == head)
              {
                // list contains only one element
                free(head);
                temp = NULL;
                head = NULL;
                prev = NULL;
                curr = NULL;
                tail = NULL;
              } else {
                // list contains more than one element
                temp = curr;
                free(temp);
                temp = tail; // ensure, temp is valid
                curr = head->next;
                head = curr;
                tail->next = curr;
                // prev = tail;
              }
    
            } else {
              // curr != head
              prev->next = curr->next;
              if(curr == tail){
                tail = prev; // tail may be head as well, now
              } else {
                // nothing to do ;O)
              }
              free(curr);
              curr = prev->next;
              temp = prev; // ensure, temp is valid
            }
          } else {
            // don't delete, just advance
            prev = curr;
            curr = curr->next;
          }
        } while(curr != head);
        printf("Node deleted.");
      }
      if(flag == 0)
      {
        printf("\n\nValue not found.");
      }
    }