知交

链表操作(改)--学生管理

#include <stdio.h>
#include <stdlib.h>
#include<string.h>
#define N 100
void tillinsert(int id,char *name,float score);//尾部插入结点
void print();//输出链表全部信息 
void headinsert(int id,char *name,float score);//头部插入结点 
void nodeinsert(int id,char *name,float score,int idtemp);//从一个结点前插入 
void deletenode(int id);//删除结点
void deletehead();//删除头结点 
void deletetill(); //删除尾结点 
//创建结构体 
struct student{
    int id;
    char name[N];
    float score;
    struct student* next;
};
//初始化头尾结点 
struct student* head=NULL;
struct student* end=NULL;
//主函数 
int main(){
    int id;
    char name[N];
    float score;
    int m;
    printf("1.输入1,输入学生信息。\n2.输入2,从尾部插入一个节点。\n3.输入3,从头部插入一个结点。\n4.输入4,从一个指定结点前插入一个结点。\n5.输入5,删除一个指定结点。\n6.输入6,显示当前链表信息。\n7.输入7,退出程序。\n"); 
    while(m!=7){
    scanf("%d",&m); 
    if(m==1){
    printf("请输入学生总数:\n");
    int i,n;
    scanf("%d",&n);
    printf("请按顺序输入学生的id,姓名,分数,中间空格隔开\n");
    for(i=1;i<=n;i++){
        scanf("%d",&id);
        scanf("%s",name);
        scanf("%f",&score);
        tillinsert(id,name,score);
       }
    }
    if(m==2){
    printf("从头部插入结点,请输入数据:\n");
    scanf("%d",&id);
    scanf("%s",name);
    scanf("%f",&score);
    headinsert(id,name,score);
    }
    if(m==3){
    printf("从尾部插入结点,请输入数据:\n");
    scanf("%d",&id);
    scanf("%s",name);
    scanf("%f",&score); 
    tillinsert(id,name,score);
    }
    if(m==4){ 
    printf("从任意一个前插入新的结点,请输入该结点中id:\n");
    int idtemp;
    scanf("%d",&idtemp);
    printf("请输入要插入结点中的数据:\n");
    scanf("%d",&id);
    scanf("%s",name);
    scanf("%f",&score);
    nodeinsert(id,name,score,idtemp);
    } 
    if(m==5){
    printf("请输入所要删除的结点的id:\n");    
    scanf("%d",&id);
    deletenode(id);
    }
    if(m==6){
        print();
    }
    if(m!=7){
    printf("程序运行完毕,请进行下一步操作:\n");}
}
   return 0;
} 
//从尾部插入结点 
void tillinsert(int id,char *name,float score){
    //创建结点 开辟空间 
    struct student* p1=(struct student*)malloc(sizeof(struct student));
    //参量赋值 
    //由于字符数组的特殊性,采用strcpy函数来赋值 
    p1->id=id;
    strcpy(p1->name,name);
    p1->score=score;
    p1->next=NULL;        
    if(head==NULL||end==NULL){
        head=p1;
        end=p1; 
    } 
    else{
        end->next=p1;
        end=p1;
    }
}
//输出链表信息
void print(){
    struct student* p=head;
    printf("该链表的信息目前为:\n");
    while(p!=NULL){
        printf("id:%d   name:%s   score:%f\n",p->id,p->name,p->score);
        p=p->next;
    }
}
//头部插入结点
void headinsert(int id,char *name,float score){
    struct student* p2=(struct student*)malloc(sizeof(struct student));
    p2->id=id;
    strcpy(p2->name,name);
    p2->score=score;
    if(head==NULL||end==NULL){
        head=p2;
        end=p2; 
    }
    else{
      p2->next=head;
      head=p2; 
    }
} 
//从一个结点前插入新的结点 idtemp为所要插入的结点对应的id 
void nodeinsert(int id,char *name,float score,int idtemp){
    struct student* p3=head;
    //特殊情况:对应id为头结点的id,即刚好要插入头结点前
    if(p3->id==idtemp){
        headinsert(id,name,score);
        return;
    }
    //非特殊情况:先遍历查找指定位置 
    while(p3->next!=NULL){
        if(p3->next->id==idtemp){
            break; 
        }
        p3=p3->next;
    }
    //如若没有查找到指定结点 
    if(p3->next==NULL){
        printf("该结点不存在\n");
        return; 
    }
    //已经查找到指定结点,建立要插入的结点并赋值 
    struct student* ptemp=(struct student*)malloc(sizeof(struct student));
    ptemp->id=id;
    strcpy(ptemp->name,name);
    ptemp->score=score;
    //连接结点 
    ptemp->next=p3->next;
    p3->next=ptemp;  
} 
void deletehead(){//定义函数删除头结点,主要为后续删除结点做准备 
    struct student* ptemp=head;
    head=head->next;
    free(ptemp);
} 
void deletetill(){//删除尾结点,为后续删除结点做准备 
    //第一种情况下,只有一个结点 
      if(head==end){
          free(head);
        head=NULL;
        end=NULL; 
      }
    else{
        //找到尾巴前一个结点
        struct student* ptemp=head;//ptemp为尾巴前面的一个结点 
        struct student* pt=end;//pt为尾结点 
        while(ptemp->next!=end){
            ptemp=ptemp->next; 
        }
        end=ptemp;//尾巴前移
        free(pt);//释放旧的尾结点
        end->next=NULL; 
    }  
    
}
//删除结点
void deletenode(int id){
    //如果链表为空 
    if(head==NULL){
        printf("该链表为空\n");
        return;
    }
    //查询是否有该结点 
    struct student* p=head;
    while(p!=NULL){
        if(p->id==id){
            break;
        }
        p=p->next; 
    }
    if(p==NULL){
        printf("未找到此结点\n");
        return; 
    }
    //判断特殊情况, 即p是否为头尾结点中的一个 
    else if(p==head){
        deletehead();
    }
    else if(p==end){
        deletetill();
    }
    else{
    //非特殊情况,需要找到所删除结点的前一个结点
        struct student* ptemp=head;
        while(ptemp->next!=p){
            ptemp=ptemp->next;
        } 
        ptemp->next=p->next;
        free(p);
        }
}  
 
 

 

posted on 2020-12-19 12:53  知交  阅读(116)  评论(0编辑  收藏  举报

导航