带你学C带你飞 | 单链表

一、单链表

  链表是一种常见的基础数据结构。根据需求,我们可以构造出单链表、双链表、循环链表和块状链表等。链表的出现很大程度上弥补了数组的先天不足。
  单链表包含两个域:信息域和指针域。

  • 信息域用来存放链表节点的内容
  • 指针域用来指向下一节点

单链表是用指针串联到一起的,直到指针指向NULL,表示单链表结束。
  单链表节点的声明:需要添加一个指向自身的指针域。
举个栗子:

#include <stdio.h>

//单链表节点的声明
struct Book
{
   
        char title[128];
        char author[40];
        struct Book *next;
};      

int main(void)
{
          
        return 0;
} 

1.头插法

  在单链表中插入元素(节点):首先,在堆中申请一个内存空间来存放节点,填充弄信息域,然后,通过调整指针指向来实现插入。
举个栗子:头插法

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

//单链表节点的声明
struct Book
{
   
        char title[128];
        char author[40];
        struct Book *next;
}

//填充信息域
void getInput(struct Book *book)
{
   
        printf("请输入书名:");
        scanf("%s",book->title);

        printf("请输入作者:");
        scanf("%s",book->author);
}

//这里**是因为library指针中存放的值是需要修改的,因此,要将指针的地址传进来,就是指向Book结构体指针的指针
void addBook(struct Book **library)
{
   
        struct Book *book, *temp;
        //在堆中申请一个内存空间来存放节点
        book = (struct Book *)malloc(sizeof(struct Book));
        if (book == NULL)
        {
   
                printf("内存分配失败");
                exit(1);
        }

        //填充信息域
        getInput(book);

        //如果头指针没有指向NULL,那么借助临时变量保存地址
        if (*library != NULL)
        {
   
                temp = *library;
                *library = book;
                book->next = temp;
        }
        //如果头指针指向NULL,则指向新建节点
        else
        {
   
                *library = book;
                book->next = NULL;
        }
}

int main(void)
{
   
        //head指针
        struct Book *library = NULL;

        addBook(&library);
        return 0;
}

  打印单链表及头插法完整部分如下
举个栗子:

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

//单链表节点的声明
struct Book
{
   
        char title[128];
        char author[40];
        struct Book *next;
};

//函数声明
void getInput(struct Book *book);
void addBook(struct Book **library);
void printLibrary(struct Book *library);
void releaseLibrary(struct Book **library);

//填充信息域
void getInput(struct Book *book)
{
   
        printf("请输入书名:");
        scanf("%s",book->title);

        printf("请输入作者:");
        scanf("%s",book->author);
}

//这里**是因为library指针中存放的值是需要修改的,因此,要将指针的地址传进来,就是指向Book结构体指针的指针
void addBook(struct Book **library)
{
   
        struct Book *book, *temp;
        //在堆中申请一个内存空间来存放节点
        book = (struct Book *)malloc(sizeof(struct Book));
        if (book == NULL)
        {
   
                printf("内存分配失败");
                exit(1);
        }

        //填充信息域
        getInput(book);

        //如果头指针没有指向NULL,那么借助临时变量保存地址
        if (*library != NULL)
        {
   
                temp = *library;
                *library = book;
                book->next = temp;
        }
        //如果头指针指向NULL,则指向新建节点
        else
        {
   
                *library = book;
                book->next = NULL;
        }
}

//打印单链表
void printLibrary(struct Book *library)
{
   
        struct Book *book;
        int count = 1;

        book = library;
        while (book != NULL)
        {
   
                printf("Book%d: \n",count);
                printf("书名:%s\n",book->title);
                printf("作者:%s\n",book->author);
                //移动一位
                book = book->next;
                count++;
        }
}

//释放内存空间
void releaseLibrary(struct Book **library)
{
   
		struct Book *temp;
        while (*library != NULL)
        {
   
        		temp = *library;
                *library = (*library)->next;
                free(temp);
        }
}

int main(void)
{
   
        //head指针
        struct Book *library = NULL;
        int ch;

        while (1)
        {
   
                printf("请问是否需要录入书籍信息(Y/N):");
                do
                {
   
                        ch = getchar();
                }while (ch != 'Y' && ch != 'N');

                if (ch == 'Y')
                {
   
                        addBook(&library);
                }
                else
                {
   
                        break;
                }

        }

        printf("请问是否需要打印图书信息(Y/N):");
        do
        {
   
                ch = getchar();
        }while (ch != 'Y' && ch != 'N');

        if (ch == 'Y')
        {
   
                printLibrary(library);
        }

        //释放内存空间
        releaseLibrary(&library);
        return 0;
}
[liujie@localhost sle43]$ gcc test.c && ./a.out
请问是否需要录入书籍信息(Y/N):Y
请输入书名:《零基础入门Python》
请输入作者:小甲鱼
请问是否需要录入书籍信息(Y/N):Y
请输入书名:《带你学C带你飞》
请输入作者:小甲鱼
请问是否需要录入书籍信息(Y/N):N
请问是否需要打印图书信息(Y/N):Y
Book1:
书名:《带你学C带你飞》
作者:小甲鱼
Book2:
书名:《零基础入门Python》
作者:小甲鱼

2.尾插法

在这里插入图片描述
其代码实现为:

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

//单链表节点的声明
struct Book
{
   
        char title[128];
        char author[40];
        struct Book *next;
};

//函数声明
void getInput(struct Book *book);
void addBook(struct Book **library);
void printLibrary(struct Book *library);
void releaseLibrary(struct Book **library);

//填充信息域
void getInput(struct Book *book)
{
   
        printf("请输入书名:");
        scanf("%s",book->title);

        printf("请输入作者:");
        scanf("%s",book->author);
}

//这里**是因为library指针中存放的值是需要修改的,因此,要将指针的地址传进来,就是指向Book结构体指针的指针
void addBook(struct Book **library)
{
   
        struct Book *book, *temp;
        //在堆中申请一个内存空间来存放节点
        book = (struct Book *)malloc(sizeof(struct Book));
        if (book == NULL)
        {
   
                printf("内存分配失败");
                exit(1);
        }

        //填充信息域
        getInput(book);

        //如果头指针没有指向NULL,那么借助临时变量保存地址
        if (*library != NULL)
        {
   
                temp = *library;
                //定位单链表的尾部
                while (temp->next != NULL)
                {
   
                        temp = temp->next;
                }
                //插入数据
                temp->next = book;
                book->next = NULL;
        }
        //如果头指针指向NULL,则指向新建节点
        else
        {
   
                *library = book;
                book->next = NULL;
        }
}

//打印单链表
void printLibrary(struct Book *library)
{
   
        struct Book *book;
        int count = 1;

        book = library;
        while (book != NULL)
        {
   
                printf("Book%d: \n",count);
                printf("书名:%s\n"
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值