用线性表建立学生信息
这是继上一次实验(顺序表)的后续,即用线性表的链式表示和实现,这个实验的要求相关事项这里就不再赘述,可以到我的上一篇文章去看,顺序表的内容也在上一篇文章,这里仅对单链表的操作进行表示和实现。
初始化部分:即构造一个空链表。
【算法描述】
Status InitList(LinkList &L)
{
L=new LNode; //新结点作为头结点
L->next=NULL; //指针域置空
return OK;
}
取值:链表的取值只能从链表的首元结点出发,顺着链域next逐个结点向下访问。
【算法描述】
Status GetElem(LinkList L,ElenType e)
{
P=L->next;j=1; //初始化,p指向首元结点
while(p&&j<i) //直到p为空或者p指向第i个元素
{ p=p->next; //p指向下一个结点
++j;
}
if(!p||j>i) return ERROR; //i的值不合法i>n or i<=0
e=p->data; //取第i个结点的数据域
return OK;
}
查找:查找过程跟顺序表类似,从链表的首元结点出发,依次将结点值和给定的值e进行比较,返回查找结果。
LNode *LocateElem(LinkList L,ElemType e)
{
P=L->next; //初始化,p指向首元结点
while(p&&p->data!=e)
p=p->next;
return p; //查找成功返回值为e的结点地址p,查找失败p为NULL
}
插入:链表的插入不需要像顺序表的插入操作那样需要移动元素,只需要在在一条链中的两元素之间断开,再用前一个数据元素的指针域指向要插入的数据元素,再令要插入数据元素的指针域指向指向刚才与前一数据元素相连接的后一个数据元素,即后一个数据元素,指针修改可以用数据元素描述为 s->next=p->next; p->next=s;
【算法描述】
Status ListInsert(LinkList &L,int i,ElemType e)
{
p=L;j=0;
while(p&&(j<i-1))
{p=p->next;++j;} //查找到第i-1个结点,p指向该结点
if(!p||j>i-1) return ERROR; //插入位置不合理
s=new Node; //生成新结点
s->data=e; //将结点*s的数据域置为e
s->next=p->next;
p->next=s;
return OK;
}
删除:删除操作跟插入操作一样,只不过这是减少一个数据元素,表长减一。首先找到指定位置的前驱结点,删除该元素时只需修改该数据元素的前一个元素的指针即可,可以描述为 p->next=p->next->next; 还要引入另一个结点,用来释放刚才已经删除了的数据元素的地址。
【算法描述】
Status ListDelete(LinkList &L,int i)
{
p=L;j=0;
while((p->next) && (j<i-1)) //找到第i-1个结点,p指向该结点
{p=p->next;++j;}
if(!(p->next) && (j>i-1)) return OK; //位置不合理
q=p->next; //临时保存被删结点的地址以备释放
p->next=q->next;
delete q; //释放删除结点的空间
return OK;
}
基本操作都已经有了,剩下的也还是主函数部分,同样的,也要有输入输出操作,用来录入信息、显示信息,跟上一篇文章的一样,这里不再写,有兴趣的可以去浏览一下,不过下面的这次实验的完整代码中也有。
【完整代码】
#include<stdio.h>
#include<malloc.h>
#include<stdlib.h>
#include<string.h>
#define OK 1
#define ERROR 0
#define OVERFLOW -2
typedef int Status; // 定义函数返回值类型
typedef struct
{
char no[8]; // 学号
char name[20]; // 姓名
int score; // 成绩
}student;
typedef student ElemType;
typedef struct LNode
{
ElemType data; // 数据域
struct LNode *next; //指针域
}LNode,*LinkList;
Status InitList(LinkList &L) // 构造空链表 L
{
L=(struct LNode*)malloc(sizeof(struct LNode)); //生成新结点,头指针L头结点
L->next=NULL;
return OK;
}
Status GetElem(LinkList L,int i,ElemType &e) // 访问链表,找到 i位置的数据域,返回给 e
{
LinkList p;
p=L->next;
int j=1;
while(p&&j<i) //向后扫描,直到p为空或p指向第i个元素
{
p=p->next; //p指向下一个结点
++j;
}
if(!p||j>i) return ERROR; //i值不合法i>n或i<=0
e=p->data; //取第i个结点的数据域
return OK;
}
Status Search(LNode L,char str[],LinkList &p) // 根据名字查找
{
p=L.next;
while(p)
{
if(strcmp(p->data.name,str)==0)
return OK;
p=p->next; //指向下一个结点
}
return ERROR;
}
Status ListInsert(LinkList L,int i,ElemType e) // 在 i个位置插入某个学生的信息
{
LinkList p,s;
p=L;
int j=0;
while(p&&j<i-1)
{
p=p->next;
++j;
}
if(!p||j>i-1) return ERROR;
s=(struct LNode*)malloc(sizeof(LNode)); //生成新结点*s
s->data=e; //将结点*s的数据域置为e
s->next=p->next; //将结点*e的指针域指向结点ai
p->next=s; //将结点*p的指针域指向结点*s
return OK;
}
Status ListDelete(LinkList p,int i) // 删除 i位置的学生信息
{
int j=0;
while((p->next)&&(j<i-1)) //查到第i-1个结点,p指向该结点
{
p=p->next;
++j;
}
if(!(p->next)||(j>i-1)) return ERROR;
LinkList q;
q=p->next; //临时保存被删结点的地址以备释放
p->next=q->next; //改变删除结点前驱结点的指针域
delete q; //释放删除结点的空间
return OK;
}
void Input(ElemType *e) //输入
{
printf("姓名:");
scanf("%s",e->name);
printf("学号:");
scanf("%s",e->no);
printf("成绩:");
scanf("%d",&e->score);
printf("输入完成\n\n");
}
void Output(ElemType &e) //输出
{
printf("姓名:%s\n学号:%s\n成绩:%d\n\n",e.name,e.no,e.score);
}
int main()
{
LNode L;
LinkList p;
ElemType a,b,c,d;
printf("1. 构造顺序表\n");
printf("2. 录入指定人数的学生信息\n");
printf("3. 显示学生表中的所有信息\n");
printf("4. 根据姓名查找该学生,并返回学号和成绩\n");
printf("5. 根据某指定位置显示该学生信息\n");
printf("6. 在指定位置插入学生信息\n");
printf("7. 在指定位置删除学生信息\n");
printf("8. 统计学生个数\n");
printf("0. 退出\n");
int n,choose=-1;
while(choose!=0)
{
printf("请输入你要选择的功能前的序号:");
scanf("%d",&choose);
if(choose==0)
break;
else if (choose==1)
{
if(InitList(p))
printf("建立顺序表成功\n");
else
printf("建立顺序表失败\n");
}
else if (choose==2)
{
printf("要输入学生的人数:");
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
printf("第%d个学生:\n",i);
Input(&a);
ListInsert(&L,i,a);
}
}
else if (choose==3)
{
for(int i=1;i<=n;i++)
{
GetElem(&L,i,b);
Output(b);
}
}
else if (choose==4)
{
char s[20];
printf("请输入要查找的学生姓名:");
scanf("%s",&s);
if(Search(L,s,p))
Output((p->data));
else
printf("查无此人");
}
else if (choose==5)
{
printf("请输入要查询的位置:");
int id1;
scanf("%d",&id1);
GetElem(&L,id1,c);
Output(c);
}
else if (choose==6)
{
printf("请输入要插入的位置:");
int id2;
scanf("%d",&id2);
printf("请输入学生信息:\n");
Input(&d);
if(ListInsert(&L,id2,d))
{
n++;
printf("插入成功\n");
}
else
{
printf("插入失败\n");
}
}
else if (choose==7)
{
printf("请输入要删除的位置:");
int id3;
scanf("%d",&id3);
if(ListDelete(&L,id3))
{
n--;
printf("删除成功\n");
}
else
{
printf("删除失败\n");
}
}
else if (choose==8)
{
printf("\n已录入的学生个数为:%d\n\n",n);
break;
}
}
printf("\n请按任意键退出\n\n");
system("pause");
return 0;
}
欢迎指错纠正!!
【参考文献】:《数据结构》(C语言版|第2版)严蔚敏 李冬梅 吴伟民编著