删除中间的节点时遇到问题。如果我在中间放置一个位置所有前一个节点都将消失,任何人都可以帮助我,谢谢!
如果我删除前面的部分没有任何问题,但在中间部分会有一些问题。
我现在被困住了。
#include<iostream>
#include<string>
#include <limits>
using namespace std;
struct Student{
string name;
int matricNo;
string course;
double cgpa;
Student* link;
};
int main(){
Student *head = NULL, *last, *newStudent, *target;
int menu = 0;
int select;
while(menu != 6){
cout << "Student Database.\n";
cout << "1.Add a student.\n";
cout << "2.Delete a student.\n";
cout << "3.View a student's information.\n";
cout << "4.View all students' information.\n";
cout << "5.View all students' information with CGPA of 3.0 or higher.\n";
cout << "6.End program.\n";
while(!(cin >> menu)){
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
cout << "Invalid input.\n";
}
if(menu == 1){
newStudent = new Student;
if(head == NULL)
head = newStudent;
cin.clear();
cin.ignore(2000,'\n');
cout << "Please enter the student's name : ";
getline(cin, newStudent -> name);
cin.clear();
cout << "Please enter the Matric Number : ";
while(!(cin >> newStudent -> matricNo)){
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
cout << "Invalid input. Please enter a number.\n";
}
cin.clear();
cin.ignore(2000,'\n');
cout << "Please enter the Course : ";
getline(cin, newStudent -> course);
cin.clear();
cout << "Please enter the student's CGPA : ";
while(!(cin >> newStudent -> cgpa) || newStudent -> cgpa > 4 || newStudent -> cgpa < 0){
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
cout << "Invalid input. Please enter a value between 0.00 and 4.00\n";
}
newStudent -> link = NULL;
if(last != NULL)
last -> link = newStudent;
last = newStudent;
system("cls");
}
if(menu == 2){
if(head != NULL){
cout << "Please enter the matric number of a student : ";
while(!(cin >> select)){
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
cout << "Invalid input.\n";
}
for(Student* p = head; p != NULL; p = p -> link){
if(p -> matricNo == select){
target = p;
if(head != NULL)
head = p -> link;
target -> link = NULL;
delete target;
}
}
}
else if(head == last){
head -> link=NULL;
last -> link=NULL;
}
else
cout << "No students in the database.\n";
}
if(menu == 3){
if(head != NULL){
cout << "Please enter the matric number of a student : ";
while(!(cin >> select)){
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
cout << "Invalid input.\n";
}
for(Student* p = head; p != NULL; p = p -> link){
if(p -> matricNo == select){
cout << "Student's Name : " << p -> name << endl;
cout << "Matric Number : " << p -> matricNo << endl;
cout << "Course : " << p -> course << endl;
cout << "CGPA : " << p -> cgpa << endl;
cout << "==================================\n";
}
}
}
else
cout << "No students in the database.\n";
}
if(menu == 4){
if(head != NULL){
for(Student* p = head; p != NULL; p = p -> link){
cout << "Student's Name : " << p -> name << endl;
cout << "Matric Number : " << p -> matricNo << endl;
cout << "Course : " << p -> course << endl;
cout << "CGPA : " << p -> cgpa << endl;
cout << "==================================\n";
}
}
else
cout << "No students in the database.\n";
}
if(menu == 5){
if(head != NULL){
for(Student* p = head; p != NULL; p = p -> link){
if(p -> cgpa >=3){
cout << "Student's Name : " << p -> name << endl;
cout << "Matric Number : " << p -> matricNo << endl;
cout << "Course : " << p -> course << endl;
cout << "CGPA : " << p -> cgpa << endl;
cout << "==================================\n";
}
}
}
else
cout << "No students in the database.\n";
}
if(menu == 6)
return 0;
}
system("PAUSE");
return 0;
}
答案 0 :(得分:1)
要删除单链接列表中间的节点,首先需要在之前找到要删除的节点。那是因为您需要将其链接设置为(将要删除的)节点链接。
有点图形化,让我们说你的列表看起来像这样:
+--------+ +--------+ +--------+ ... --> | Node A | --> | Node B | --> | Node C | --> ... +--------+ +--------+ +--------+
现在假设您要删除“Node B”。要做到这一点,你必须使列表看起来像这样:
/---------------\ +--------+ | +--------+ | +--------+ ... --> | Node A | -/ | Node B | -+-> | Node C | --> ... +--------+ +--------+ +--------+
现在“节点A”没有链接到“节点B”,因此“节点B”实际上不再在列表中。 “节点A”和“节点B”都链接到“节点C”无关紧要,因为您无法访问“节点B”,也因为下一步是删除“节点B”的结构
请注意,当您要删除的节点是列表中的第一个节点时,会出现一种特殊情况。如果找不到列表中的节点,您还应该能够处理。
当然还有其他解决方案(如UKMonkey所述),例如使用标准std::list
(或单链接std::forward_list
)。所以我认为这只是为了练习链接列表的基本工作原理。
您还可以拥有一个双链表,其中每个节点不仅具有列表中下一个节点的链接,还具有前一个节点的链接。上面概述的原则是相同的。
答案 1 :(得分:0)
当涉及遍历单链表以查找和删除列表中的某个现有节点时,简单的范例转换大大简化了任务。
问题的范式转换是使用指向列表中每个节点的指针,而不是指向列表中每个节点的指针。当你这样做时,if
语句的典型笨拙森林会立即消失,并被一个非常简单,直接的算法取代:
for (Student **p=&head; *p; p=&(*p)->next)
{
if ((*p)->matricNo == select)
{
Student *node= *p;
*p=node->next;
delete node;
break;
}
}