我正在尝试删除链表中的某个元素。
当我在屏幕上打印所有元素时,它们都有一定的顺序(参见案例2)。在case 7中,我可以根据顺序选择要删除的元素。
case 7中的代码不起作用。下面是我的代码:
#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", ¤t->year);
while (getchar() != '\n')
continue;
printf("Diameter:");
scanf("%f", ¤t->d);
while (getchar() != '\n')
continue;
printf("Period:");
scanf("%d", ¤t->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;
}发布于 2014-12-30 17:33:15
你当前的算法已经完全崩溃了。
使用one following.
简而言之,这需要重新做一遍。
有许多方法可以做到这一点,其中许多方法至少使用一对指针( prev和current),并在列表中向下移动它们,这似乎是您尝试过的,也是几个答案试图解决的问题。不同的是,我将向您展示如何使用单个指针到指针来做到这一点。这有一个额外的好处,即消除了对特殊情况下的头指针检查的需要。
包括基本的错误检查,它是这样做的:
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),则包括头指针)。这允许我们更新指向其后继地址的指针,然后删除节点并完成操作。
当涉及到单链表操作时,指针到指针算法通常提供令人惊讶的优雅的解决方案和通常简洁的代码。盯着它看一段时间,也许会将它与不同的两个/三个指针方法进行比较。
祝你好运。
发布于 2014-12-30 15:44:39
您的删除逻辑不正确;
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;
}发布于 2014-12-30 15:46:06
在删除列表项目时,您应该正确地重新链接列表。也不要尝试从已删除的元素(prev=current;current=prev->next; free(prev);)中读取
所以你的case 7可能看起来像这样的代码:
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;https://stackoverflow.com/questions/27701322
复制相似问题