首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在C中删除链表中的某个元素

如何在C中删除链表中的某个元素
EN

Stack Overflow用户
提问于 2014-12-30 15:31:16
回答 3查看 121关注 0票数 0

我正在尝试删除链表中的某个元素。

当我在屏幕上打印所有元素时,它们都有一定的顺序(参见案例2)。在case 7中,我可以根据顺序选择要删除的元素。

case 7中的代码不起作用。下面是我的代码:

代码语言:javascript
复制
#include "stdio.h"
#include "ctype.h"
#include "stdlib.h"
#include "math.h"
#include "string.h"
#define SIZE 100
double dummy = sin(0.0);

struct sputnik {
  char nazvanie[30];
  char nazvanie_main[30];

  int year;
  float d;
  int period;
  struct sputnik *next;
};

int main(void) {
  char choice;
  int punkt;
  int i, count = 0;
  struct sputnik *head = NULL;
  struct sputnik *prev, *current;
  int res, kolvo, j, number;
  struct sputnik a[SIZE];
  system("clear");

  while (1) {
    printf("Menu: ");
    printf("1- Create table with sputniks  \n 2-All sputniks \n 3-Write      4-Read \n 5-Add \n 6-Change \n 7-Delete \n 8-Exit \n");
    scanf("%d", &punkt);

    while (getchar()!='\n') 
      continue;

    switch(punkt) {
      case 1:
        while (1) {
          printf("Create new table? (N-new; O-old)");
          choice = toupper(getchar());
          if (choice == 'N') {
            count = 0;
            prev = head;
            while (prev != NULL) {
              current = prev->next;
              free(prev);
              prev = current;
            }
            head = NULL;
          }
          if (choice != 'N' && choice != 'O') {
            while (getchar() != '\n')
              continue;
            continue;
          }
          while (getchar()!='\n')
            continue;
          break;
        }
        for ( ; ; count++) {
          current = (struct sputnik *)malloc(sizeof(struct sputnik));
          if (head == NULL) {
            head = current;
          } else {
            prev->next = current;
          }
          current->next = NULL;
          printf("Name %d sputnika:", count + 1);
          gets(current->nazvanie);
          printf("Name planet:");
          gets(current->nazvanie_main);
          printf("Open year:");
          scanf("%d", &current->year);
          while (getchar() != '\n')
            continue;
          printf("Diameter:");
          scanf("%f", &current->d);
          while (getchar() != '\n')
            continue;
          printf("Period:");
          scanf("%d", &current->period);
          while (getchar() != '\n')
            continue;
          prev = current;
          printf("Finish vvod?: y/n: \n");
          if (toupper(getchar()) == 'Y') {
            count++;
            break;
          } else {
            while (getchar() != '\n')
              continue;
            continue;
          };
        }
        break;
      case 2:
        if (head == NULL) {
          printf ("No data \n");
        } else {
          printf(" Sputniks: \n");
        }
        current = head;
        i = 0;
        while (current != NULL) {
          printf("%d sputnik - %s planet %s god %d diametr %4.3f period %d\n", ++i, current->nazvanie, current->nazvanie_main, current->year, current->d, current->period);
          current = current->next;
        }
        break;
      case 3:
        break;
      case 4:
        break;
      case 5:
        break;
      case 6:
        break;
      case 7:
        int nummer;
        printf("Number for sputnik to delete:\n");
        scanf("%d", &nummer);
        while (getchar() != '\n')
          continue;
        current = head;
        i = 0;
        while (current != NULL) {
          if (i == nummer - 1) {
            prev = current;
            free(current);
            current = prev->next;
          } else {
            current = current->next;
            i = i + 1;
          }
        }
        break;
      case 8:
        prev = head;
        while (prev != NULL) {
          current = prev->next;
          free(prev);
          prev = current;
        }
        printf("Finish \n");
        return 0;
        break;
      default:
        printf ("Dont right choose!\n");
        break;
    }
  } 
  return 0; 
}
EN

回答 3

Stack Overflow用户

发布于 2014-12-30 17:33:15

你当前的算法已经完全崩溃了。

使用one following.

  • Your算法,您永远不会链接已删除节点之前的节点。
  • 根本不会考虑删除头节点。
  • 即使在删除目标之后,您也不需要遍历列表的其余部分。

简而言之,这需要重新做一遍。

有许多方法可以做到这一点,其中许多方法至少使用一对指针( prev和current),并在列表中向下移动它们,这似乎是您尝试过的,也是几个答案试图解决的问题。不同的是,我将向您展示如何使用单个指针到指针来做到这一点。这有一个额外的好处,即消除了对特殊情况下的头指针检查的需要。

包括基本的错误检查,它是这样做的:

代码语言:javascript
复制
int nummer;
printf("Number for sputnik to delete:\n");
if (scanf("%d", &nummer) == 1 && nummer > 0)
{
    struct sputnik** pp = &head;
    while (--nummer && *pp)
        pp = &(*pp)->next;;
    if (*pp)
    {
        struct sputnik *p = *pp;
        *pp = p->next;
        free(p);
    }
}
while (getchar() != '\n')
    continue;

这将遍历链表中的实际指针;而不仅仅是它们的值。因此,当我们到达指向我们想要删除的节点的指针时,我们使用列表中的指针(如果请求是针对节点(1),则包括头指针)。这允许我们更新指向其后继地址的指针,然后删除节点并完成操作。

当涉及到单链表操作时,指针到指针算法通常提供令人惊讶的优雅的解决方案和通常简洁的代码。盯着它看一段时间,也许会将它与不同的两个/三个指针方法进行比较。

祝你好运。

票数 2
EN

Stack Overflow用户

发布于 2014-12-30 15:44:39

您的删除逻辑不正确;

代码语言:javascript
复制
struct sputnik *prev = NULL, *current = NULL;
current = head;

if (number == 1) {
  head = head->next;
  free(current);
  current = NULL;
  return;
}

while (i < (number - 1)) {
  current = current->next;
  i++;
} 

prev = current;
current = current->next;

if (current->next == NULL) {
  free(current);
  current = NULL;
  prev->next = NULL;
  return;
} else {
  prev->next = current->next;
  free(current);
  current = NULL;
  return;
}
票数 0
EN

Stack Overflow用户

发布于 2014-12-30 15:46:06

在删除列表项目时,您应该正确地重新链接列表。也不要尝试从已删除的元素(prev=current;current=prev->next; free(prev);)中读取

所以你的case 7可能看起来像这样的代码:

代码语言:javascript
复制
        int nummer;
        printf(" Number for sputnik to delete:\n");
        scanf ("%d",&nummer);
        while(getchar()!='\n') continue;
        current=head; prev=NULL;
        i=0;
        while(current!=NULL) {
          if (i==nummer-1){
              if (prev==NULL) {
                // move head pointer if first element should be removed
                head=current->next;
              } else {
                prev->next = current->next; // relink list items
              }
              free(current); // free allocated memory
              break;
          }
          else 
          {
            prev=current; current=current->next; i=i+1; // go to next item
          }
        }
        break;
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/27701322

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档