(大一萌新必看!)一些关于 链表 的理解 和 简易管理系统

苦读诗书后理解的链表内容,真的很有用!精华满满全程无尿点!

链表的构成是学生的姓名、学号、成绩(为求简化,只选择三项)

链表的理解

主要目的实现链表的基本功能:   增、删、改、查;

增:头插法或者尾插法构建链表;

(本人认为链表的构建,主要就是构建一个带着数据和指针的结构体,数据部分储存需要的数据,然后通过改变指针的指向,来将多个储存在计算机内存不同位置的结构体数据串联起来)

第一步:初始化链表

定义首元结点,头结点存储数据为空,指针指向首元结点

//链表的初始化
LinkList InitList()
{
	LinkList head;//头结点变量
	head = (Node*)malloc(sizeof(Node));//动态分配内存
	head -> next = NULL;//头结点指针域为空
	return head;//返回头结点地址,即头指针
}
头插法

如果是头插法,其主要目的就是不断添加在首元结点和头结点之间;因此,改变指针指向的思路便是--新构建的结点指针指向应该是原来头结点指针所指向的结点地址,此时此刻,头结点和新建结点所指向的应该是同一个结点(这只是我本人的个人观点,没有在代码中验证过,只是单纯的理论分析,小白,勿伤);因此下一步需要改变头结点指针指向,指向新建结点,实现头插法添加。

//头插法创建链表
void CreateByHead(LinkList head)
{
	Node *s;
	char name[20];
	int number;
	printf("请输入学生的姓名、学号\n");
	while(1){
		scanf("%s",name);
		scanf("%d",&number);
		if(number==0){
			break;
		}
		s = (Node*)malloc(sizeof(Node));
		strcpy(s->name,name);
		s->number = number;
		s->next = head->next;//新建结点指向原来的首元结点
		head -> next = s; //链表的头结点指向新建结点
	} 
 } 
尾插法

如果是尾插法,则其主要目的就是不断添加在尾节点之后,其后永远链接着NULL(空指针),因此构建链表的主要思路就是--尾结点的指针指向永远是新创建结点的地址,(听起来比头插法少一点,其实实际体验下来,并没有差多少,甚至问哦个人觉得没有头插法方便)

由于现在不是头结点同时需要不断变换,所以尾插法需要声明两个结构体指针,一个用来构建新结点,另一个则用来表示插入前的尾结点。

在尾结点的指针指向新建结点后,此时的尾结点就应该是新建结点了,所以将新建结点的地址赋给用来纸指向“尾结点”的机构体指针,最后在循环外将尾结点储存的指针指向NULL。

//尾插法构建链表
void CreatByRear(LinkList head){
	Node *r,*s;
	char name[20];
	int number;
	r = head;
	printf("请输入学生的姓名学号:\n");
	while(1){
		scanf("%s",name);
		scanf("%d",&number);
		if(number == 0){
			break;
		}
		s = (Node*)malloc(sizeof(Node));
		strcpy(s->name,name);
		s->number = number;
		r->next = s;//原来的尾结点指向新建结点
		r = s;//r指向新结点(r指向链表末尾)
	}
	
	r->next = NULL;//尾结点的指针为空
} 

删:顾名思义删除结点

指针区别于数组,就在于它的储存并不是按照一定顺序,而是依靠指针来构成连接;

明白这点后就可以很简单的知道链表的删除了!

使用查找找到需要删除的结点后,将前结点指针指向后结点将这个结点跳过去随后释放结点

//单链表的删除
 void Delete(LinkList head,int pos){
 	Node *p = head,*q;//q用来释放内存
 	int j=0;
 	printf("**********删除第%d个学生***************\n",pos);
	 while(p&&j<pos-1){ // 通过循环找到pos-1个结点,可以改变为姓名查找
	 	p=p->next;
		j++; 
	 } 
	 if(p==NULL||p->next==NULL){//第pos个结点不存在
	 	printf("the pos is error");
	 }else {
	 	q = p->next;//q指向第pos个结点
	 	p->next = q->next;//连接删除结点两边的结点
		 free(q); //释放要删除的结点
	 }
 	
 }

改:就是找到目标结点后修改数据

改本身没什么可说的,重点其实是在查上面

//偷个小懒,就使用管理系统中的删除操作了
void change(LinkList head,char name[]){
        LinkList p;
        p = head->next;
        while(p)
        {
                if(strcmp(p->name,name)!=0) p = p->next;
                else break;
        }
        
        if(p==NULL){
                printf("查无此人,操作失败\n");
        }else {
                printf("输入修改后的学生姓名、学号、成绩\n");
                scanf("%s%d%d",p->name,&p->number,&p->score);
        }
}

查:个人认为是很有的说的一点

首先就是最重要的一点,查找操作返回的是结构体指针!!!!目的就是找到后方便操作

废话不多说,上!代!码!

(摸鱼好爽,所以我还选择用操作系统里的代码)

STD *search(LinkList head,char name[]){
        LinkList s;
        s = head->next;
        while(s)
        {
                if(strcmp(s->name,name)!=0) s= s->next;
                else break;
        }
        if(s == NULL) printf("没有找到");
        return s;
}

查找本身没什么说道的,重点还是与其他功能的联合操作

其他操作:显示,升降序排序

显示:很简单的操作,只需要定义一个结构体指针,指向首元结点,然后打印其中的数据部分,随后指针后移,直到指向空指针NULL

3  2   1 上代码!!!

void OutPut(LinkList head){
        LinkList p;
        p = head->next;
        while(p){
                printf("%s %d %d\n",p->name,p->number,p->score);
                p = p->next;
        }
}

排序:原有知识的再运用

其实就是原有的数组的排序方法(原谅小编最擅长简单粗暴的冒泡排序),在链表中使用,如有改变,修改指针指向便可,麻烦的就是寻找前后结点

这里以升序演示,降序就是大小换换位置而已

void paixuS(LinkList head){
        
        LinkList p ,s;
        int cnt = jishu(head);
        for(int i=0;i<cnt;i++){
                LinkList z = head;
                
                p = z->next;
                //找到对比项前一项
                 //p是对比项,s是下一项,z是上一项 
                while(p&&p->next){
                        s = p->next;
                        if(p->score>s->score){
                                z->next = p->next;
                                p->next = s->next;
                                s->next = p;
                        }//大的项往后排
                        z = z->next;//顺位后移 
                        p = z->next;
                }
        }
        printf("排序后结果如下:\n");
}

第一版:

没有联系文件打印,只是使用链表

主要实现的功能是

************************************************************

1) 输入学生成绩

2) 删除学生信息

3) 修改学生信息

4) 查找学生信息

5) 显示数据

6) 按升序排列学生信息

7) 按降序排序学生信息

8)从文件中读取数据存入链表

0) 退出

***********************************************************

代码如下

#include<stdio.h>
#include<stdlib.h>
#include<string.h>

typedef struct student
{
        char name[30];
        int number;
        int score;
        struct student *next;
}STD,*LinkList;


void OutPut(LinkList head);
LinkList chu();
void CreateByHead(LinkList head);
void Out(LinkList head);
STD *search(LinkList head,char name[]);
void change(LinkList head,char name[]);
void Delete(LinkList head,int i);
int jishu(LinkList head);
void menu();
void paixuS(LinkList head); 
void paixuJ(LinkList head);


int main()
{
        menu();
        LinkList ha;
        ha = chu();
        
        int a;
        scanf("%d",&a);
        while(1){
                if(a==1){
                        CreateByHead(ha);
                }else if(a==2){
                        printf("请输入需要修删除第几个学生信息\n");
                        int k;
                        scanf("%d",&k);
                        Delete(ha,k);
                }else if(a==3){
                        printf("请输入需要修改信息的学生姓名\n");
                        char name[30];
                        scanf("%s",name);
                        change(ha,name);
                }else if(a==4){
                        printf("请输入查找学生的姓名\n");
                        char name[30];
                        scanf("%s",name);
                        STD *m = search(ha,name);
                        printf("%s %d %d\n",m->name,m->number,m->score);
                }else if(a==0){
                        break;
                }else if(a==5){
                        OutPut(ha);
                }else if(a==6){
                        paixuS(ha);
                        OutPut(ha);
        //成绩升序排列 
                }else if(a==7){
                        paixuJ(ha);
                        OutPut(ha);
                }
                
                scanf("%d",&a);
        }        


        
        
        int cnt;
        cnt = jishu(ha);
        STD std[100];
        LinkList p = ha->next;
        for(int i=0;i<cnt;i++){
                std[i].number = p->number;
                std[i].score = p->score;
                strcpy(std[i].name,p->name);
                
                p = p->next;
        }
        
        FILE *fp;
        fp = fopen("c:\\text\\lian.txt","wb");
        if(fp==NULL){
                printf("文件打开失败\n");
                return 0; 
        }else {
                for(int i=0;i<cnt;i++){
                        printf("%s %d %d\n",std[i].name,std[i].number,std[i].score);
                        fprintf(fp,"%s %d %d\n",std[i].name,std[i].number,std[i].score);
                }

        }
        fclose(fp);
        return 0;
}


LinkList chu()
{
        LinkList head;
        head = (STD*)malloc(sizeof(STD));
        head -> next = NULL;
        return head;
}

void CreateByHead(LinkList head)
{
        LinkList s;
        char name[30];
        int number;
        int score;
        printf("请输入学生姓名、学号、成绩\n");
        while(1)
        {
                scanf("%s%d%d",name,&number,&score);
                if(number==0){
                        printf("结束输入\n");
                        break;
                }
                
                s = (STD*)malloc(sizeof(STD));
                strcpy(s->name,name);
                s->number = number;
                s->score = score;
                
                s->next = head->next;
                head->next = s;
        }
}

void Out(LinkList head){
        LinkList p;
        p = head->next;
        printf("学生成绩如下\n");
        while(p)
        {
                printf("%d %s %d\n",p->number,p->name,p->score);
                p = p->next;
        }
}

STD *search(LinkList head,char name[]){
        LinkList s;
        s = head->next;
        while(s)
        {
                if(strcmp(s->name,name)!=0) s= s->next;
                else break;
        }
        if(s == NULL) printf("没有找到");
        return s;
}

void change(LinkList head,char name[]){
        LinkList p;
        p = head->next;
        while(p)
        {
                if(strcmp(p->name,name)!=0) p = p->next;
                else break;
        }
        
        if(p==NULL){
                printf("查无此人,操作失败\n");
        }else {
                printf("输入修改后的学生姓名、学号、成绩\n");
                scanf("%s%d%d",p->name,&p->number,&p->score);
        }
}

void Delete(LinkList head,int i){
        LinkList p=head,s;
        int j=0;
        while(p&&j<i-1){
                p = p->next;
                j++;
        }
        if(p==NULL||p->next==NULL){
                printf("ERROR\n");
        }else{
                s = p->next;
                p->next = s->next;
                free(s);
        }
        
}

int jishu(LinkList head){
        int cnt = 0;
        LinkList p;
        p = head->next;
        while(p){
                cnt++;
                p = p->next;
        }
        return cnt;
}


void menu(){
        printf("***********学生信息管理系统**************\n");
        printf("1) 输入学生成绩\n2)  删除学生信息\n3)  修改学生信息\n4)  查找学生信息\n5)  显示\n6)  按升序排列学生信息\n7)  按降序排序学生信息\n0)  退出\n");
        
}

void OutPut(LinkList head){
        LinkList p;
        p = head->next;
        while(p){
                printf("%s %d %d\n",p->name,p->number,p->score);
                p = p->next;
        }
}

void paixuS(LinkList head){
        
        LinkList p ,s;
        int cnt = jishu(head);
        for(int i=0;i<cnt;i++){
                LinkList z = head;
                
                p = z->next;
                //找到对比项前一项
                 //p是对比项,s是下一项,z是上一项 
                while(p&&p->next){
                        s = p->next;
                        if(p->score>s->score){
                                z->next = p->next;
                                p->next = s->next;
                                s->next = p;
                        }//大的项往后排
                        z = z->next;//顺位后移 
                        p = z->next;
                }
        }
        printf("排序后结果如下:\n");
}

void paixuJ(LinkList head){
        LinkList p ,s;
        int cnt = jishu(head);
        for(int i=0;i<cnt;i++){
                LinkList z = head;

                p = z->next;
             
                while(p&&p->next){
                        s = p->next;
                        if(p->score<s->score){
                                z->next = p->next;
                                p->next = s->next;
                                s->next = p;
                        }
                        z = z->next;
                        p = z->next;
                }
        }
        printf("排序后结果如下:\n");
}

对于删除功能的优化

对于查找第几个学生,这种操作属实鸡肋,因此优化为按照姓名查找

主要思路:

输入姓名后,使用strcmp()函数进行比较,寻找。

如果当指向空指针,则没有找到,输出 “ 查无此人 ”。

代码如下(简短代码)

#include<stdio.h>
#include<stdlib.h>
#include<string.h>

typedef struct student{
        char name[30];
        int score;
        struct student *next;
}STD,*LinkList;

LinkList chu();
void CreateByHear(LinkList head);
void OutPut(LinkList head);
STD *Search(LinkList head,char name[]);
void Delete(LinkList head,char name[]);


int main()
{
        LinkList ha;
        ha = chu();
        CreateByHear(ha);
        OutPut(ha);
        printf("ÇëÊäÈëÐÕÃû\n");
        char na[30];
        scanf("%s",na);
//        LinkList p = Search(ha,na);
//        printf("%s %d",p->name,p->score);
//查找

        Delete(ha,na);
        OutPut(ha); 
}

LinkList chu(){
        LinkList head;
        head = (STD*)malloc(sizeof(STD));
        head ->next = NULL; 
        return head; 
}

void CreateByHear(LinkList head){
//尾插法创建链表 
        LinkList p,s;
        p = head;
        
        char name[30];
        int score;
        printf("请输入学生信息\n");
        while(1)
        {
                scanf("%s %d",name,&score);
                if(score==0){
                        break;
                }
                s = (STD*)malloc(sizeof(STD));//动态分配内存
        
                strcpy(s->name,name);
                s->score = score;
                
                p->next = s;
                p = s;
                
        }
        p->next = NULL;
        
}


void OutPut(LinkList head){
        LinkList p = head->next;
        while(p){
                printf("%s %d\n",p->name,p->score);
                p = p->next;
        }
}

STD*  Search(LinkList head,char name[]){
        LinkList p;
        p = head->next;
        
        
        while(p){
                if(strcmp(p->name,name)!=0){
                        p = p->next;
                }else break;
        }
        if(p==NULL) printf("查无此人\n");
        
        return p;
}

void Delete(LinkList head,char name[]){
        LinkList p,r;
        r = head;
        p = r->next;
        //p是下一个结点 
        while(r->next){
                if(strcmp(p->name,name)!=0){
                        r = r->next;
                        p = r->next;
                        
                }else {
                        r->next = p->next;
                        free(p);
                        break;
                }
        }
        
        if(p==NULL) printf("查无此人\n");
}

第二版

由于第一版使用链表输出内容没有办法储存,因此使用文件,选择将链表内存储的数据,打印到txt文件里,便于整理数据,提高实用性

同时添加了把文件的数据传入链表中进行操作的功能,进一步增强实用性

***********************实用主义万岁!!!!!!!*********************

与文件联合

代码如下

#include<stdio.h>
#include<stdlib.h>
#include<string.h>

typedef struct student
{
        char name[30];
        int number;
        int score;
        struct student *next;
}STD,*LinkList;


void OutPut(LinkList head);
LinkList chu();
void CreateByHead(LinkList head);
void Out(LinkList head);
STD *search(LinkList head,char name[]);
void change(LinkList head,char name[]);
void Delete(LinkList head,int i);
int jishu(LinkList head);
void menu();
void paixuS(LinkList head); 
void paixuJ(LinkList head);
void Daoru(LinkList head);
void Cun(LinkList head,STD std[],int n);


int main()
{
        menu();
        LinkList ha;
        ha = chu();
        
        int a;
        scanf("%d",&a);
        while(1){
                if(a==1){
                        CreateByHead(ha);
                }else if(a==2){
                        printf("请输入需要修删除第几个学生信息\n");
                        int k;
                        scanf("%d",&k);
                        Delete(ha,k);
                }else if(a==3){
                        printf("请输入需要修改信息的学生姓名\n");
                        char name[30];
                        scanf("%s",name);
                        change(ha,name);
                }else if(a==4){
                        printf("请输入查找学生的姓名\n");
                        char name[30];
                        scanf("%s",name);
                        STD *m = search(ha,name);
                        printf("%s %d %d\n",m->name,m->number,m->score);
                }else if(a==0){
                        break;
                }else if(a==5){
                        OutPut(ha);
                }else if(a==6){
                        paixuS(ha);
                        OutPut(ha);
        //成绩升序排列 
                }else if(a==7){
                        paixuJ(ha);
                        OutPut(ha);
                }else if(a==8){
                    Daoru(ha);
                }
                
                scanf("%d",&a);
        }        


        
        
        int cnt;
        cnt = jishu(ha);
        STD std[100];
        LinkList p = ha->next;
        for(int i=0;i<cnt;i++){
                std[i].number = p->number;
                std[i].score = p->score;
                strcpy(std[i].name,p->name);
                
                p = p->next;
        }
        
        FILE *fp;
        fp = fopen("c:\\text\\lian.txt","wb");
        if(fp==NULL){
                printf("文件打开失败\n");
                return 0; 
        }else {
                for(int i=0;i<cnt;i++){
                        printf("%s %d %d\n",std[i].name,std[i].number,std[i].score);
                        fprintf(fp,"%s %d %d\n",std[i].name,std[i].number,std[i].score);
                }

        }
        fclose(fp);
        return 0;
}


LinkList chu()
{
        LinkList head;
        head = (STD*)malloc(sizeof(STD));
        head -> next = NULL;
        return head;
}

void CreateByHead(LinkList head)
{
        LinkList s;
        char name[30];
        int number;
        int score;
        printf("请输入学生姓名、学号、成绩\n");
        while(1)
        {
                scanf("%s%d%d",name,&number,&score);
                if(number==0){
                        printf("结束输入\n");
                        break;
                }
                
                s = (STD*)malloc(sizeof(STD));
                strcpy(s->name,name);
                s->number = number;
                s->score = score;
                
                s->next = head->next;
                head->next = s;
        }
}

void Out(LinkList head){
        LinkList p;
        p = head->next;
        printf("学生成绩如下\n");
        while(p)
        {
                printf("%d %s %d\n",p->number,p->name,p->score);
                p = p->next;
        }
}

STD *search(LinkList head,char name[]){
        LinkList s;
        s = head->next;
        while(s)
        {
                if(strcmp(s->name,name)!=0) s= s->next;
                else break;
        }
        if(s == NULL) printf("没有找到");
        return s;
}

void change(LinkList head,char name[]){
        LinkList p;
        p = head->next;
        while(p)
        {
                if(strcmp(p->name,name)!=0) p = p->next;
                else break;
        }
        
        if(p==NULL){
                printf("查无此人,操作失败\n");
        }else {
                printf("输入修改后的学生姓名、学号、成绩\n");
                scanf("%s%d%d",p->name,&p->number,&p->score);
        }
}

void Delete(LinkList head,int i){
        LinkList p=head,s;
        int j=0;
        while(p&&j<i-1){
                p = p->next;
                j++;
        }
        if(p==NULL||p->next==NULL){
                printf("ERROR\n");
        }else{
                s = p->next;
                p->next = s->next;
                free(s);
        }
        
}

int jishu(LinkList head){
        int cnt = 0;
        LinkList p;
        p = head->next;
        while(p){
                cnt++;
                p = p->next;
        }
        return cnt;
}


void menu(){
        printf("***********学生信息管理系统**************\n");
        printf("1) 输入学生成绩\n2)  删除学生信息\n3)  修改学生信息\n4)  查找学生信息\n5)  显示\n6)  按升序排列学生信息\n7)  按降序排序学生信息\n8)从文件中读取数据存入链表\n0)  退出\n");
        
}

void OutPut(LinkList head){
        LinkList p;
        p = head->next;
        while(p){
                printf("%s %d %d\n",p->name,p->number,p->score);
                p = p->next;
        }
}

void paixuS(LinkList head){
        
        LinkList p ,s;
        int cnt = jishu(head);
        for(int i=0;i<cnt;i++){
                LinkList z = head;
                
                p = z->next;
                //找到对比项前一项
                 //p是对比项,s是下一项,z是上一项 
                while(p&&p->next){
                        s = p->next;
                        if(p->score>s->score){
                                z->next = p->next;
                                p->next = s->next;
                                s->next = p;
                        }//大的项往后排
                        z = z->next;//顺位后移 
                        p = z->next;
                }
        }
        printf("排序后结果如下:\n");
}

void paixuJ(LinkList head){
        LinkList p ,s;
        int cnt = jishu(head);
        for(int i=0;i<cnt;i++){
                LinkList z = head;

                p = z->next;
             
                while(p&&p->next){
                        s = p->next;
                        if(p->score<s->score){
                                z->next = p->next;
                                p->next = s->next;
                                s->next = p;
                        }
                        z = z->next;
                        p = z->next;
                }
        }
        printf("排序后结果如下:\n");
}

void Cun(LinkList head,STD std[],int n)
{
        LinkList s,p = head;
        
        
        for(int i=0;i<n;i++){
                s = (STD*)malloc(sizeof(STD));
                strcpy(s->name,std[i].name);
                s->number = std[i].number;
                s->score = std[i].score;
                        
                p->next = s;
                p = s;
                        
        }
        p->next = NULL;
}

void Daoru(LinkList head)
{
        STD std[1000];
        FILE *fp;
        int n;
        printf("请输入学生数量:\n");
        scanf("%d",&n);
        
        fp = fopen("c:\\text\\lian.txt","r");
        for(int i=0;i<n;i++){
                fscanf(fp,"%s %d %d",std[i].name,&std[i].number,&std[i].score);
        }        
        
                
        Cun(head,std,n);
        OutPut(head);
        
        fclose(fp);//关闭文件
}

一些想法

目前来看该简易系统基本可以完成一些简易操作,譬如链表的增、删、改、查

目前来看,系统内存储的数据只有学生姓名,序号,以及总成绩

太过稀少,可以增加为 学生姓名,序号,语文,数学,英语,以及总成绩

总成绩是语数英三科成绩总和,同时,储存文件时排序按照总成绩升降排序

(单纯只是觉得这样排序的话实用性更好一点,毕竟实用万岁!L('ω')┘三└('ω')」) 

  • 23
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值