当前位置: 首页 > news >正文

链表(1)

目录

单链表

主函数test.c

test1

test2

test3

test4

头文件&函数声明SList.h

函数实现SList.c

打印SLPrint

创建节点CreateNode

尾插SLPushBack

头插SLPushFront

头删SLPopBck

尾删SLPopFront

易错点


本篇开始链表学习。今天主要是单链表&OJ题目。

单链表

前面的博文我们讲了顺序表。顺序表的优势就是【物理空间的连续】,就只需要一个指针指向开始位置,用数组下标去访问即可。但是这也是它的劣势。当插入和删除数据需要挪动数据。

无论是【顺序表】还是【链表】里的数据,任何类型都可。所以用typedef。

在开始阶段,线性表可能是物理空间上连续【顺序表】,可能是逻辑顺序上连续【链表】。链表的优势就是,删除和插入数据不需要挪动,空间可以一块一块的释放,不会影响其他节点。链表每个节点都是独立的。

【链表】的种类很多,今天先介绍【无头单项不循环链表】----【单链表】。

主函数test.c

#include"SList.h"
int main()
{SLNode* phead = NULL;//结构体指针变量存放结构体的地址 头节点test1(&phead);//测试尾插test2(&phead);//测试头插test3(&phead);//测试尾删test4(&phead);//测试头删return 0;
}

test1

void test1(SLNode** pphead)//测试尾插
{SLPushBack(pphead, 10);SLPushBack(pphead, 20);SLPushBack(pphead, 30);SLPushBack(pphead, 40);SLPrint(*pphead);
}

test2

void test2(SLNode** pphead)//测试头插
{SLPushFront(pphead, 77);SLPushFront(pphead, 66);SLPushFront(pphead, 55);SLPushFront(pphead, 33);SLPrint(*pphead);
}

test3

void test3(SLNode** pphead)//测试头删
{SLPopFront(pphead);SLPopFront(pphead);SLPopFront(pphead);SLPrint(*pphead);
}

test4

void test4(SLNode** pphead)//测试尾删
{SLPopBack(pphead);SLPopBack(pphead);SLPrint(*pphead);
}

头文件&函数声明SList.h

#pragma once
#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
  • 创建单链表
//创建单链表
typedef int SLNDataType;//单链表节点数据类型typedef struct SListNode//创建节点
{SLNDataType val;struct SListNode* next;
}SLNode;

?为什么 SListNode 还未创建好,就可以在结构体内部使用这个 SListNode 了

因为next是一个结构体指针变量,主体是指针变量,无影响。但是如果是 struct SListNode next;不可以,结构体嵌套结构体是不可以的。


  •  打印数据
//打印数据
void SLPrint(SLNode* phead);
  • 尾插
//尾插
void SLPushBack(SLNode** pphead, SLNDataType x);
  • 头插
//头插
void SLPushFront(SLNode** pphead, SLNDataType x);
  • 头删
//头删
void SLPopFront(SLNode** pphead);
  • 尾删 
//尾删
void SLPopBack(SLNode** pphead);

函数实现SList.c

#include"SList.h"

打印SLPrint

  • 不要让phead移动
void SLPrint(SLNode* phead)
{assert(phead);SLNode* tail = phead;printf("phead->");while (tail->next != NULL){printf("%d->", tail->val);tail = tail->next;}printf("NULL");printf("\n");
}

创建节点CreateNode

//创建链表的节点---结构体
SLNode* CreateNode(SLNDataType x)
{SLNode* newnode = (SLNode*)malloc(sizeof(SLNode));if (newnode == NULL){perror("malloc");exit(-1);//直接终止程序//return;}newnode->val = x;newnode->next = NULL;return newnode;
}

尾插SLPushBack

  • 二级指针的使用,不然就会链接不起来,出了函数栈帧局部变量就销毁了。
  • 改变外部的变量,一定有一个解引用的操作
  • 多情况的考虑
//尾插
void SLPushBack(SLNode** pphead, SLNDataType x)
{//assert(*pphead);SLNode* newnode = CreateNode(x);//无节点if (*pphead == NULL){*pphead = newnode;}//多个节点else{SLNode* tail = *pphead;while (tail->next != NULL){tail = tail->next;}tail->next = newnode;}}

头插SLPushFront

  • 代码书写的先后顺序
  • 二级指针 
//头插
void SLPushFront(SLNode** pphead, SLNDataType x)
{//assert(*pphead);SLNode* newnode = CreateNode(x);newnode->next = *pphead;*pphead = newnode;
}

头删SLPopBck

  • 代码书写的先后顺序
  • 二级指针 
//头删
void SLPopFront(SLNode** pphead)
{assert(*pphead);SLNode* tail = *pphead;*pphead = (*pphead)->next;free(tail);tail = NULL;
}

 

尾删SLPopFront

  • 多种情况的考虑 
//尾删
void SLPopBack(SLNode** pphead)
{assert(*pphead);//一个节点if ((*pphead)->next == NULL){free(*pphead);*pphead = NULL;}else{SLNode* tail = *pphead;SLNode* prve = tail;while (tail->next != NULL){prve = tail;tail = tail->next;}prve->next = NULL;free(tail);tail = NULL;}
}

 


 

易错点

  • 断言❌
  • 无节点/一个节点/多节点的考虑❌
  • 传值调用/传址调用(二级指针使用)❌
  • 记住:要修改头节点(头节点是结构体指针变量的指向必须用二级指针❌
  • 空间的释放(不是释放指针变量,释放的是指针指向的空间)❌
  • *pphead&*pphead->next辨析❌
  • 野指针的诞生❌

代码---------→【唐棣棣 (TSQXG) - Gitee.com】

联系---------→【邮箱:2784139418@qq.com】

http://www.lryc.cn/news/220949.html

相关文章:

  • 智慧农业:农林牧数据可视化监控平台
  • 知识注入以对抗大型语言模型(LLM)的幻觉11.6
  • 机器人物理交互场景及应用的实际意义
  • Kubernetes Dashboard 用户名密码方式登录
  • Redisson中的对象
  • GNU ld链接器 lang_process()(二)
  • 《国产服务器操作系统发展报告(2023)》重磅发布
  • 【PTE-day03 报错注入】
  • jenkins gitlab CI/CD
  • Java 中的数据类型有哪些?
  • 基于SSM的大学学生成长系统
  • 369B1860G0028 44A730240-G01 IC697ACC722B
  • 系列十一、拦截器(二)#案例演示
  • 数据分析实战 | 关联规则分析——购物车分析
  • maven 添加 checkstyle 插件约束代码规范
  • 什么是MySQL的执行计划(Explain关键字)?
  • 编码格式科普ASCII unicode utf-8 usc-2 GB2312
  • Pycharm中新建一个文件夹下__init__.py文件有什么用
  • OracleBulkCopy c#批量插入oracle数据库的方法
  • 046_第三代软件开发-虚拟屏幕键盘
  • MySQL主从搭建,实现读写分离(基于docker)
  • uni-app android picker选择默认月份
  • Go 接口-契约介绍
  • 变压器试验VR虚拟仿真操作培训提升受训者技能水平
  • Mastering Makefile:模块化编程技巧与经验分享
  • el-input输入校验插件(正则表达式)
  • 【Matplotlib】plt.plot() X轴横坐标展示完整整数坐标
  • 左手 Jira,右手 Polarion,驶入互联网和制造业十字路口的新能源汽车
  • 网络安全(黑客)-0基础小白自学
  • ActiveMQ、RabbitMQ、RocketMQ、Kafka介绍