顺序表是一种线性表数据结构,它的定义是:把线性表中所有表项按照其逻辑顺序依次存储到从计算机存储中指定存储位置开始的一块连续的存储空间中。这样,线性表中第一个表项的存储位置就是被指定的存储位置,第i个表项(2 ≤ i ≤ n)的存储位置紧接在第i - 1个表项的存储位置的后面。
顺序表的特点包括:
- 在顺序表中,各个表项的逻辑顺序与其存放的物理顺序一致,即第i个表项存储于第i个物理位置(1 ≤ i ≤ n)。
- 对顺序表中所有表项,既可以进行顺序访问,也可以进行随机访问。也就是说,既可以从表的第一个表项开始逐个访问表项,也可以按照表项的序号(下标)直接访问表项。
- 顺序表的存储密度高,因为它使用连续的存储空间。
- 顺序表也有一些缺点,例如要求大片连续空间,改变容量不方便。
总的来说,顺序表是一种非常基本和常用的数据结构,它适用于需要快速访问元素的情况,但不适用于需要频繁插入和删除元素的情况。
2.顺序表的基本运算
顺序表的基本运算包括以下几种:
- 初始化顺序表:在创建顺序表时,需要对顺序表进行初始化,即将顺序表中的元素全部置为0或其他默认值。
- 插入元素:在顺序表的指定位置插入一个新元素。插入元素时,需要将该位置及其后面的所有元素依次向后移动一个位置,为新元素腾出空间。
- 删除元素:在顺序表的指定位置删除一个元素。删除元素时,需要将该位置后面的所有元素依次向前移动一个位置,覆盖要删除的元素。
- 判断顺序表是否为空:获取顺序表中指定位置的元素值。
- 判断顺序表是否已满:计算顺序表中元素的个数。
- 查询指定元素:在顺序表中查找指定值的元素,并返回其位置。
- 输出顺序表:依次访问顺序表中的每个元素,并进行相应的操作。
- 帮助:顺序表的功能及其特点
- 销毁顺序表:释放顺序表所占用的内存空间。
这些基本运算是实现顺序表数据结构的基础,通过它们可以实现顺序表的各种操作和应用。在实际应用中,可以根据具体需求和数据特点来选择和设计合适的顺序表操作算法。(一下是整体的功能)
3.顺序表的实现
1,.首先导入需要使用的函数库第三个库可有可无(主要因为是颜色渲染)
2.定义好数据类型(我这边是以学生管理为主题)
3.上代码首先是初始化顺序表给书序表申请一块Student结构体*顺序表size的大小的内存空间,
再给顺序表L的属性初始化。
4.插入元素我们差run一般都是从尾部插入,如果内存不够就得重新申请一块内存空间(就是扩容)
扩容代码如下
如果有足够的内存空间的话直接插入直接修改元素
整体效果(我们绿色的字体是调用了windows函数库)
5.删除元素,按照指定下标删除元素元素位置往后移(也有一个删除最后一个元素的函数,因为时间关系没有加上去)
这是删除最后一个元素的函数
6.判断顺序表是否为空,这个比较简单直接看顺序表的长度是否为0
7.顺序表是否已满这个也比较简单,直接查看顺序表当前的长度是否大于等于常初始化常量值
8.(重点)遍历顺序表,把顺序表插入的每个学生都显示出来。通过循环顺序表来实现
代码逻辑
因技术有限不是很熟悉C语言字符串规则所以这个name有问题其他数据正常显示
9.查询指定的元素,通过输入学生信息来和顺序表里面的数据做对比如果num学号和age年龄和身高和体重都一样代表有该元素(因为技术问题没有对比name姓名)
这个有元素之后的结果
10.查询顺序表有多少元素,实现逻辑就是求顺序表的长度
11.帮助
4.完整demo
代码如下:
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#define LIST_INIT_SIZE 5
#define LIST_INCREMENT 2
typedef struct {
char name[10];
int num;
int age;
int height;
int weight;
}Student;
typedef struct {
Student *stu; // 每个数组元素的数据类型
int length; // 一共有多少个学生
int listsize; // 整个顺序表的长度
}SqList;
// 初始化一个顺序表
int initList(SqList *L){
// 1.申请一个空间
L->stu = (Student *)malloc(LIST_INIT_SIZE * sizeof(Student));
// 2.判断是否拿到了空间内存
if(!L->stu) exit(-1);
// 3.如果拿到了内存空间,就需要初始化顺序表
L->length = 0;
L->listsize = LIST_INIT_SIZE;
return 1;
}
// 销毁顺序表
int deleteList(SqList *L){
// 1.判断顺序表是否存在
if(L->stu == NULL) return 0;
// 2.如果存在,则释放对应的内存
free(L->stu);
// 3.释放内存之后,要恢复表的初始值
L->length = 0;
L->listsize = 0;
return 1;
}
// 遍历顺序表
void findAllList(SqList *L){
int i = 0;
if(L==NULL){
printf("顺序表没有学生");
}
for(i = 0; i < L->length; i++){
printf("num=%2d,name=%s,age=%d, height=%d, weight=%d \n",L->stu[i].num,L->stu[i].name, L->stu[i].age, L->stu[i].height, L->stu[i].weight);
}
}
// 查找数组中的某个元素,如果查找到某个元素,将返回1,否则返回0
int findOneList(SqList *L, Student *stu){
int i = 0;
while(i < L->length){
if((L->stu[i].num==stu->num &&L->stu[i].age == stu->age) && (L->stu[i].height == stu->height) && (L->stu[i].weight == stu->weight)) return 1;
i ++;
}
return 0;
}
// 打印成员信息
void displayValue(Student *stu){
if(!stu) return;
printf("num=%2d,name=%2s,age=%d, height=%d, weight=%lf\n", stu->num,stu->name,stu->age, stu->height, stu->weight);
}
// 扩大数组的长度
int extantList(SqList *L){
// 1.重新申请内存
Student *p = (Student *)realloc(L->stu, (L->listsize + LIST_INCREMENT)*sizeof(Student));
// 2.判断是否申请到了这个内存
if(!p) exit(-1);
// 如果申请到了内存,就要更新顺序表的信息
L->stu = p;
L->listsize += LIST_INCREMENT;
return 1;
}
// 元素复制
void copyValue(Student *s1, Student *s2){
s1->age = s2->age;
s1->height = s2->height;
s1->weight = s2->weight;
s1->name[10]=s2->name[10];
s1->num=s2->num;
}
// 在顺序表的尾部插入元素
int insertLastList(SqList *L, Student *s){
// 1.如果顺序表已经满了,就需要重新申请空间
if(L->length >= L->listsize) extantList(L);
// 2.有足够空间,在尾部插入新元素即可
copyValue(&L->stu[L->length], s);
// 3.如果新元素插入,需要更新成员数量
L->length ++;
}
// 在顺序表的指定位置插入
int insertLocList(SqList *L, int i, Student *e){
// 1.判断插入位置是否合法
if(i < 0 || i > L->length-1) return 0;
// 2.判断表是否有空余空间,如果没有,扩大表长
if(L->length >= L->listsize) extantList(L);
// 3.先将要插入的元素位置后面的所有元素向后移动一个位置
int j;
for(j = L->length; j > i; j --){
copyValue(&L->stu[j], &L->stu[j-1]);
}
// 4.插入元素
copyValue(&L->stu[i], e);
// 5.更新表中的信息
L->length ++;
return 1;
}
//查询顺序表个数
int length(SqList *L)
{
return L->length;
}
// 在指定位置删除元素
int ListDelete(SqList *L, int index) {
if (index < 1 || index > L->length) {
return 0; // 删除位置不合法
}
int i;
for ( i = index; i < L->length; i++) {
L->stu[i - 1] = L->stu[i]; // 将元素前移
}
L->length--; // 长度减1
return 1; // 删除成功
}
// 删除最后一个元素
int ListDeleteLast(SqList *L) {
if (L->length == 0) {
return 0; // 顺序表为空,无法删除元素
}
int i;
for ( i = L->length - 1; i > 0; i--) {
L->stu[i] = L->stu[i - 1]; // 将元素后移
}
L->length--; // 长度减1
return 1; // 删除成功
}
//判断顺序表是否为null
int empty(SqList *L)
{
return (L->length == 0)?1:0;
}
//查看顺序表是否满
int full(SqList *L)
{
return (L->length == LIST_INIT_SIZE)?1:0;
}
int main(){
HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
SqList L;
Student stu;
int num;
do{
SetConsoleTextAttribute(hConsole, 0x7);
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("10. 帮助\n");
printf("9.销毁顺序表\n");
printf("0. 退出\n");
printf("请输入您要进行的操作(1-6,0退出):");
scanf("%d",&num);
switch(num){
case 1: if(initList(&L)){
SetConsoleTextAttribute(hConsole, 0xa);
printf("顺序表初始化成功\n");
}break;
case 2:
printf("请输入要插入的学号、姓名、身高、体重\n");
printf("请输入学号:");
scanf("%d",&stu.num);
printf("请输入姓名:");
scanf("%s",&stu.name);
printf("请输入年龄:");
scanf("%d",&stu.age);
printf("请输入身高:");
scanf("%d",&stu.height);
printf("请输入体重:");
scanf("%d",&stu.weight);
if(insertLastList(&L,&stu)){
SetConsoleTextAttribute(hConsole, 0xa);
printf("学生%s插入成功\n",stu.name);
}
break;
case 3:
printf("请输入你要删除的元素");
int i;
scanf("%d",&i);
if(ListDelete(&L,i)){
SetConsoleTextAttribute(hConsole, 0xa);
printf("删除成功\n");
}
break;
case 4: if(empty(&L)==1){
SetConsoleTextAttribute(hConsole, 0x6);
printf("顺序表为空\n");
} else{
SetConsoleTextAttribute(hConsole, 0x6);
printf("顺序表还有\n",length(&L));
}
break;
case 5: if(full(&L)==1){
SetConsoleTextAttribute(hConsole, 0x4);
printf("顺序表已满\n");
}else{
SetConsoleTextAttribute(hConsole, 0x6);
printf("顺序表未满\n");
}
break;
case 6:findAllList(&L);break;
case 7:
printf("请输入学生信息查询是否有该学生(因为技术有限就不比较学生姓名了)\n");
printf("请输入学号:");
scanf("%d",&stu.num);
printf("请输入年龄:");
scanf("%d",&stu.age);
printf("请输入身高:");
scanf("%d",&stu.height);
printf("请输入体重:");
scanf("%d",&stu.weight);
if(findOneList(&L,&stu)==1){
SetConsoleTextAttribute(hConsole, 0x6);
printf("有该学生\n");
} else{
SetConsoleTextAttribute(hConsole, 0x3);
printf("没有该学生信息\n");
}
break;
case 8:
SetConsoleTextAttribute(hConsole, 0x6);
int num=length(&L);
printf("顺序表个数有%d个\n",num);break;
case 9:if(deleteList==1){
SetConsoleTextAttribute(hConsole, 0xa);
printf("顺序表已销毁\n");
break;
}
case 10:
printf("本产品就是一个C语言模拟学生管理系统的顺序表,bug很多\n");
}
}while(num!=0);
}
5.小结
本次实验掌握了顺序表如何实现,也了解到C语言的一些库函数的使用
6.参考文献
多去B站学习,了解更多数据结构相关的知识