数据结构实验一 :顺序表的综合操作

该程序使用C++实现了一个顺序表,包含学生信息(学号,姓名,性别,年龄),实现了输入、显示、查找、插入、删除和计数等功能。通过文件输入或逐个输入学生信息,支持按姓名和位置查询,动态插入和删除元素,以及统计学生数量。程序中定义了结构体和子函数,包括初始化、输入、输出、查询、插入、删除和统计子函数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、实验目的

1.掌握线性表的定义;

2.掌握线性表的顺序存储基本操作,如建立、查找、插入和删除等。

二、实验内容

定义一个包含学生信息(学号,姓名,性别,年龄)的的顺序表,使其具有如下功能:

(1) 根据指定学生个数,逐个输入学生信息;

(2) 逐个显示学生表中所有学生的相关信息;

(3) 根据姓名进行查找,返回此学生的学生信息;

(4) 根据指定的位置可返回相应的学生信息;

(5) 给定一个学生信息,插入到表中指定的位置;

(6) 删除指定位置的学生记录;

(7) 统计表中学生个数。

三、实验提示

学生信息的定义:

typedef struct {

    char  no[11];     //表示11位学号,也可以定义为string no;

    char name[20];    //表示姓名,也可以定义为string name;

char xb;          //表示性别,以字母M表示男,字母W表示女

int age;         //表示年龄

} Student;

顺序表的定义

typedef  struct {

    Student  *elem;     //指向线性表的基地址

    int  length;        //线性表的当前长度

}SqList;

包含的头文件与声明:

#include<iostream>
#include<string.h>
#include<fstream>
using namespace std;
#define maxsize 100

对顺序表进行定义:

typedef struct{
	string no;
	string name;
	char xb;
	int age;
}student;
typedef struct{
	student *elem;
	int length;
}sqlist;

子函数,为顺序表分配空间:

注:在C语言中动态分配的函数有malloc、calloc和realloc,包含在头文件<stdio.h>中,C++则是简单的new函数,其中的区别我们将在下一节进行讲明;

void initlist(sqlist &l){
	l.elem=new student[maxsize];	
	if (!l.elem)
		cout<<"创建顺序表失败"<<endl; 
	else{
		l.length = 0; 
		cout<<"创建顺序表成功"<<endl;
	}
}

子菜单函数,用于提高程序的交互性:

void menu(){
	cout<<"1.输入学生信息"<<endl;
    cout<<"2.显示所有学生信息"<<endl;
    cout<<"3.根据姓名查找学生信息"<<endl; 
    cout<<"4.根据指定位置学生信息"<<endl;
    cout<<"5.插入学生信息"<<endl;
    cout<<"6.删除指定学生信息"<<endl;
    cout<<"7.统计学生个数"<<endl;
    cout<<"0.退出"<<endl;
}

子输入函数,在代码段中我使用了两种输入的方式,一种为文件的输入,被注释的部分则为一般的正常逐个输入:

注:在c++中我们输入输出通常使用cin与cout函数,相比之下比c语言的scanf与printf更节省时间

void input(sqlist &l){
	int i=0;
	fstream file;//文件输入 
	file.open("student.txt");
	if(!file){
		cout<<"错误!未找到文件"<<endl; 
	}
	while(!file.eof()){
		file>>l.elem[i].no>>l.elem[i].name>>l.elem[i].xb>>l.elem[i].age;
		i++;
	}
	cout<<"输入student.txt信息完毕"<<endl;
	l.length=i;//不用减一,i从开始加 
	file.close();//文件关闭 
//	int n;
//	cout<<"请输入学生个数"<<endl;
//	cin>>n;
//	cout<<"请输入学生的 学号 姓名 性别 年龄:"<<endl;
//	for(int i=l.length;i<=n-1;i++){
//		cin>>l.elem[i].no>>l.elem[i].name>>l.elem[i].xb>>l.elem[i].age;
//	} 
//	l.length=n;
}

功能子函数执行将顺序表中的元素全部逐个输出:

void output(sqlist l){
	cout<<"表中所有学生学号 姓名 性别 年龄为:"<<endl;
	for(int i=0;i<=l.length-1;i++){ 
		cout<<l.elem[i].no<<"	"<<l.elem[i].name<<"	"<<l.elem[i].xb<<"	"<<l.elem[i].age<<endl;
	}
}

 子查询函数,主要功能为根据学生姓名或位置进行查找并输出:

void search(sqlist l){
	string name;
	int flag=0;
	cout<<"请输入要查询的学生姓名:"<<endl;
	cin>>name;
	for(int i=0;i<=l.length-1;i++){
		if(l.elem[i].name==name){
			cout<<"该生的学号 姓名 性别 年龄为:"<<endl; 
			cout<<l.elem[i].no<<"	"<<l.elem[i].name<<"	"<<l.elem[i].xb<<"	"<<l.elem[i].age<<endl;
			flag=1;
		}
	}
	if(!flag){
		cout<<"未查询到学生"<<name<<"的信息"<<endl;
	}
}
void search_2(sqlist l){
	int i;
	cout<<"请输入要查询学生的位置"<<endl;
	cin>>i; 
	if(i<=0||i>=l.length){
		cout<<"未查询到该学生信息"<<endl;
	}
	else{
		cout<<"该生的学号 姓名 性别 年龄为:"<<endl; 
		cout<<l.elem[i-1].no<<"	"<<l.elem[i-1].name<<"	"<<l.elem[i-1].xb<<"	"<<l.elem[i-1].age<<endl;
	}
}

子插入函数,功能为在相应位置进行插入操作,主要实现将该位置的及以后的元素全部向后移动一位,所以需要判断表是否已满。因为顺序表插入与删除操作都需要大量的时间复杂度所以在需要大量更改元素的情况下,我们大多使用链表来完成实验:

void insert(sqlist &l){
	int n,i;
	cout<<"请输入要插入的学生位置"<<endl;
	cin>>n; 
	if(n<=0||n>=maxsize||l.length>=maxsize){
		cout<<"插入错误"<<endl;
	}
	else{
		for(i=l.length-1;i>=n-1;i--){//减一 
		l.elem[i+1].no=l.elem[i].no;
		l.elem[i+1].name=l.elem[i].name;
		l.elem[i+1].xb=l.elem[i].xb;
		l.elem[i+1].age=l.elem[i].age;
	}
	cout<<"请输入要插入学生的学号 姓名 性别 年龄:"<<endl;
	cin>>l.elem[n-1].no>>l.elem[n-1].name>>l.elem[n-1].xb>>l.elem[n-1].age; 
	l.length+=1;//插入后长度加一 
	cout<<"插入成功"<<endl;
	}	
} 

注:该代码段中的l.elem[i+1].n=l.elem[i].no以及其他元素的替换可以统合为l.elem[i+1]=l.elem[i],所实现的功能是一样的,可以减少代码长度

子删除函数,主要功能为将指定位置的函数进行删除:

注:在C++中delete函数用于回收new分配的内存空间,包含在头文件<iostream>中。C++中我们在回收用 new 分配的单个对象的内存空间的时候用delete,回收用 new[]分配的一组对象的内存空间的时候用delete[]。所以我使用的函数名为delete_1

void delete_1(sqlist &l){
	int n,i;
	cout<<"请输入要删除的学生位置"<<endl; 
	cin>>n;
	if(n<=0||n>l.length){
		cout<<"删除错误"<<endl;
	} 
	else{
		for(i=n;i<=l.length-1;i++){//减一 
			l.elem[i-1].no=l.elem[i].no;
			l.elem[i-1].name=l.elem[i].name;
			l.elem[i-1].xb=l.elem[i].xb;
			l.elem[i-1].age=l.elem[i].age;
		}
		cout<<"删除成功"<<endl;
		l.length-=1;//删除后长度减一 
	}
}

 子输出函数,实现的功能为将表中含有的学生人数输出,即为输出l.length,因此我们在进行插入与删除操作时应注意l.length长度的变化:

void list(sqlist l){
	cout<<"表中共有"<<l.length<<"名学生"<<endl;
}

主函数,主要用到的为while语句与switch语句,为了减少操作难度与代码简洁我将所有的函数返回值设置为void空类型,所有操作均在子函数中进行:

int main(){
	sqlist l;
	int i = 0, n, temp,choose;
	initlist(l); 
	menu();
	cin>>choose;
	while(choose!=0){
	switch(choose){
		case 1:input(l);break;
		case 2:output(l);break;
		case 3:search(l);break;
		case 4:search_2(l);break;
		case 5:insert(l);break;
		case 6:delete_1(l);break;
		case 7:list(l);break;
	}	
	cout<<"请输入操作"<<endl;
	cin>>choose;
	}
    cout<<"欢迎下次使用"endl;
	return 0;
} 

文件截图:

注:如图,我们在使用文件输入的时候要记得将文件名改为代码中打开的文件名如"student.txt"并在另存为时将编码改为ANSI,否则会出现文件输入时文字乱码

注:目前程序还存在一些bug,例如在我输入5位学生信息时,若是在插入时不小心插入到第7位,在执行输出函数时,第6位的值变成了0,而插入第7位学生的信息却会消失或者被覆盖;

以下为该程序的运行结果:​​​​​​​

 

评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值