单链表的基本操作
单链表的基本操作
利用单链表编写简单的学生信息管理系统,加深对单链表不同操作的灵活运用
构造单链表
定义俩个结构体类型,互相嵌套
struct Student //学生
{
long long ID; //学号
char name[20]; //姓名
double score; //成绩
};
struct Class //班级(Class_and_grade)
{
struct Student S; //学生
struct Class *next; //指向下一个结构体
};
与以下代码等价
struct Class //班级(Class_and_grade)
{ //学生
long long ID; //学号
char name[20]; //姓名
double score; //成绩
struct Class *next; //指向下一个结构体
};
1.建立单链表(头节点)
void Class_Initialize( Class * & C ) //初始化单链表(调用参数)
{
C = ( Class * ) malloc ( sizeof ( Class ) ) ; //开辟内存
C ->next = NULL ; //将头指针的后继置空
}
2.输入单链表(尾插法)
void Import( struct Class * & C ) //输入(尾插法)
{
struct Class * p = NULL, * q = NULL ; //定义俩个工作指针
q = C ;
cout << "输入要录入学生个数:";
int n ;
cin >> n ;
for( int i = 0 ; i < n ; i++ )
{
p = ( Class * ) malloc ( sizeof ( Class ) ) ;
cout << "输入第" << i + 1 << "位学生的信息:"<<endl;
cout << "学号:" << endl;
cin >> p ->S.ID;
cout << "姓名:" << endl;
cin >> p ->S.name;
cout << "成绩:" << endl;
cin >> p ->S.score;
q ->next = p ;
q = p ;
q ->next = NULL ;
}
}
3.插入节点(根据位置)
void Interposition ( struct Class * & C, int location )
{
struct Class * p = C, * q = NULL ;
if ( location < 0 )
{
cout << "位置错误" << endl ;
return ;
}
for ( int i = 0 ; i < location - 1 ; i ++ )
{
p = p ->next;
if (!p)
{
cout << "位置错误" << endl;
return ;
}
}
q = ( Class * ) malloc ( sizeof ( Class ) ) ;
cout << "输入第" << location + 1 << "位学生的信息:" << endl ;
cout << "学号:" << endl;
cin >> q ->S.ID;
cout << "姓名:" << endl;
cin >> q ->S.name;
cout << "成绩:" << endl;
cin >> q ->S.score;
q ->next = p ->next;
p ->next = q;
cout << "插入成功" << endl ;
}
4.删除节点(根据元素)
void Delate ( struct Class * & C, long long ID )//删除结点
{
struct Class * p = C ->next, * q = C ;
for( ; p != NULL ; q =p,p =p ->next )
//p指针和q指针同时查找,p指向当前的学生,q保指向了上一个学生
{
if( p ->S.ID == ID )
{
q ->next = p ->next; //假设找到了需要删除的学生,让它上一个学生的指针指向跳过他的下一个学生
free ( p ) ; //释放 p 节点
cout << "删除成功" << endl ;
return ;
}
}
cout << "删除失败" << endl ;
}
5.查找节点(根据元素)
void Find ( struct Class * S, long long ID) //按元素查找
{
struct Class *p ; //定义工作指针
int i = 1 ;
for( p = S ->next ; p != NULL ; p = p ->next )
{
if (p ->S.ID == ID )
{
cout << "第" << i + 1 << "位学生:" << endl ;
cout << "姓名:" << p ->S.name << "成绩:"<< p ->S.score << endl ;
return ;
}
}
cout << "未找到该用户" << endl ;
}
6.销毁单链表(释放所有节点)
void Release ( struct Class * & C )
{
struct Class * p = C, * q = C ->next ;
while ( q )
{
free(p);
p = q;
q = p->next;
}
free(p);
C = NULL;
cout << "单链表已销毁" << endl ;
}
代码
#include <bits/stdc++.h>
using namespace std;
struct Student //学生
{
long long ID; //学号
char name[20]; //姓名
double score; //成绩
};
struct Class //班级(Class_and_grade)
{
struct Student S; //学生
struct Class *next; //指向下一个结构体
};
//stuct Class Initialize ( ) //初始化单链表(返回值为结构体类型)
void Class_Initialize( Class * & C ) //初始化单链表(调用参数)
{
C = ( Class * ) malloc ( sizeof ( Class ) ) ; //开辟内存
C ->next = NULL ; //将头指针的后继置空
}
void Import( struct Class * & C ) //输入(尾插法)
{
struct Class * p = NULL, * q = NULL ; //定义俩个工作指针
q = C ;
cout << "输入要录入学生个数:";
int n ;
cin >> n ;
for( int i = 0 ; i < n ; i++ )
{
p = ( Class * ) malloc ( sizeof ( Class ) ) ;
cout << "输入第" << i + 1 << "位学生的信息:"<<endl;
cout << "学号:" << endl;
cin >> p ->S.ID;
cout << "姓名:" << endl;
cin >> p ->S.name;
cout << "成绩:" << endl;
cin >> p ->S.score;
q ->next = p ;
q = p ;
q ->next = NULL ;
}
}
void Output ( struct Class * C ) //输出单链表
{
struct Class *p = C ->next ; //定义工作指针指向头指针
int num=0;
while(p!=NULL)
{
printf("%2d|%010d\t|%s\t|%5.2lf\n", num++, p ->S.ID, p ->S.name, p->S.score );
p = p ->next ;
}
}
void Interposition ( struct Class * & C, int location )
{
struct Class * p = C, * q = NULL ;
if ( location < 0 )
{
cout << "位置错误" << endl ;
return ;
}
for ( int i = 0 ; i < location - 1 ; i ++ )
{
p = p ->next;
if (!p)
{
cout << "位置错误" << endl;
return ;
}
}
q = ( Class * ) malloc ( sizeof ( Class ) ) ;
cout << "输入第" << location + 1 << "位学生的信息:" << endl ;
cout << "学号:" << endl;
cin >> q ->S.ID;
cout << "姓名:" << endl;
cin >> q ->S.name;
cout << "成绩:" << endl;
cin >> q ->S.score;
q ->next = p ->next;
p ->next = q;
cout << "插入成功" << endl ;
}
void Find ( struct Class * S, long long ID) //按元素查找
{
struct Class *p ; //定义工作指针
int i = 1 ;
for( p = S ->next ; p != NULL ; p = p ->next )
{
if (p ->S.ID == ID )
{
cout << "第" << i + 1 << "位学生:" << endl ;
cout << "姓名:" << p ->S.name << "成绩:"<< p ->S.score << endl ;
return ;
}
}
cout << "未找到该用户" << endl ;
}
void Delate ( struct Class * & C, long long ID )//删除结点
{
struct Class * p = C ->next, * q = C ;
for( ; p != NULL ; q =p,p =p ->next )
//p指针和q指针同时查找,p指向当前的学生,q保指向了上一个学生
{
if( p ->S.ID == ID )
{
q ->next = p ->next; //假设找到了需要删除的学生,让它上一个学生的指针指向跳过他的下一个学生
free ( p ) ; //释放 p 节点
cout << "删除成功" << endl ;
return ;
}
}
cout << "删除失败" << endl ;
}
void Release ( struct Class * & C )
{
struct Class * p = C, * q = C ->next ;
while ( q )
{
free(p);
p = q;
q = p->next;
}
free(p);
C = NULL;
cout << "单链表已销毁" << endl ;
}
int main()
{
struct Class * C ; //当前链表的头指针
long long ID ; //学号
int n, location ; //指令,插入位置
Class_Initialize( C ); //当前的链表指针
do
{
cout << "1.输入 2.插入 3.查找 4.删除 5.输出 0.销毁"<<endl;
cout << "请输入指令:";
cin >> n ;
switch(n)
{
case 1: //输入单链表
Import( C ) ;
break ;
case 2: //按位置查找结点并插入
cout << "输入要插入位置:";
cin >> location ;
Interposition ( C, location );
break;
case 3: //按元素查找结点
cout << "输入要查找学生的学号:";
cin >> ID ;
Find ( C, ID );
break;
case 4: //按元素查找节点并删除
cout << "输入要删除学生的学号:";
cin >> ID ;
Delate ( C, ID );
break;
case 5: //输出线性表
Output( C ) ;
break ;
case 0: //销毁线性表
Release ( C );
break;
default:
cout<<"指令有误,请重新输入:";
}
}
while(n);
return 0;
}
拓展(顺序表/单链表)
通过对顺序表和单链表大量练习,体会到俩种存储方式的优缺点,并在实际问题中灵活运用
顺序表
顺序表易于理解,节省空间,适合存储后只进行读取,不修改或修改操作执行次数较少时使用
单链表
单链表需要的内存空间大于顺序表,但是当修改次数较多时,单链表进行修改只需要改变修改节点的前驱后继