zoukankan      html  css  js  c++  java
  • 一段充满血与泪的代码(链表的一些基本操作)

    别问为什么充满血与泪,问就是我菜

    以下代码主要是通过学习B站UP主C3程序猿课程学来的。

    #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);//头部插入结点 
    struct student* search(int idtemp);
    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;
        printf("请输入学生总数:
    ");
        int i,n;
        scanf("%d",&n);
        printf("请按顺序输入学生的id,姓名,分数,中间空格隔开
    ");
        for(i=1;i<=n;i++){
            scanf("%d",&id);
            scanf("%s",name);
            scanf("%f",&score);
            tillinsert(id,name,score);
        }
        print();
        printf("从头部插入结点,请输入数据:
    ");
        scanf("%d",&id);
        scanf("%s",name);
        scanf("%f",&score);
        headinsert(id,name,score);
        print();
        printf("从尾部插入结点,请输入数据:
    ");
        scanf("%d",&id);
        scanf("%s",name);
        scanf("%f",&score); 
        tillinsert(id,name,score);
        print();
        printf("输入一个结点的id,查询该结点内容:
    ");
        int idtemp;
        scanf("%d",&idtemp);
        struct student* pp;
        pp=search(idtemp);
        printf("id:%d   name:%s   score:%f
    ",pp->id,pp->name,pp->score);
        printf("从任意一个前插入新的结点,请输入该结点中id:
    ");
        scanf("%d",&idtemp);
        printf("请输入要插入结点中的数据:
    ");
        scanf("%d",&id);
        scanf("%s",name);
        scanf("%f",&score);
        nodeinsert(id,name,score,idtemp);
        print();
        printf("请输入所要删除的结点的id:
    ");    
        scanf("%d",&id);
        deletenode(id);
        print();
    } 
    //从尾部插入结点 
    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("该链表的信息目前为:
    ");
        while(p!=NULL){
            printf("id:%d   name:%s   score:%f
    ",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; 
        }
    } 
    //查询指定结点,返回值为指针类型
    struct student* search(int idtemp){
        struct student*ptemp=head;
        while(ptemp!=NULL){
            if(ptemp->id==idtemp){
                return ptemp;
            }
        ptemp=ptemp->next; 
      }
      if(ptemp==NULL){
          printf("未找到指定结点
    ");
          return NULL;
      }     
    } 
    //从一个结点前插入新的结点 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("该结点不存在
    ");
            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("该链表为空
    ");
            return;
        }
        //查询是否有该结点 
        struct student* p=head;
        while(p!=NULL){
            if(p->id==id){
                break;
            }
            p=p->next; 
        }
        if(p==NULL){
            printf("未找到此结点
    ");
            return; 
        }
        //第一种情况 只有一个结点
        if(head==end){
            deletehead();
        }
        //有两个结点,所要删除的结点为头尾结点中的一个(主要是删除头尾结点的算法不同,因此需要分情况讨论) 
        else if(head->next==end){
            if(head->id==id){
                deletehead();
            } 
            else{
                deletetill(); 
            }
        } 
        //有多个结点 
        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);
            }
        }  
    } 
    人生如逆旅,我亦是行人
  • 相关阅读:
    vue router 中 mode和base
    C# 迭代器、枚举器、IEnumerable和IEnumerator
    C#单例模式(Singleton Pattern)
    C#设计模式
    C# UML图符号的含义
    C#设计模式-迭代器模式
    IQueryable<T>和表达式树
    .NET IEnumerable和IEnumerator
    C#基础知识之const和readonly关键字
    C#基础知识之base、this、new、override、abstract梳理
  • 原文地址:https://www.cnblogs.com/sz2003/p/14139275.html
Copyright © 2011-2022 走看看