C语言基础之单向链表

一、链表的概述

1、单向链表的概述

单向链表是由一个个节点组成,节点没有名字,链表中的每个节点都包含一个存储空间,用于存储数据,以及一个指针,指向下一个节点的位置 达到逻辑上连续。这些节点在内存中是分散存储的,而不是连续存储的。这种分散存储的方式使得链表具有了动态内存分配的能力,可以在运行时根据需要创建和删除节点。

在这里插入图片描述

2、链表和数组优缺点

**静态数组:**int arr[5]; 必须事先确定数组元素的个数,过多浪费,过小溢出,删除插入效率低(需要移动大量数据)

动态数组:不需要事先知道元素个数,在使用中动态申请,删除插入数据效率低(需要移动大量数据)

随机访问效率非常高。我们可以直接通过索引来访问数组中的任意一个元素,而不需要遍历整个数组。

**链表:**不需要事先知道数据个数,在使用中动态申请,插入删除不需要移动数据,在运行时我们只需要改变几个指针就可以在任何位置插入或删除一个元素。(缺点:遍历效率低)

3、单向链表的设计

(1)链表节点设计

#include <stdio.h>//节点的设置
struct stu
{//数据域int num;char str[128];//指针域 连接到的节点struct stu *next;
};int main(int argc, char const *argv[])
{//申请空间struct stu* data1 = (struct stu*)malloc(sizeof(struct stu));struct stu* data2 = (struct stu*)malloc(sizeof(struct stu));struct stu* data3 = (struct stu*)malloc(sizeof(struct stu));struct stu* data4 = (struct stu*)malloc(sizeof(struct stu));struct stu* data5 = (struct stu*)malloc(sizeof(struct stu));//初始化数据内容data1->num = 10;data2->num = 20;data3->num = 30;data4->num = 40;data5->num = 50;strcpy(data1->str,"xixi");strcpy(data2->str,"haha");strcpy(data3->str,"lala");strcpy(data4->str,"hehe");strcpy(data5->str,"dsds");data1->next = NULL;data2->next = NULL;data3->next = NULL;data4->next = NULL;data5->next = NULL;//定义链表头head = data1;//将data1的地址定义为表头//连接链表data1->next = data2;data2->next = data3;data3->next = data4;data4->next = data5;data5->next = NULL; return 0;
}

(2)链表的遍历

    void print_array(struct stu * head){//链表的遍历struct stu *pb = head;while (pb != NULL){printf("%d %s\n",pb->num,pb->str);pb = pb->next;}}

4、单向链表的使用

(1)节点的插入

①头部插入

struct stu* head_in(struct stu* head)//头部插入
{//为插入的数据申请空间struct stu* data = (struct stu*)malloc(sizeof(struct stu));//赋值data->num = 20;strcpy(data->str,"didi");data->next = NULL;struct stu* pb = head;data->next = head;//将原本的头地址赋到新数据的指针域head = data;//让新数据的地址作为头地址return head;//返回新的头地址
}

②尾部插入

//尾部插入
void tail_in(struct stu* head)
{struct stu* data = (struct stu*)malloc(sizeof(struct stu));data->num = 80;strcpy(data->str,"wei");data->next = NULL;struct stu* pb = head;while (pb->next != NULL)//判断指针域是否为空,为空说明是最后一个数据{pb = pb->next;}pb->next = data;//将新数据连接到尾端
}

③有序插入

//有序插入
struct stu* order_in(struct stu* head)
{//为插入的数据申请空间struct stu* data = (struct stu*)malloc(sizeof(struct stu));//赋值data->num = 45;strcpy(data->str, "youxu");data->next = NULL;struct stu* pb = head;struct stu* fp = head;struct stu* ff = head;if(data->num < pb->num)//小的在前{    data->next = head;head = data;}else if(data->num > pb->num){while (pb->next != NULL && data->num > pb->num){   fp = pb;pb = pb->next;}ff = data;ff->next = data->next;data = fp;data->next = ff;ff->next = pb;}return head;}

(2)链表的节点查找

struct stu* node(struct stu* head, char *str)
{struct stu* pb = head;while (strcmp(pb->str, str) != 0 && pb->next != NULL){pb = pb->next;}if(strcmp(pb->str, str) == 0){return pb;}printf("NO\n");return NULL;
}

(3)链表节点的删除

//节点删除
struct stu* delet_node(struct stu* head, char *str)
{struct stu* pb = head , *pf = head;while (strcmp(pb->str, str) != 0 && pb->next != NULL){pf = pb;pb = pb->next;}if(strcmp(pb->str, str) == 0){if(pb == head)//头节点{head = head->next;}else  //中节点{pf->next = pb->next;}free(pb);return head;}printf("NO\n");return NULL;
}

(4)链表的释放

//释放链表
void free_file(struct stu* head)
{struct stu* pb = head;while (pb != NULL){head = pb->next;free(pb);pb = head;}}

(5)链表的翻转

//链表翻转
struct stu* serversal(struct stu* head)
{struct stu* pf = NULL;struct stu* pb = head->next;head->next = NULL;while (pb != NULL){pf = pb->next;pb->next = head;head = pb;pb = pf;}return head;  
}

(6)链表的排序

//链表排序
void sort_file(struct stu* head)
{struct stu* p_i = head, *p_j = head; while (p_i->next != NULL) {struct stu* p_min = p_i; p_j = p_min->next; while (p_j != NULL) {if (p_min->num > p_j->num) p_min = p_j; p_j = p_j->next; }if (p_i != p_min) {//交换数据struct stu tmp = *p_i;*p_i = *p_min;*p_min = tmp;tmp.next = p_i->next;p_i->next = p_min->next;p_min->next = tmp.next;}p_i = p_i->next; //i++}
}

5、单向链表案例

单向链表存储学生信息

#include <stdio.h>
#include <stdlib.h>
#include <string.h>//节点的设置
struct stu
{//数据域int num;char str[128];//指针域struct stu *next;
};
struct stu * head = NULL;void print_array(struct stu * head);//遍历
struct stu* delet_node(struct stu* head, char *str);//节点删除
struct stu* head_in(struct stu* head, int q,char * w);//头部插入
void free_file(struct stu* head);//释放链表
struct stu* node(struct stu* head, char *str);//节点查找
void sort_file(struct stu* head);//链表排序void help(void)
{printf("*******************************\n");printf("*            Help             *\n");printf("*            Output           *\n");//输出printf("*            Input            *\n");//输入printf("*            Delete           *\n");//删除printf("*            Query            *\n");//查询printf("*            Sort             *\n");//排序printf("*            Free             *\n");//关闭printf("*******************************\n");
}
int main(int argc, char const *argv[])
{help();while (1){char cmd[128] = "";printf("--->Please enter the commed:\n");scanf("%s",cmd);if(strcmp(cmd, "Help") == 0){help();}else if (strcmp(cmd, "Output") == 0){ print_array(head);}else if (strcmp(cmd, "Input") == 0){int q = 0;char w[128] = "";printf("--->Please input information:\n");scanf("%d %s",&q ,w);head = head_in(head,q,w);}else if (strcmp(cmd, "Delete") == 0)//删除{char data[128] = "";printf("--->Please input link\n");scanf("%s",data);head = delet_node(head,data);}else if (strcmp(cmd, "Query") == 0)//查询{struct stu* pf = NULL;char data[128] = "";printf("--->Please input link\n");scanf("%s",data);pf = node(head,data);if(pf != NULL){printf("%d %s\n",pf->num, pf->str);}}else if (strcmp(cmd, "Sort") == 0)//排序{sort_file(head);}else if (strcmp(cmd, "Free") == 0)//关闭{free_file(head);return 0;}}return 0;
}
//遍历
void print_array(struct stu * head)
{//判断链表是否存在if (head == NULL) //不存在{printf("link not exits\n");return;}//链表的遍历struct stu *pb = head;while (pb != NULL){printf("%d %s\n",pb->num,pb->str);pb = pb->next;}
}
//节点删除
struct stu* delet_node(struct stu* head, char *str)
{if(head == NULL){printf("link not exist\n");return NULL;}struct stu* pb = head , *pf = head;while (strcmp(pb->str, str) != 0 && pb->next != NULL){pf = pb;pb = pb->next;}if(strcmp(pb->str, str) == 0){if(pb == head)//头节点{head = head->next;}else  //中节点{pf->next = pb->next;}free(pb);return head;}printf("NO\n");return NULL;
}
//头部插入
struct stu* head_in(struct stu* head,int q, char *w)
{struct stu* data = (struct stu*)malloc(sizeof(struct stu));data->next = NULL;if(head == NULL){data->num = q;strcpy(data->str,w);head = data;return head;}else{data->num = q;strcpy(data->str,w);data->next = NULL;struct stu* pb = head;data->next = head;head = data;return head;}}
//释放链表
void free_file(struct stu* head)
{if(head == NULL){printf("link not exist\n");return;}struct stu* pb = head;while (pb != NULL){head = pb->next;free(pb);pb = head;}}
//节点查找
struct stu* node(struct stu* head, char *str)
{if(head == NULL){printf("link not exist\n");return NULL;}struct stu* pb = head;while (strcmp(pb->str, str) != 0 && pb->next != NULL){pb = pb->next;}if(strcmp(pb->str, str) == 0){return pb;}printf("NO\n");return NULL;
}
//链表排序
void sort_file(struct stu* head)
{if(head == NULL){printf("link not exist\n");return;}struct stu* p_i = head, *p_j = head; while (p_i->next != NULL) {struct stu* p_min = p_i; p_j = p_min->next; while (p_j != NULL) {if (p_min->num > p_j->num) p_min = p_j; p_j = p_j->next; }if (p_i != p_min) {//交换数据struct stu tmp = *p_i;*p_i = *p_min;*p_min = tmp;tmp.next = p_i->next;p_i->next = p_min->next;p_min->next = tmp.next;}p_i = p_i->next; //i++}
}

6、如有错误欢迎指正

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

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

相关文章

面向控制台编程?Java的GUI开发

记得之前刚开始学习Java&#xff0c;按部就班去阅读《Java核心技术》这本书的时候&#xff0c;总是听别人提起&#xff0c;java swing那一章不用看了。然后直到对着控制台编程了半年&#xff0c;回来捡起了Swing图形界面&#xff0c;跟着网上搞了坦克大战的游戏&#xff0c;总觉…

论文阅读——Rein

Stronger, Fewer, & Superior: Harnessing Vision Foundation Models for Domain Generalized Semantic Segmentation 一、引言 是一个对Domain Generalized Semantic Segmentation (DGSS)任务的视觉大模型的微调方法&#xff0c;即Rein。 Rein 专为 DGSS 任务量身定制&a…

最细节操作 Linux LVM 逻辑卷管理

Linux LVM&#xff08;逻辑卷管理&#xff09; 周末愉快&#xff0c;今天带大家实战一下LVM! 一、LVM理论 LVM&#xff0c;即Logical Volume Manager&#xff0c;逻辑卷管理器&#xff0c;是一种硬盘的虚拟化技术&#xff0c;可以允许用户的硬盘资源进行灵活的调整和动态管理…

MySQL语法分类 DQL(6)分页查询

为了更好的学习这里给出基本表数据用于查询操作 create table student (id int, name varchar(20), age int, sex varchar(5),address varchar(100),math int,english int );insert into student (id,name,age,sex,address,math,english) values (1,马云,55,男,杭州,66,78),…

计算机设计大赛 题目:基于机器视觉opencv的手势检测 手势识别 算法 - 深度学习 卷积神经网络 opencv python

文章目录 1 简介2 传统机器视觉的手势检测2.1 轮廓检测法2.2 算法结果2.3 整体代码实现2.3.1 算法流程 3 深度学习方法做手势识别3.1 经典的卷积神经网络3.2 YOLO系列3.3 SSD3.4 实现步骤3.4.1 数据集3.4.2 图像预处理3.4.3 构建卷积神经网络结构3.4.4 实验训练过程及结果 3.5 …

【jeecgboot】微服务实战LISM

目录 一、服务解决方案-Spring Cloud Alibaba1.1选用原因&#xff08;基于Spring Cloud Alibaba的试用场景&#xff09;1.2 核心组件使用前期规划 部署 nacos部署 mino使用JavaFreemarker模板引擎&#xff0c;根据XML模板文件生成Word文档使用JavaFlowable 工作流引擎前端 -vue…

redis中List和hash数据类型

list类型是用来存储多个有序的字符串的&#xff0c;列表当中的每一个字符看做一个元素&#xff0c;一个列表当中可以存储一个或者多个元素&#xff0c;redis的list支持存储2^32-1个元素。redis可以从列表的两端进行插入&#xff08;pubsh&#xff09;和弹出&#xff08;pop&…

sqlite 常见命令 表结构

在 SQLite 中&#xff0c;将表结构保存为 SQL 具有一定的便捷性和重要性&#xff0c;原因如下 便捷性&#xff1a; 备份和恢复&#xff1a;将表结构保存为 SQL 可以方便地进行备份。如果需要还原或迁移数据库&#xff0c;只需执行保存的 SQL 脚本&#xff0c;就可以重新创建表…

深度学习-基于机器学习的情绪分析研究

概要 互联网技术的迅速发展使得社交平台逐渐成为热点事件中社会情感的枢纽。社会热点事件的舆论监管的其中一个重要环节就是能够准确分析民众的社会情绪。本文旨在探索可以基于文本大数据彻底分析民众对热点事件的社会情绪的模型和方法。先是从社交平台上借助文本大数据、对数据…

261:vue+openlayers 使用setRotation旋转地图

第261个 点击查看专栏目录 本示例介绍演示如何在vue+openlayers中使用setRotation旋转地图。setRotation是view的一个方法,旋转的内容是弧度,这里设置的角度需要将其换算为弧度,即 x*Math.PI/180. 直接复制下面的 vue+openlayers源代码,操作2分钟即可运行实现效果 文章目…

Linux学习方法-框架学习法——Linux系统框架

配套视频学习链接&#xff1a;https://www.bilibili.com/video/BV1HE411w7by?p2&vd_sourced488bc722b90657aaa06a1e8647eddfc 目录 Linux系统框架(从裸机到OS) Linux可看成是一个大软件/大程序 应用和驱动 内核态和用户态 Linux的文件系统 Linux初学者首先要搞清楚三…

Linux第78步_使用原子整型操作来实现“互斥访问”共享资源

使用原子操作来实现“互斥访问”LED灯设备&#xff0c;目的是每次只允许一个应用程序使用LED灯。 1、创建MyAtomicLED目录 输入“cd /home/zgq/linux/Linux_Drivers/回车” 切换到“/home/zgq/linux/Linux_Drivers/”目录 输入“mkdir MyAtomicLED回车”&#xff0c;创建MyA…