链表的实现
实验要求
例6-17的节点结构(学生)和基本流程,用函数分别实现链表的创建、输出、插入、删除和修改节点数据,并在main函数中测试这些函数。基本结构可以参考ppt。
分析
流程
在主函数中,提示用户输入节点个数n,然后提示用户输入指令,并进行相应操作
代码
/**
* 例6-17的节点结构(学生)和基本流程,用函数分别实现链表的创建、输出、插入、删除和修改节点数据,
并在main函数中测试这些函数。基本结构可以参考ppt。
一律根据学号进行增删改
*/
#include <bits/stdc++.h>
using namespace std;
//学生节点
struct ListNode
{
long num;
string name;
float grade;
ListNode* next;
ListNode():num(0),name(""),grade(0),next(nullptr){}
ListNode(long num_,string name_,float grade_):num(num_),name(name_),grade(grade_),next(nullptr){}
};
//创建,创建有n个结点的链表
ListNode* create(int n){
ListNode* dummy = new ListNode;
ListNode* cur = dummy;
for(int i=0;i<n;i++){
ListNode* node = new ListNode;
cout<<"请输入学号,姓名,成绩:\n";
cin>>node->num>>node->name>>node->grade;
node->next = nullptr;
cur->next = node;
cur = cur->next;
}
std::cout << "创建成功!\n" << std::endl;
return dummy->next;
}
//输出
void printList(ListNode* head){
ListNode* cur = head;
while(cur != nullptr){
cout<<cur->num<<" "<<cur->name<<" "<< cur->grade<<endl;
cur = cur->next;
}
std::cout << "打印成功!" << std::endl;
}
//插入
//插入到学号为id的学生后面
void insert(ListNode* head,long id){
ListNode* cur = head;
ListNode* newNode = new ListNode;
newNode->next = nullptr;
cout<<"请输入要插入的学生的学号,姓名,成绩:\n";
cin>>newNode->num>>newNode->name>>newNode->grade;
while(cur->next != nullptr){ //cur将停留在最后一个结点 如果目标节点不存在,则插入在最后,如目标节点存在,也是插入在最后
if(cur->num == id){ //找到了目标节点,进行插入
ListNode* temp = cur->next;
cur->next = newNode;
newNode->next = temp;
cout<<"插入成功!\n";
return;
}
cur = cur->next;
}
cur->next = newNode;
newNode->next = nullptr;
cout<<"没有找到该学号学生,默认已插入链表尾部!\n";
}
//删除,默认假设删除的id存在
void deleteNode(ListNode* head,long id){
ListNode* dummy = new ListNode;
dummy->next = head;
ListNode* cur = dummy;
while(dummy != nullptr){
if(dummy->next->num == id){
ListNode* temp = dummy->next;
dummy->next = dummy->next->next;
delete temp;
cout<<"删除成功!\n";
return;
}
dummy = dummy->next;
}
cout<<"找不到要删除的结点!\n";
}
//修改
//根据id进行修改
void alter(ListNode* head, long id){
ListNode* cur = head;
while(cur != nullptr){
if(cur->num == id){
cout<<"请输入新的分数:\n";
cin>>cur->grade;
break;
}
cur = cur->next;
}
cout<<"修改成功!\n";
}
//释放链表
void freelist(ListNode* head){
ListNode* cur = head;
while(cur != nullptr){
ListNode* temp = cur->next;
delete cur;
cur = temp;
}
}
//基于命令行的学生链表
int main(){
int n;
cout<<"请输入创建的链表的结点个数:\n";
cin>>n;
ListNode* head = create(n);
while(true){
std::cout << "请输入命令来进行操作:1:打印链表 2:插入 3:删除 4.修改 5.退出\n";
int op;
cin>>op;
switch (op) {
case 1:
printList(head);
break;
case 2:
std::cout << "请输入学生学号(将插入到该学生后):" << std::endl;
long id;
cin>>id;
insert(head,id);
break;
case 3:
std::cout << "请输入要删除的学生学号:" << std::endl;
// long id;
cin>>id;
deleteNode(head,id);
break;
case 4:
std::cout << "请输入要修改的学生的学号:" << std::endl;
// long id;
cin>>id;
alter(head,id);
break;
case 5:
freelist(head);
std::cout << "已经成功退出!" << std::endl;
return 0;
default:
std::cout << "输入的命令有误,请重新输入!" << std::endl;
break;
}
}
return 0;
}
实验结果
创建
插入
插入的学号存在时,插入到该学生之后。
插入的学号不存在时候,插入到链表最后。
删除
修改
退出
输入错误的命令
遇到的问题
Bug:
1.在创建链表的函数中,一开始dummy = nullptr导致输入第一个学生后程序就崩溃
解决:应该改为dummy = new ListNode
2.打印链表格式输出有误,姓名和成绩之间少了空格
3.在打印完链表后程序崩溃了
原因:是因为在创建链表的过程中,新建链表后next没有指向空
解决:以后应当在结构体中写构造函数,使得next默认指向null
4.在插入成功之后死循环
可能的原因:提示语句后面加了换行符\n,又加了换行符号endl,系统把endl读入当成了换行符
但改了之后仍然有这个问题
最终解决:输入新节点的时候,写成了cin>>node->num>>node->grade>>node->grade;
应该是:cin>>node->num>>node->name>>node->grade;
总结
1.写代码之前先设计好,再写,能提高效率。
2.写代码时候注意细节,好多bug都是代码细节导致的,后面找bug花了不少时间。