目录
前言
本篇文章记录本人在数据结构学习过程中学完线性表的链式存储实现的一个小小实操,用链表的方式实现了学生管理系统,可以通过增删改查的基本操作对学生的信息进行操作。下面本人将把本人的代码展示在文章后面。(注:本人使用Dev c++可以完美运行,其他编译器运行有问题可以自己找找原因。)
一、链表是什么?
链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行时动态生成。每个结点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域。 相比于线性表顺序结构,操作复杂。由于不必须按顺序存储,链表在插入的时候可以达到O(1)的复杂度,比另一种线性表顺序表快得多,但是查找一个节点或者访问特定编号的节点则需要O(n)的时间,而线性表和顺序表相应的时间复杂度分别是O(logn)和O(1)。
二、代码实现学生管理系统
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//学生结构体
typedef struct{
char name[10];//用字符型数组保存学生姓名
int age;//int型保存学生年龄
}Student;
//结点
typedef struct LNode{
Student data;//节点数据域保存学生信息
LNode *next;//指向该节点类型指针,用于指向下一节点
}LNode,*LinkList;
//初始化
bool InitL(LinkList &L){
L=(LNode*)malloc(sizeof(LNode));//为头节点分配空间
L->next=NULL;//头结点next指针置空
return true;
}
//查找第i个结点
LNode* GetE(LinkList L,int i){
if(i<1)//检查i值是否合法
return NULL;
LNode *p=L->next;//头结点为0号节点,这句语句使p指向第一个节点
int j=1;//用于记录p指向的节点位置
while(p!=NULL && j<i){
p=p->next;//指针p后移
j++;//指针所在位置加1
}
if(p==NULL){
printf("非法输入!输入的值大于表长\n");
return NULL;
}
return p;
}
//查找指定位置学生信息
bool GetStu(LinkList L,int i){
if(L->next==NULL){
printf("该学生表为空\n");
return false;
}
LNode *p=GetE(L,i);
printf("该学生信息为:\n");
printf("姓名:%s\n",p->data.name);
printf("年龄:%d\n",p->data.age);
return true;
}
//头插操作
bool InsertE(LinkList &L,int i,Student e){
LNode *s=(LNode*)malloc(sizeof(LNode));
s->data.age=e.age;
strcpy(s->data.name,e.name);//数组赋值函数
s->next=L->next;
L->next=s;
printf("学生添加成功\n");
return true;
}
//删除数据元素——学生信息
bool DeleteE(LinkList &L,int i){
if(i<1)
return false;
LNode *p=L->next;
if(i==1){
L->next=p->next;
printf("第1个学生信息删除成功!\n");
return true;
}
p=GetE(L,i-1);
LNode *q=p->next;
p->next=q->next;
free(q);
printf("第%d个学生信息删除成功!\n",i);
return true;
}
//打印学生信息
bool PrintL(LinkList L){
LNode *p=L;
if(p->next==NULL){//判空
printf("当前学生表为空\n");
return false;
}
printf("表内现有的学生信息为:\n");
while(p->next!=NULL){//若不为空,依次打印表中学生信息
p=p->next;//实现指针依次后移
printf("姓名:%s\n",p->data.name);
printf("年龄:%d\n",p->data.age);
}
return true;
}
//菜单
void menu(){
printf("==============功能列表=============\n");
printf("1.添加学生\n");
printf("2.查找学生\n");
printf("3.删除学生\n");
printf("4.打印\n");
printf("===================================\n");
}
int main(){
LinkList L;
InitL(L);
int x;
while(1){
menu();
printf("请输入你要进行的操作:\n");
scanf("%d",&x);
switch(x){//通过swich()函数来进行对操作的选择
case 1:{
Student e;
printf("请输入学生姓名:\n");
scanf("%s",e.name);
printf("请输入学生年龄:\n");
scanf("%d",&e.age);
InsertE(L,1,e);
break;
}
case 2:{
int i;
printf("请输入学生在表中所在位置:\n");
scanf("%d",&i);
GetStu(L,i);
break;
}
case 3:{
int i;
printf("请输入你要删除的学生所在位置:\n");
scanf("%d",&i);
DeleteE(L,i);
break;
}
case 4:{
PrintL(L);
break;
}
}
}
return 0;
}
三、运行结果
往学生表添加两名学生,小明和张三,然后尝试各种操作
总结
本次实现仅简单实现了增加、删除、查找和遍历打印的操作,有其他操作需求的朋友可以留言,这边会持续更新,当然大家也可以在理解的基础上自己动手操作。
通过本次的实现感觉自己对链表的掌握更深了,理解了链表是如何通过指针相互联系起来的,在实操中第一次也是出了一些bug,但花了两个多小时调试修改之后代码总算可以按照预想的实现,在这个过程中也是收获满满。