【C】单链表

news/2025/2/19 8:23:42/文章来源:https://www.cnblogs.com/Shima-Rin/p/18716184

单链表

声明一个指向自身的结构体

struct Test
{int x;int y;struct Test test;
};

输出结果:

error!

程序报错,因为这样会造成无限的循环。当编译器解析到struct Test testtest是结构体Test的成员,定义test成员需要Test,而结构体Test自身又是不完整的,那么程序就无法定义一个结构体变量,所以会陷入无限的递归。修改方法如下:

struct Test
{int x;int y;struct Test *test;
};

test加上星号(*)将其变为一个指向Test结构体自身的指针变量

单链表

单链表是最简单的一种链表实现方式,它包含两个域,一个信息域和一个指针域:

信息域用来存放链表节点的内容(相当于数组里的内容)

指针域用来指向下一个和它一模一样的节点

当最后一个节点的指针域指向NULL时,表示单链表就此结束

head:真正的单链表它还需要一个头指针,用于存放指向链表第一个节点的地址

链表中各个元素在内存中不是紧密存放,而是通过指针连接在一起的

对于 Book 结构体来说,要把它变成链表的其中一个元素,我们只需要为其添加一个指向自身的成员即可:

struct Book
{char title[128]; //信息域char author[40];struct Book *next;
};

单链表中插入元素(头插法)

在单链表中插入元素,事实上只需要修改指针的指向即可:

将书籍添加到单链表的代码我们这么可以写:

#include<stdio.h>
#include<stdlib.h>
struct Book
{char title[128]; //信息域char author[40];struct Book *next;
};
void getInput(struct Book *boos);
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);
}
void addBook(struct Book **library)
//要修改library(即head指针)的值,所以要传入library指针的地址
//即用二级指针**library(指向指针的指针)
{struct Book *book, *temp;book = (struct Book *)malloc(sizeof(struct Book));if (book == NULL){printf("内存分配失败!\n");exit(1);}getInput(book);if (*library != NULL){temp = *library;*library = book;book->next = temp;}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: ", count);printf("书名 : %s", book->title);printf("作者 : %s", 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)
{struct Book *library = NULL;  //定义头指针,指向一个空的单链表addBook(&library);return 0;
}

尾插法

头插法,就是将数据插入到单链表的头部位置。相对应的还有另一个种方法:尾插法 —— 将数据插入到单链表的尾部位置

void addBook(struct Book **library)
{struct Book *book, *temp;book = (struct Book *)malloc(sizeof(struct Book));if (book == NULL){printf("内存分配失败!\n");exit(1);}getInput(book);if (*library != NULL){temp = *library;//定位单链表尾部位置while (temp->next != NULL){temp = temp->next;}temp->next = book;//当temp->next == NULL时,插入book节点book->next = NULL;}else{*library = book;book->next = NULL;}
}

上面的程序虽然能成功运行,但每插入一次数据都要遍历一次链表,效率不高。

void addBook(struct Book **library)
{struct Book *book;static struct Book *tail;//指针tail用来记录单链表尾部位置//因为每调用一次addbook函数指针tail都会初始化//为了让指针tail永远记录上一次插入数据后的尾部位置//用static将tail转为静态指针变量book = (struct Book *)malloc(sizeof(struct Book));if (book == NULL){printf("内存分配失败!\n");exit(1);}getInput(book);if (*library != NULL){tail->next = book;book->next = NULL;}else{*library = book;book->next = NULL;}tail = book;
}

搜索单链表

有时候我们可能会对单链表进行搜索操作,比如输入这个书名或者作者的名字,可以找到相关的节点数据。

struct Book *searchBook(struct Book *library, char *target)
{struct Book *book;book = library;while (book != NULL){if (!strcmp(book->title, target) || !strcmp(book->author, target)){break;}book = book->next;}return book;
}void printBook(struct Book *book)
{printf("书名:%s\n", book->title);printf("作者:%s\n", book->author);
}
...
int main(void)
{...printf("\n请输入书名或作者:");scanf("%s", input);book = searchBook(library, input);if (book == NULL){printf("很抱歉,没能找到!\n");}else{do{printf("已找到符合条件的书籍...\n");printBook(book);} while ((book = searchBook(book->next, input)) != NULL);}releaseLibrary(&library);return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/883927.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

所有Ollama用户请注意!!!你的IP可能已泄露

刚刚学到一项非常硬核的“黑”科技,只要几个关键词,就能实现 Ollama 自由。全世界几万台高性能带显卡的电脑供你使用。 添加图片注释,不超过 140 字(可选)看看这个页面,美国,中国,德国,英国....一个独立 IP 背后就是一台电脑,有些可能还是服务器。我实测了,随便找一…

【C】内存布局

动态内存管理 动态内存管理的几个函数malloc -- 申请动态内存空间 free -- 释放动态内存空间 calloc -- 申请并初始化一系列内存空间 realloc -- 重新分配内存空间malloc函数原型:void *malloc(size_t size);malloc函数向系统申请分配size个字节的内存空间,并返回一个指向这块…

【C】指针

指针 变量在内存中的存放 在内存中,字节是最小的存储单元。对于一个内存单元来说,指针就是单元的地址,每个地址可以存放一个字节的数据。存放一个整形变量(int)就需要动用到四个存储单元。 在内存中完全没有存储变量名的必要。 因为编译器知道具体每一个变量名对应的存放地址…

VMwareWorkstation pro 17下载与安装

‌VMware Workstation Pro 17‌是一款功能强大的虚拟机软件,专为开发者和IT专业人士设计。它允许用户在一台物理计算机上创建和运行多个虚拟操作系统,从而实现跨平台的开发、测试和部署。VMware Workstation Pro 17采用了先进的虚拟化技术,能够在单个物理主机上运行多个虚拟…

我的“ DeepSeek 越来越闲了”!讯飞星火无限调用 API 攻略来了

最近DeepSeek 确实挺忙,网页繁忙,API资源紧张。 添加图片注释,不超过 140 字(可选) 开源模型也很忙,被下载了 267万次!!! 添加图片注释,不超过 140 字(可选) 但是,我的 DeepSeek 要越来越闲了。腾讯云的接口刚用上,讯飞星火的又来了。 添加图片注释,不超过 1…

【C】数组

数组 数组的定义语法:类型 数组名[元素个数] (方括号内只能是常量或者常量表达式) int a[6]; char b[24]; double c[3];上面几个类型分别占用内存的字节数为: int a[6] ==> 4 * 6 = 24 char b[24] ==> 1 * 24 = 24 double c[3] …

【牛客训练记录】牛客小白月赛110

训练情况赛后反思 C题没看到偶数,导致打错表了TAT,然后浪费了一点时间 A题 编号每 \(500\) 一组,我们分别除 \(500\) 和取模 \(500\) 就行了点击查看代码 #include <bits/stdc++.h> // #define int long long #define endl \nusing namespace std;void solve(){int x;…

华为FusionCompute虚拟化平台

一、华为FusionCompute虚拟化套件介绍 华为FusionCompute虚拟化套件是业界领先的虚拟化解决方案,能够帮助客户带来如下的价值,从而大幅提升数据中心基础设施的效率。帮助客户提升数据中心基础设施的资源利用率; 帮助客户成倍缩短业务上线周期; 帮助客户成倍降低数据中心能耗…

卡特兰数学习笔记

引入 从 \((0,0)\) 走到 \((n,n)\),求不越过 \(y=x\) 的方案数。 不考虑是否合法的方案数是 \(\binom{2n}{n}\),即从 \(2n\) 个移动中选 \(n\) 个向右的。 接下来考虑不合法的情况,不合法当且仅当碰到了 \(y=x+1\) 这条直线,设这个点是 \((p,p+1)\),将后面的折线沿着 \(y=…

SpringCloud自定义loadbalancer实现标签路由

一、背景最近前端反应开发环境有时候调接口会很慢,原因是有开发图方便将本地服务注册到开发环境,请求路由到开发本地导致, 为了解决该问题想到可以通过标签路由的方式避免该问题,实现前端联调和开发自测互不干扰。该方案除了用于本地调试,还可以用于用户灰度发布。 二、实…

2025.2.14鲜花

ln将卷积转为加法。推歌 (看fengwu博客时候看见的) 《堕》 星河挂在天上 保护璀璨月亮 而你在我心中宛如月光 为你痴为你狂 为你笑为你闯 为你悲为你伤 为你扬 她是踏碎星河落入我梦境的幻想 环遍星系为你寻找的力量 神明给我在最难熬的时光 留下唯一的星光 堕入日月星辉之中…

解密prompt系列48. DeepSeek R1 Kimi 1.5长思维链 - RL Scaling

春节前DeepSeek R1和Kimi1.5炸翻天了,之前大家推测的O1的实现路径,多数都集中在MCTS推理优化,以及STaR等样本自优化方案等等,结果DeepSeek和Kiim直接出手揭示了reasoning的新路线不一定在SFT和Inference Scaling,也可以在RL。也算是Post Train阶段新的Scaling方向,几个核…