实验二、链表——学生成绩表的管理
实验目的:
熟悉链式表的逻辑特性、存储表示方法的特点和链式表的基本操作。
实验要求:
能够实现线性表的链式存储表示,能够实现链表的基本操作及应用。
实验内容:
编写程序实现下列的要求:
(1)设学生成绩表中的数据元素为学生成绩(含姓名、成绩字段),实现这样的线性表的链式存储表示。
(2)键盘输入若干个数据元素(用特殊数据来标记输入数据的结束),利用链表的基本操作(前插或后插算法),建立学生成绩单链表。测试数据如:
关 88 张 85 马 90 赵 55 黄 85
(3)键盘输入关键字值x,打印出表中所有关键字值<=x的结点数据。(用于比较的关键字字段为分数)。如x=85等。
(4)输入关键字值x,删除表中所有关键字值<=x的结点。(用于比较的关键字字段为分数)。
(5)* 释放该链表(删除所有结点)。
(6)* 若要求建立的学生成绩单链表为有序表,重新编写算法和程序实现前面的要求(3)。(用于比较的字段为分数)。
练习及思考题:
(1)不同类型的数据元素所对应的链式表在类型定义和操作实现上有什么异同?
(2)有头结点的链式表,有什么特点?
(3)尽量多地利用已有的代码,实现两个多项式的加、减及乘法等运算。
(4)尽量多地利用已有的代码,实现两个集合的和(并)、差及交等运算。
main.cpp
#include<iostream>
#include "linklist.h"
using namespace std;
int main(){
LinkList L;
CreateList_H(L);//头插
Print_small_x(L);//打印分数小于等于score的数据结点
Delete_small_x(L);//删除分数小于等于score的数据结点
DestroyList(L);//销毁
//构建有序链表
return 0;
}
basic.cpp
#include "linklist.h"
#include<iostream>
using namespace std;
//初始化(带头结点)
void InitList(LinkList &L){
L=new LNode;
L->next=NULL;
}
//判空
bool Empty(LinkList L){
return L->next==NULL;
}
//输出单链表
void PrintList(LinkList L){
LNode *p=L->next;
while(p){
cout<<p->data.name<<"\t"<<p->data.score<<endl;
p=p->next;
}
cout<<endl;
}
//按位查找
bool GetElem(LinkList L,int i,ElemType &e){
}
//后删
bool DeleteNextNode(LNode *p){
LNode *next=p->next;
p->next=next->next;
delete p;
}
//打印表中所有分数 <= x的结点数据
void Print_x(LinkList L,float x){
LNode *p=L->next;
int flag=0;
while(p){
if(p->data.score<=x){
flag=1;
cout<<p->data.name<<"\t"<<p->data.score<<endl;
p=p->next;
}
}
if(flag==0){
cout<<"没有学生的分数小于等于"<<x<<endl;
}
}
//删除表中所有分数 <= x的结点数据
void Delete_x(LinkList &L,float x){
LinkList A=L;
LNode *r=L,*pl=L->next;
while(pl){
if(pl->data.score>x){
r->next=pl;
r=pl;
pl=pl->next;
}else{
LNode *p=pl;
pl=pl->next;
delete p;
}
}
r->next=NULL;
}
extra.cpp
#include "linklist.h"
#include<iostream>
using namespace std;
//头插法建立单链表
void CreateList_H(LinkList &L){
cout<<"----------------------头插法建立单链表----------------------"<<endl;
InitList(L);//初始化
cout<<"请输入学生信息(输入#表示结束):"<<endl;
cout<<"请输入学生姓名:";
string name;
cin>>name;
while(name!="XXX"){
cout<<"请输入该学生的分数:";
float score;
cin>>score;
LNode *p=new LNode;
p->data.name=name;
p->data.score=score;
p->next=L->next;
L->next=p;
cout<<"请输入学生姓名:";
cin>>name;
}
cout<<"建立完成!"<<endl;
PrintList(L);
}
//尾插法建立单链表
void CreateList_T(LinkList &L){
cout<<"----------------------尾插法建立单链表----------------------"<<endl;
InitList(L);//初始化
LNode *r=L;
cout<<"请输入学生信息(输入#表示结束):"<<endl;
cout<<"请输入学生姓名:";
string name;
cin>>name;
while(name!="XXX"){
cout<<"请输入该学生的分数:";
float score;
cin>>score;
LNode *p=new LNode;
p->data.name=name;
p->data.score=score;
p->next=NULL;
r->next=p;
r=p;
cout<<"请输入学生姓名:";
cin>>name;
}
cout<<"建立完成!"<<endl;
PrintList(L);
}
//销毁
void DestroyList(LinkList &L){
cout<<"---------------------- 销毁单链表 ----------------------"<<endl;
while(L->next!=NULL){
DeleteNextNode(L);//一直删头结点后面的结点
}
delete L;//删除头结点
L->next=NULL;
cout<<"销毁成功!"<<endl;
}
//打印表中所有分数 <= x的结点数据
void Print_small_x(LinkList L){
cout<<"-------------打印表中所有分数小于等于score的结点数据------------"<<endl;
cout<<"请输入分数:";
float score;
cin>>score;
Print_x(L,score);
}
//删除表中所有分数 <= x的结点数据
void Delete_small_x(LinkList &L){
cout<<"-------------删除表中所有分数小于等于score的结点数据------------"<<endl;
cout<<"请输入分数:";
float score;
cin>>score;
Delete_x(L,score);
cout<<"删除成功:";
PrintList(L);
}
linklist.h
#ifndef CIRCLE_H
#define CIRCLE_H
#include<iostream>
using namespace std;
typedef struct student{
string name;//学生姓名
float score;//分数
}student;
typedef student ElemType;
typedef struct LNode{
ElemType data;
struct LNode *next;
}LNode,*LinkList;
void InitList(LinkList &L);
void PrintList(LinkList L);
bool DeleteNextNode(LNode *p);
void DestroyList(LinkList &L);
void Delete_x(LinkList &L,float x);
void Print_x(LinkList L,float x);
void CreateList_H(LinkList &L);
void Print_small_x(LinkList L);
void Delete_small_x(LinkList &L);
#endif
有序多项式的建立:
void CreatePolyn(PolLinkList &P){//建立有序多项式P
cout<<"-------------建立有序多项式P------------"<<endl;
P=new PolNode;
P->next=NULL;
cout<<"请输入您要建立的多项式的项数:";
int n;
cin>>n;
for(int i=1;i<=n;i++){
cout<<"请输入第"<<i<<"项的系数和指数:";
PolNode *s=new PolNode;
cin>>s->data.coef>>s->data.expn;
PolNode *pre=P;
PolNode *p=P->next;
while(p&&p->data.expn<s->data.expn){//找到第一个大于等于它的结点
p=p->next;
pre=pre->next;
}
s->next=p;
pre->next=s;
}
cout<<"创建成功!"<<endl;
Print_Polyn(P);
}
对于有序多项式的操作:
//有序多项式的加法
void AddPolyn(PolLinkList Pa,PolLinkList Pb,PolLinkList &Pc){//求多项式Pa+Pb,返回这两个多项式的和Pc
PolNode *p1=Pa->next;
PolNode *p2=Pb->next;
Pc=new PolNode;
Pc->next=NULL;
PolNode *p3=Pc;
while(p1&&p2){
if(p1->data.expn==p2->data.expn){//指数相等,进行相加(需注意系数之和是否为0)
PolNode *s=new PolNode;
s->data.expn=p1->data.expn;
s->data.coef=p1->data.coef+p2->data.coef;
if(s->data.coef!=0){
p3->next=s;
p3=s;
}
p1=p1->next;
p2=p2->next;
}else if(p1->data.expn<p2->data.expn){//p1指向的指数更小,后移
PolNode *s=new PolNode;
s->data.expn=p1->data.expn;
s->data.coef=p1->data.coef;
p3->next=s;
p3=s;
p1=p1->next;
}else{// p2指向的指数更小,后移
PolNode *s=new PolNode;
s->data.expn=p2->data.expn;
s->data.coef=p2->data.coef;
p3->next=s;
p3=s;
p2=p2->next;
}
}
while(p1!=NULL){//p1没有遍历完,将未遍历的部分直接加入结果中
PolNode *s=new PolNode;
s->data.expn=p1->data.expn;
s->data.coef=p1->data.coef;
p3->next=s;
p3=s;
p1=p1->next;
}
while(p2!=NULL){//p2没有遍历完,将未遍历的部分直接加入结果中
PolNode *s=new PolNode;
s->data.expn=p2->data.expn;
s->data.coef=p2->data.coef;
p3->next=s;
p3=s;
p2=p2->next;
}
p3->next=NULL;
}
//有序多项式的减法
void SubPolyn(PolLinkList Pa,PolLinkList Pb,PolLinkList &Pc){//求多项式Pa-Pb,返回这两个多项式的差Pc
PolNode *p1=Pa->next;
PolNode *p2=Pb->next;
Pc=new PolNode;
Pc->next=NULL;
PolNode *p3=Pc;
while(p1&&p2){
if(p1->data.expn==p2->data.expn){//指数相等,进行相减(需注意系数之和是否为0)
PolNode *s=new PolNode;
s->data.expn=p1->data.expn;
s->data.coef=p1->data.coef-p2->data.coef;
if(s->data.coef!=0){
p3->next=s;
p3=s;
}
p1=p1->next;
p2=p2->next;
}else if(p1->data.expn<p2->data.expn){//p1指向的指数更小,后移
PolNode *s=new PolNode;
s->data.expn=p1->data.expn;
s->data.coef=p1->data.coef;
p3->next=s;
p3=s;
p1=p1->next;
}else{//p2指向的指数更小,后移(由于是减法,p1中没有对应的项进行相减,相当于0-coef)
PolNode *s=new PolNode;
s->data.expn=p2->data.expn;
s->data.coef=0-p2->data.coef;
p3->next=s;
p3=s;
p2=p2->next;
}
}
while(p1!=NULL){//p1没有遍历完,将未遍历的部分直接加入结果中
PolNode *s=new PolNode;
s->data.expn=p1->data.expn;
s->data.coef=p1->data.coef;
p3->next=s;
p3=s;
p1=p1->next;
}
while(p2!=NULL){//p2没有遍历完,将未遍历的部分直接加入结果中(由于是减法,p1遍历完了,相当于0-coef)
PolNode *s=new PolNode;
s->data.expn=p2->data.expn;
s->data.coef=0-p2->data.coef;
p3->next=s;
p3=s;
p2=p2->next;
}
p3->next=NULL;
}
//有序多项式的乘法
void MulPolyn(PolLinkList Pa,PolLinkList Pb,PolLinkList &Pc){
PolNode *p1=Pa->next;
PolNode *p2=Pb->next;
Pc=new PolNode;
Pc->next=NULL;
PolNode *p3=Pc;
for(;p1!=NULL;p1=p1->next){
for(p2=Pb->next;p2!=NULL;p2=p2->next){
PolNode *s=new PolNode;
s->data.expn=p1->data.expn+p2->data.expn;
s->data.coef=p1->data.coef*p2->data.coef;
if(s->data.coef!=0){
//合并同类项
PolNode *q=Pc->next;
PolNode *pre=Pc;
while(q&&q->data.expn<s->data.expn){//找到第一个指数大于等于s的结点
q=q->next;
pre=pre->next;
}
if(q==NULL){//没找到,证明s结点的指数是最大的
p3->next=s;
p3=s;
}else{//找到了,不插在最后面
if(q->data.expn==s->data.expn){//如果指数相等,合并同类项
q->data.coef=q->data.coef+s->data.coef;
if(q->data.coef==0){//系数为0则舍去
pre->next=q->next;
delete q;
}
delete s;
}else{//如果指数大于s,将s结点放在前面
s->next=q;
pre->next=s;
}
}
}
}
}
p3->next=NULL;
}
//并
void BingPolyn(PolLinkList Pa,PolLinkList Pb,PolLinkList &Pc){//求多项式Pa,Pb项的并集Pc
PolNode *p1=Pa->next;
PolNode *p2=Pb->next;
Pc=new PolNode;
Pc->next=NULL;
PolNode *p3=Pc;
while(p1&&p2){
if(p1->data.expn==p2->data.expn){//指数相等
if(p1->data.coef==p2->data.coef){//如果系数也相等,则项相等,取一个即可
PolNode *s=new PolNode;
s->data.expn=p1->data.expn;
s->data.coef=p1->data.coef;
p3->next=s;
p3=s;
}else{//系数不相等,两个都要保留
PolNode *s=new PolNode;
PolNode *s1=new PolNode;
s->data.expn=p1->data.expn;
s->data.coef=p1->data.coef;
p3->next=s;
p3=s;
s1->data.expn=p2->data.expn;
s1->data.coef=p2->data.coef;
p3->next=s1;
p3=s1;
}
p1=p1->next;
p2=p2->next;//将两个指针都向后挪
}else if(p1->data.expn<p2->data.expn){//p1指向的指数更小,先放进并集中,然后往后挪
PolNode *s=new PolNode;
s->data.expn=p1->data.expn;
s->data.coef=p1->data.coef;
p3->next=s;
p3=s;
p1=p1->next;
}else{//p2指向的指数更小,先放进并集中,然后往后挪
PolNode *s=new PolNode;
s->data.expn=p2->data.expn;
s->data.coef=p2->data.coef;
p3->next=s;
p3=s;
p2=p2->next;
}
}
//把剩下的放进结果中
while(p1!=NULL){
PolNode *s=new PolNode;
s->data.expn=p1->data.expn;
s->data.coef=p1->data.coef;
p3->next=s;
p3=s;
p1=p1->next;
}
while(p2!=NULL){
PolNode *s=new PolNode;
s->data.expn=p2->data.expn;
s->data.coef=p2->data.coef;
p3->next=s;
p3=s;
p2=p2->next;
}
p3->next=NULL;
}
//交
void JiaoPolyn(PolLinkList Pa,PolLinkList Pb,PolLinkList &Pc){//求多项式Pa,Pb项的交集Pc
PolNode *p1=Pa->next;
PolNode *p2=Pb->next;
Pc=new PolNode;
Pc->next=NULL;
PolNode *p3=Pc;
while(p1&&p2){
if(p1->data.expn==p2->data.expn){
if(p1->data.coef==p2->data.coef){//项相同(即系数和指数都相同)才放入交集
PolNode *s=new PolNode;
s->data.expn=p1->data.expn;
s->data.coef=p1->data.coef;
p3->next=s;
p3=s;
}
p1=p1->next;
p2=p2->next;
}else if(p1->data.expn<p2->data.expn){
p1=p1->next;
}else{
p2=p2->next;
}
}
p3->next=NULL;
}
//差
void ChaPolyn(PolLinkList Pa,PolLinkList Pb,PolLinkList &Pc){//求多项式Pa,Pb项的差集Pc
PolNode *p1=Pa->next;
PolNode *p2=Pb->next;
Pc=new PolNode;
Pc->next=NULL;
PolNode *p3=Pc;
while(p1&&p2){
//将Pa中有,Pb中没有的项放入结果
if(p1->data.expn==p2->data.expn){
if(p1->data.coef==p2->data.coef){
}else{
PolNode *s=new PolNode;
s->data.expn=p1->data.expn;
s->data.coef=p1->data.coef;
p3->next=s;
p3=s;
}
p1=p1->next;
p2=p2->next;
}else if(p1->data.expn<p2->data.expn){
PolNode *s=new PolNode;
s->data.expn=p1->data.expn;
s->data.coef=p1->data.coef;
p3->next=s;
p3=s;
p1=p1->next;
}else{
p2=p2->next;
}
}
while(p1!=NULL){
PolNode *s=new PolNode;
s->data.expn=p1->data.expn;
s->data.coef=p1->data.coef;
p3->next=s;
p3=s;
p1=p1->next;
}
p3->next=NULL;
}