单向链表之嵌套结构体的练习

现有学生的信息需要存储,学生信息包括:姓名、年龄、分数,利用单向表实现以下功能:

  1. 创建头结点

  2. 创建普通结点

  3. 单链表头插

  4. 单链表尾插

  5. 单链表的遍历

  6. 单链表的头删

  7. 单链表尾删

  8. 单链表按位置插入

  9. 单链表按位置删除

  10. 单链表按位置修改

  11. 单链表按位置查找

  12. 单链表按元素查找

  13. 单链表按元素修改

  14. 单链表按元素删除

  15. 单链表逆置

  16. 按成绩冒泡排序

  17. 单链表的释放

main.c

#include "main.h"

int main(int argc, char const *argv[])
{
    int n;
    linklist L = Create_Head();
    printf("请输入学生个数:");
    scanf("%d",&n);
    datatype e;
    printf("\n<-------------------------学生信息录入------------------------->\n\n");
    
#if 0

    for (size_t i = 0; i < n; i++)
    {
        printf("请输入第%ld名学生的姓名:",i+1);
        scanf("%s",e.name);
        printf("请输入第%ld名学生的年龄:",i+1);
        scanf("%d",&e.age);
        printf("请输入第%ld名学生的分数:",i+1);
        scanf("%lf",&e.score);
        Insert_Head(L,e);
        printf("\n");
    }

#else

    for (size_t i = 0; i < n; i++)
    {
        printf("请输入第%ld名学生的姓名:",i+1);
        scanf("%s",e.name);
        printf("请输入第%ld名学生的年龄:",i+1);
        scanf("%d",&e.age);
        printf("请输入第%ld名学生的分数:",i+1);
        scanf("%lf",&e.score);
        Insert_Rear(L,e);
        printf("\n");
    }

#endif

    OutputList(L);

    //链表头删
    printf("\n<-------------------------学生信息头删------------------------->\n\n");
    Delete_Head(L);
    OutputList(L);

    //链表尾删
    printf("\n<-------------------------学生信息尾删------------------------->\n\n");
    Delete_Rear(L);
    OutputList(L);

    //单链表按位置插入
    printf("\n<-------------------------学生信息按位置插入------------------------->\n\n");
    int pos;
    printf("请输入插入的位置:");
    scanf("%d",&pos);
    if(pos>=1 && pos<=L->len+1)
    {
        printf("请输入插入的学生的姓名:");
        scanf("%s",e.name);
        printf("请输入插入的学生的年龄:");
        scanf("%d",&e.age);
        printf("请输入插入的学生的分数:");
        scanf("%lf",&e.score);
        Insert_Position(L,pos,e);
        OutputList(L);
    }
    else
    {
        printf("\n插入位置不合法,操作失败!\n\n");
    }

    //单链表按位置删除
    printf("\n<-------------------------学生信息按位置删除------------------------->\n\n");
    printf("请输入删除的位置:");
    scanf("%d",&pos);
    Delete_Position(L,pos);
    OutputList(L);

    //单链表按位置修改
    printf("\n<-------------------------学生信息按位置修改------------------------->\n\n");
    printf("请输入修改的位置:");
    scanf("%d",&pos);
    if(pos>=1 && pos<=L->len)
    {
        printf("请输入修改后的学生的姓名:");
        scanf("%s",e.name);
        printf("请输入修改后的学生的年龄:");
        scanf("%d",&e.age);
        printf("请输入修改后的学生的分数:");
        scanf("%lf",&e.score);
        Updata_Position(L,pos,e);
        OutputList(L);
    }
    else
    {
        printf("\n修改位置不合法,操作失败!\n\n");
    }

    //单链表按位置查找
    printf("\n<-------------------------学生信息按位置查找------------------------->\n\n");
    printf("请输入查找的位置:");
    scanf("%d",&pos);
    Search_Position(L,pos);

    //单链表按元素查找
    printf("\n<-------------------------学生信息按元素查找------------------------->\n\n");
    printf("请输入查找的学生的姓名:");
    scanf("%s",e.name);
    printf("请输入查找的学生的年龄:");
    scanf("%d",&e.age);
    printf("请输入查找的学生的分数:");
    scanf("%lf",&e.score);
    printf("\n您所查询的学生在位置:%d\n\n",Search_Data(L,e));
    OutputList(L);

    //单链表按元素修改
    datatype key;
    printf("\n<-------------------------学生信息按元素修改------------------------->\n\n");
    printf("请输入修改前的学生的姓名:");
    scanf("%s",key.name);
    printf("请输入修改前的学生的年龄:");
    scanf("%d",&key.age);
    printf("请输入修改前的学生的分数:");
    scanf("%lf",&key.score);
    printf("\n\n");
    printf("请输入修改后的学生的姓名:");
    scanf("%s",e.name);
    printf("请输入修改后的学生的年龄:");
    scanf("%d",&e.age);
    printf("请输入修改后的学生的分数:");
    scanf("%lf",&e.score);
    Updata_Data(L,key,e);
    OutputList(L);

    //单链表按元素删除
    printf("\n<-------------------------学生信息按元素删除------------------------->\n\n");
    printf("请输入删除的学生的姓名:");
    scanf("%s",e.name);
    printf("请输入删除的学生的年龄:");
    scanf("%d",&e.age);
    printf("请输入删除的学生的分数:");
    scanf("%lf",&e.score);
    Delete_Data(L,e);
    OutputList(L);

    //单链表逆置
    printf("\n<-------------------------学生信息逆置------------------------->\n\n");
    printf("逆置前的学生信息如下所示:\n");
    OutputList(L);
    printf("逆置后的学生信息如下所示:\n");
    Inversion_Link(L);
    OutputList(L);
  
    //冒泡排序
    printf("\n<-------------------------学生信息按成绩排序------------------------->\n\n");
    printf("排序前的学生信息如下所示:\n");
    OutputList(L);
    printf("排序后的学生信息如下所示:\n");
    BubbleSort(L);
    OutputList(L);

    //链表空间释放
    L = free_space(L);

    return 0;
}

main.h

#ifndef __MAIN_H
#define __MAIN_H

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

//学生信息结构体
typedef struct
{
    char name[20];  //学生信息
    int age;    //学生年龄
    double score;   //学生分数
}Student;

typedef Student datatype;

typedef struct Node
{
    //数据域
    union
    {
        int len;    //头结点数据域
        datatype data;
    };
    //指针域
    struct Node *next;  //指向下一个结点   
}*linklist;

linklist Create_Head(); //创建头结点
linklist Create_Node(); //创建普通结点
int Insert_Head(linklist L,datatype e); //单链表头插
int Insert_Rear(linklist L,datatype e); //单链表尾插
void OutputList(linklist L);    //单链表的遍历
int Delete_Head(linklist L);    //单链表的头删
int Delete_Rear(linklist L);    //单链表尾删
int Insert_Position(linklist L,int pos,datatype e); //单链表按位置插入
int Delete_Position(linklist L,int pos);    //单链表按位置删除
int Updata_Position(linklist L,int pos,datatype e); //单链表按位置修改
int Search_Position(linklist L,int pos);    //单链表按位置查找
int Search_Data(linklist L,datatype e);     //单链表按元素查找
int Updata_Data(linklist L,datatype key,datatype e);    //单链表按元素修改
int Delete_Data(linklist L,datatype e); //单链表按元素删除
int Inversion_Link(linklist L); //单链表逆置
void BubbleSort(linklist L);    //冒泡排序
linklist free_space(linklist L);    //单链表的释放


#endif // !__MAIN_H

linklist.c

#include "main.h"

/**
 * @brief   创建头结点
 * 
 * @return linklist 
 */
linklist Create_Head()
{
    linklist L = (linklist)malloc(sizeof(struct Node));
    if (L == NULL)
        return NULL;
    //数据域
    L->len = 0;
    //指针域
    L->next = NULL;
    return L;
}

/**
 * @brief   创建普通结点
 * 
 * @return linklist 
 */
linklist Create_Node()
{
    linklist p = (linklist)malloc(sizeof(struct Node));
    if (p == NULL)
        return NULL;
    //数据域
    strcpy(p->data.name,"\0");
    p->data.age = 0;
    p->data.score = 0;
    //指针域
    p->next = NULL;
    return p;
}

/**
 * @brief       单链表头插
 * 
 * @param L     单链表
 * @param e     插入的学生信息
 * @return int  成功返回0,失败返回-1
 */
int Insert_Head(linklist L,datatype e)
{
    if (L == NULL)
    {
        printf("\n链表不存在,数据头插失败!\n\n");
        return -1;
    }
    linklist p = Create_Node();
    if (p == NULL)
        return -1;
    //数据域
    p->data = e;
    //指针域
    p->next = L->next;
    L->next = p;
    L->len++;
    return 0;
}

/**
 * @brief       单链表尾插
 * 
 * @param L     
 * @param e     学生信息
 * @return int  成功返回0,失败返回-1
 */
int Insert_Rear(linklist L,datatype e)
{
    if (L == NULL)
    {
        printf("\n链表不存在,数据尾插失败!\n\n");
        return -1;
    }

    linklist p = Create_Node();
    if (p == NULL)
        return -1;
    
    linklist q = L;
    for (size_t i = 1; i <= L->len; i++)
    {
        q = q->next;        
    }
    //指针域
    p->next = q->next;
    q->next = p;
    //数据域
    p->data = e;
    L->len++;
    return 0;

}


/**
 * @brief   链表遍历输出
 * 
 * @param L 
 */
void OutputList(linklist L)
{
    if (L == NULL || L->len == 0)
    {
        printf("\n数据元素不存在,遍历失败!\n\n");
        return;
    }
    linklist p = L;
    for (size_t i = 1; i <= L->len; i++)
    {
        p = p->next;
        printf("\n姓名\t\t年龄\t\t分数\n");
        printf("\n%s\t\t%d\t\t%.1lf\n",p->data.name,p->data.age,p->data.score);
    }
}

/**
 * @brief       单链表头删
 * 
 * @param L 
 * @return int  成功返回0,失败返回-1
 */
int Delete_Head(linklist L)
{
    if (L == NULL || L->len == 0)
    {
        printf("\n数据元素不存在,头删失败!\n\n");
        return -1;
    }
    linklist q = L->next;
    L->next = q->next;
    free(q);
    q = NULL;
    L->len--;
    return 0;
}

/**
 * @brief       单链表尾删
 * 
 * @param L 
 * @return int  成功返回0,失败返回-1
 */
int Delete_Rear(linklist L)
{
    if (L == NULL || L->len == 0)
    {
        printf("\n数据元素不存在,尾删失败!\n\n");
        return -1;
    }
    linklist p = L;
    for (size_t i = 1; i <= L->len-1; i++)
    {
        p = p->next;
    } 
    free(p->next);
    p->next = L;
    L->len--;
    return 0;
}

/**
 * @brief       单链表按位置插入 
 * 
 * @param L     单链表
 * @param pos   插入的位置
 * @param e     学生信息
 * @return int  成功返回0,失败返回-1
 */
int Insert_Position(linklist L,int pos,datatype e)
{
    if (L == NULL || L->len == 0 || pos < 1 || pos > L->len+1)
    {
        printf("\n单链表按位置插入失败!\n\n");
        return -1;
    }

    linklist p = Create_Node();
    if (p == NULL)
        return -1;

    linklist q = L;
    for (size_t i = 1; i <= pos-1; i++)
    {
        q = q->next;
    }
    //数据域
    p->data = e;
    //指针域
    p->next = q->next;
    q->next = p;
    L->len++;
    return 0;
}

/**
 * @brief       单链表按位置删除
 * 
 * @param L     单链表
 * @param pos   删除的位置
 * @return int  成功返回0,失败返回-1
 */
int Delete_Position(linklist L,int pos)
{
    if (L == NULL || L->len == 0 || pos < 1 || pos > L->len)
    {
        printf("\n单链表按位置删除失败!\n\n");
        return -1;
    }

    linklist p = L;
    for (size_t i = 1; i <= pos-1; i++)
    {
        p = p->next;
    }
    linklist q = p->next;
    p->next = q->next;
    free(q);
    q = NULL;
    L->len--;
    return 0;
}

/**
 * @brief       单链表按位置修改
 * 
 * @param L     单链表
 * @param pos   修改的位置
 * @param e     学生信息
 * @return int  成功返回0,失败返回-1
 */
int Updata_Position(linklist L,int pos,datatype e)
{
    if (L == NULL || L->len == 0 || pos < 1 || pos > L->len)
    {
        printf("\n单链表按位置修改失败!\n\n");
        return -1;
    }

    linklist p = L;
    for (size_t i = 1; i <= pos; i++)
    {
        p = p->next;
    }

    p->data = e;
    return 0;
}

/**
 * @brief       单链表按位置查找
 * 
 * @param L 
 * @param pos   查找的位置
 * @return int  成功返回0,失败返回-1
 */
int Search_Position(linklist L,int pos)
{
    if (L == NULL || L->len == 0 || pos < 1 || pos > L->len)
    {
        printf("\n单链表按位置查找失败!\n\n");
        return -1;
    }

    linklist p = L;
    for (size_t i = 1; i <= pos; i++)
    {
        p = p->next;
    }
    printf("您所查询的学生信息如下:\n");
    printf("\n姓名\t\t年龄\t\t分数\n");
    printf("\n%s\t\t%d\t\t%.1lf\n",p->data.name,p->data.age,p->data.score);
    return 0;
}

/**
 * @brief           单链表按元素查找
 * 
 * @param L         单链表
 * @param e         学生信息
 * @return int      成功返回位置,失败返回-1
 */
int Search_Data(linklist L,datatype e)
{
    if (L == NULL || L->len == 0)
    {
        printf("\n单链表按元素查找失败!\n\n");
        return -1;
    }

    linklist p = L;
    for (int i = 1; i <= L->len; i++)
    {
        p = p->next;
        if (strcmp(p->data.name,e.name)==0 && p->data.age==e.age && p->data.score==e.score)
        {
            return i;
        }
    }
    return -1;
}

/**
 * @brief       单链表按元素修改
 * 
 * @param L 
 * @param key   修改前的元素
 * @param e     修改后的元素
 * @return int  成功返回0,失败返回-1
 */
int Updata_Data(linklist L,datatype key,datatype e)
{
    int pos = Search_Data(L,key);
    if (pos == -1)
    {
        printf("\n单链表按元素修改失败!\n\n");
        return -1;
    }
    Updata_Position(L,pos,e);
    return 0;
}

/**
 * @brief           单链表按元素删除
 * 
 * @param L         单链表
 * @param e         删除的学生信息
 * @return int      成功返回0,失败返回-1
 */
int Delete_Data(linklist L,datatype e)
{
    int pos = Search_Data(L,e);
    if (pos == -1)
    {
        printf("\n单链表按元素删除失败!\n\n");
        return -1;
    }
    Delete_Position(L,pos);
    return 0;
}

/**
 * @brief           单链表逆置
 * 
 * @param L 
 * @return int      成功返回0,失败返回-1
 */
int Inversion_Link(linklist L)
{
    if (L == NULL || L->len == 0)
    {
        printf("\n单项链表逆置失败!\n\n");
        return -1;
    }
    linklist p = L->next;
    L->next = NULL;
    for (size_t i = 1; i <= L->len; i++)
    {
        linklist t = p->next;
        p->next = L->next;
        L->next = p;
        p = t;
    }
    return 0; 
}

/**
 * @brief       按成绩冒泡排序
 * 
 * @param L 
 */
void BubbleSort(linklist L)
{
    for (size_t i = 1; i < L->len; i++)
    {
        linklist p = L;
        int flag = 0;
        for (size_t j = 0; j < L->len-i; j++)
        {
            p = p->next;
            if (p->data.score < p->next->data.score)
            {
                datatype temp = p->data;
                p->data = p->next->data;
                p->next->data = temp;
                flag = 1;
            }
        }
        if (flag == 0)
            break;    
    } 
}

/**
 * @brief       链表空间释放
 * 
 * @param L 
 * @return linklist 
 */
linklist free_space(linklist L)
{
    if (L == NULL)
        return NULL;
    int count = L->len;
    for (size_t i = 0; i < count; i++)
    {
        Delete_Head(L);
    }
    free(L);
    L = NULL;
    return L; 
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值