我正在尝试删除链接列表中的某个元素。
当我在屏幕上打印所有元素时,它们都有一定的顺序(参见案例2)。在案例7中,我可以根据该订单选择要删除的元素。
案例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;
}
答案 0 :(得分:2)
您当前的算法已完全破解。
简而言之,这需要完成。
有很多方法可以做到这一点,许多方法使用至少一对指针(一个prev和一个当前)并将它们推向列表,这似乎是你尝试过的,以及几个答案正在尝试解决的问题。与众不同,我将向您展示如何使用单个指针指针来完成此操作。这样做的另一个好处就是不需要特殊情况的头指针检查。
包括基本错误检查,它是这样完成的:
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))。这允许我们将指针更新为其后继地址,然后删除节点并完成。
当涉及单链表操作时,指针指针算法通常提供令人惊讶的优雅解决方案和通常简洁的代码。盯着它看一段时间,或许可以将它与不同的两个/三个指针方法进行比较。
祝你好运。
答案 1 :(得分:0)
您的删除逻辑不正确;
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;
}
答案 2 :(得分:0)
删除项目时,应正确重新链接列表。并且也不要尝试从已删除的元素(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;