数据结构之链表的使用【C语言】

链表在几种数据结构中算是比较简单的,操作也比较简单。链表分为单向、双向、循环链表,其中单向链表是所有链表的基础。结合一个简单的例子,用C语 言实践单向链表的创建、修改、删除操作。在实践的过程中,学习了C语言关于scanf的使用技巧:在scanf使用多次时,需要使用 fflush(stdin)来清空缓冲区,最好每次使用后,就刷新一次,以免出现不确定的输入的问题。

学生信息:姓名、年龄。

操作:1、增加;2、修改;3、删除;4、查询;5、退出。其中查询使用strstr()函数,实现部分匹配查找。顺序查询算法复杂度为O(n)。

缺点:只有顺序添加节点功能,没有随机添加节点功能。

代码:

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

#define NAMEMAX 40
#define SUCCESS 1
#define FAIL 0

struct student
{
    char studentName[NAMEMAX];
    unsigned int studentAge;
    struct student* next;
};
typedef struct student node;
typedef struct student* pNode;

static int studentNumber;

/********* 函数声明 开始 *********/
pNode add_student(pNode head);
pNode find_lastNode(pNode head);
void modify_student(pNode head);
pNode delete_student(pNode head);
int search_student(pNode head);
void quit_student(pNode head);
/********* 函数声明 结束 *********/

/***
 * 查找最后一个节点
 */
pNode find_lastNode(pNode head)
{
    pNode tempPNode;

    tempPNode = head;
    while(tempPNode->next != NULL)
    {
        tempPNode = tempPNode->next;
    }

    return tempPNode;
}

/***
 * 显示学生个人信息
 */
void show_student_information(pNode node)
{
    printf("姓名:%s\n",node->studentName);
    printf("年龄:%u\n",node->studentAge);
}

/**
 * 增加学生信息
 * 创建单向链表
 * head:链表头指针
 */
pNode add_student(pNode head)
{
    char tempName[NAMEMAX];//学生姓名临时变量
    unsigned int tempAge;//学生年龄临时变量
    pNode tempPNode;
    pNode tempPPreNode;
    char isAdd;

    printf("\n************************\n");
    printf("      增加学生信息\n");
    printf("************************\n");
    printf("请输入学生姓名: ");
    scanf("%s",tempName);//输入姓名
    printf("请输入学生年龄: ");
    while((scanf("%u",&tempAge) !=1) || tempAge <=0)//输入年龄
    {
        printf("请输入正确的年龄(大于0的整数): ");
    }
    printf("************************\n");
    printf("学生信息\n");
    printf("姓名:%s\n", tempName);
    printf("年龄:%u\n", tempAge);
    printf("是否增加(Y/N): ");

    fflush(stdin);//刷新缓冲区
    while((scanf("%c",&isAdd) != 1) || (isAdd != 'Y' && isAdd != 'y' && isAdd != 'N' && isAdd != 'n'))//是否增加
    {
        printf("请输入Y或者y或者N或者n!\n");
        printf("是否增加(Y/N): ");
        //刷新缓冲区
        fflush(stdin);
    }
    if(isAdd == 'Y' || isAdd == 'y')
    {
        if(head == NULL)//无节点
        {
            head = (pNode)malloc(sizeof(node));
            strcpy(head->studentName, tempName);
            head->studentAge = tempAge;
            head->next = NULL;
        }
        else//有节点
        {
            tempPNode = (pNode)malloc(sizeof(node));
            strcpy(tempPNode->studentName, tempName);
            tempPNode->studentAge = tempAge;
            tempPNode->next = NULL;

            tempPPreNode = find_lastNode(head);
            tempPPreNode->next = tempPNode;
        }
        studentNumber ++;
        printf("增加学生信息成功,");
    }
    else
    {
        printf("增加学生信息失败,");
    }

    printf("返回主菜单\n\n");

    return head;
}

/**
 * 修改学生信息
 * 顺序查找链表
 */
void modify_student(pNode head)
{
    unsigned int index = 0;//选中学生的序号
    unsigned int tmpIndex = 0;//临时变量
    pNode tmpNode;//节点临时变量
    char tmpName[NAMEMAX];
    unsigned int tmpAge = 0;
    char isAdd;

    if(search_student(head))
    {
        printf("请选择序号:");

        while((scanf("%u",&index) != 1) || index == 0)
        {
            printf("请输入大于0的整数!\n");
            printf("请选择序号:");
            fflush(stdin);
        }

        tmpNode = head;

        while(tmpNode)
        {
            if(strstr(tmpNode->studentName,tmpName) != NULL)/*查找成功*/
            {
                tmpIndex++;
                if(tmpIndex == index)//找到
                {
                    break;
                }
                else//未找到
                {
                    tmpNode = tmpNode->next;
                }
            }
        }

        if(tmpIndex != 0 && tmpIndex == index)//找到
        {
            printf("选中的学生信息:\n");
            show_student_information(tmpNode);

            printf("新信息:\n");
            printf("姓名:");
            scanf("%s",tmpName);
            printf("年龄:");

            while((scanf("%u",&tmpAge) != 1) || tmpAge == 0)
            {
                printf("请输入大于0的整数!\n");
                printf("年龄:");
                fflush(stdin);
            }

            printf("是否修改(Y/N): ");

            fflush(stdin);//刷新缓冲区
            while((scanf("%c",&isAdd) != 1) || (isAdd != 'Y' && isAdd != 'y' && isAdd != 'N' && isAdd != 'n'))//是否增加
            {
                printf("请输入Y或者y或者N或者n!\n");
                printf("是否修改(Y/N): ");
                //刷新缓冲区
                fflush(stdin);
            }

            if(isAdd == 'Y' || isAdd == 'y')//修改
            {
                strcpy(tmpNode->studentName, tmpName);
                tmpNode->studentAge = tmpAge;
                printf("已修改!返回主菜单。\n");
            }
            else//不修改
            {
                printf("未修改!返回主菜单。\n");
            }

        }
        else//未找到
        {
            printf("未修改!返回主菜单。\n");
            return;
        }
    }

}

/***
 * 按照姓名模糊查找,并删除相关学生信息
 * 删除链表节点
 */
pNode delete_student(pNode head)
{
    unsigned int index = 0;//选中学生的序号
    unsigned int tmpIndex = 0;//临时变量
    pNode tmpNode = NULL;//节点临时变量
    pNode tmpPreNode = NULL;//要删除的节点的前一个节点临时变量
    char tmpName[NAMEMAX];
    char isDel;

    if(search_student(head))
    {
        printf("请选择序号:");

        while((scanf("%u",&index) != 1) || index == 0)
        {
            printf("请输入大于0的整数!\n");
            printf("请选择序号:");
            fflush(stdin);
        }

        tmpNode = head;

        while(tmpNode)
        {
            if(strstr(tmpNode->studentName,tmpName) != NULL)/*查找成功*/
            {
                tmpIndex++;
                if(tmpIndex == index)//找到
                {
                    break;
                }
                else//未找到
                {
                    tmpPreNode = tmpNode;
                    tmpNode = tmpNode->next;
                }
            }
        }

        if(tmpIndex !=0 && tmpIndex == index)//找到
        {
            printf("是否删除(Y/N): ");

            fflush(stdin);//刷新缓冲区
            while((scanf("%c",&isDel) != 1) || (isDel != 'Y' && isDel != 'y' && isDel != 'N' && isDel != 'n'))//是否增加
            {
                printf("请输入Y或者y或者N或者n!\n");
                printf("是否删除(Y/N): ");
                //刷新缓冲区
                fflush(stdin);
            }

            if(isDel == 'Y' || isDel == 'y')//删除
            {
                if(tmpNode == head)//如果删除的节点为头结点
                {
                    head = head->next;
                }
                else if(tmpNode->next != NULL)//删除的节点在中间
                {
                    tmpPreNode->next = tmpNode->next;
                    tmpNode->next = NULL;
                }
                else if(tmpNode->next == NULL)//删除的节点在末尾
                {
                    tmpPreNode->next = NULL;

                }
                free(tmpNode);
                tmpNode == NULL;
                printf("删除成功!返回主菜单。\n");
                studentNumber --;
            }
            else//不删除
            {
                printf("未删除!返回主菜单。\n");
            }
        }
        else//未找到
        {
            printf("未找到!返回主菜单。\n");
        }
    }

    return head;
}

/***
 * 按照姓名模糊查找
 * 顺序查找链表
 */
int search_student(pNode head)
{
    //测试使用
    pNode tmpNode;
    int tmpIndex = 0;
    char tmpName[NAMEMAX];//学生姓名临时变量

    if(head == NULL)
    {
        printf("没有学生信息,请添加!返回主菜单。\n");
        return FAIL;
    }

    printf("\n************************\n");
    printf("输入学生姓名【模糊查找】:\n");

    fflush(stdin);

    scanf("%s",tmpName);

    tmpNode = head;

    while(tmpNode)
    {
        if(strstr(tmpNode->studentName,tmpName) != NULL)/*查找成功*/
        {
            tmpIndex++;
            printf("%d:\n",tmpIndex);
            show_student_information(tmpNode);
        }
        tmpNode = tmpNode->next;
    }

    if(tmpIndex == 0)
    {
        printf("没有查找到名字中包含%s的学生!\n",tmpName);
        printf("\n************************\n");
        return FAIL;
    }
    printf("\n************************\n");
    return SUCCESS;
}

/**
 * 退出系统,删除所有学生信息
 * 删除链表
 */
void quit_student(pNode head)
{
    pNode tmpNode1 = NULL;
    pNode tmpNode2 = NULL;

    if(head == NULL)
    {
        return;
    }

    tmpNode1 = head;

    while(tmpNode1)
    {
        tmpNode2 = tmpNode1->next;
        free(tmpNode1);
        tmpNode1 = tmpNode2;
    }
    head = NULL;
}

/*****
 * 主程序
 */
int main(void)
{
    int choice;//用户选项
    int isContinue;//是否继续
    pNode head;//链表头

    choice = 0;
    studentNumber = 0;
    head = NULL;
    isContinue = 1;

    do{
        printf("************************\n");
        printf("欢迎使用学生信息管理系统\n");
        printf("************************\n");
        printf("主菜单:\n");
        printf("1.增加学生信息\n");
        printf("2.修改学生信息\n");
        printf("3.删除学生信息\n");
        printf("4.查询学生信息\n");
        printf("5.退出系统\n");
        printf("------------------------\n");
        printf("已有%d名学生信息\n",studentNumber);
        printf("------------------------\n");
        printf("请输入菜单选项(1-5): ");

        while((scanf("%d",&choice) != 1) || (choice > 5) || (choice < 1))
        {
            printf("警告:请输入1-5整数!\n");
            printf("请输入菜单选项(1-5): ");
            fflush(stdin);//刷新缓冲区
        }

        switch(choice)
        {
        case 1://增加
            head = add_student(head);
            break;
        case 2://修改
            modify_student(head);
            break;
        case 3://删除
            head = delete_student(head);
            break;
        case 4://查询
            search_student(head);
            break;
        case 5://退出系统
            quit_student(head);
            isContinue = 2;
            break;
        default://异常错误,暂无处理
            printf("出现异常错误,退出系统!\n");
            break;
        }
    }while(isContinue == 1);

    return 0;
}


 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值