【C语言】链表及单链表基本操作

2023-05-16

1、什么是链表?链表的分类?

链表是一种物理存储结构上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。

数据结构中:

在这里插入图片描述

2、链表的分类

共有8种链表结构
在这里插入图片描述

3、单链表的基本操作

类似于顺序表,我们来实现单链表的基本操作,具体见SList.h 代码中语句及注释。

#pragma once
typedef int SDataType;
//链表的节点
typedef struct SListNode
{
 SDataType _data;
 struct SListNode* _PNext;
}Node,*PNode;

typedef struct SList       //封装了链表的结构
{
 PNode _pHead;//指向链表第一个节点
}SList;

void SListInit(SList*s);//链表的初始化

//在链表s最后一个节点后插入一个值为data的节点
void SListPushBack(SList* s, SDataType data);

//删除链表s最后一个节点
void SListPopBack(SList* s);

//在链表s第一个节点前插入值为data的节点
void SListPushFront(SList* s, SDataType data);

//删除链表s的第一个节点
void SListPopFront(SList* s);

//在链表的pos位置后插入值为data的节点
void SListInsert(PNode pos, SDataType data);

//删除链表s中pos位置的节点
void SListErase(SList* s, PNode pos);

// 在链表中查找值为data的节点,找到返回该节点的地址,否则返回NULL 
PNode SListFind(SList* s, SDataType data);

//移除链表中第一个值为data的元素
void SListRemove(SList*s, SDataType data);

// 获取链表中有效节点的个数 
int SListSize(SList* s);

// 检测链表是否为空 
int SListEmpty(SList* s);

// 将链表中有效节点清空 
void SListClear(SList* s);

// 销毁链表 
void SListDestroy(SList* s);
//打印链表
void SListPrint(SList* s);

以下为SList.c具体代码:

#include <stdio.h>
#include "Slist.h"
#include <assert.h>
#include <stdlib.h>
#include <stddef.h>

1.初始化部分,我们只需要将链表的头结点置为NULL即可。

void SListInit(SList*s) {
 assert(s);
 s->_pHead = NULL;
}

2.尾插,首先我们要创建一个新节点,然后判断链表当前是否有节点,若没有,则直接让第一个节点指向新节点,若有,找到最后一个节点,让他指向新节点。

void SListPushBack(SList* s, SDataType data) {
 //找链表最后一个节点
 assert(s);
 PNode pNewNode = BuySListNode(data);
 if (s->_pHead == NULL) {//链表没有节点的情况
  s->_pHead = pNewNode;
 }
 else {
  PNode pCur = s->_pHead;
  while (pCur->_PNext) {
   pCur = pCur->_PNext;
  }
  //让最后一个节点指向新节点
  pCur->_PNext = pNewNode;
 }
}

3.尾删,首先判断链表中有没有节点,若没有,直接返回,若有一个节点,直接让第一个节点指向NULL,若有多个节点,则需要记录下倒数第二个节点,让它指向NULL。

void SListPopBack(SList* s) {
 assert(s);
 if (s->_pHead == NULL) {//链表中没有节点
  return;
 }
 else if (s->_pHead->_PNext == NULL) {//只有一个节点
  free(s->_pHead);
  s->_pHead = NULL;
 }
 else {                           //多个节点
  PNode pCur = s->_pHead;
  PNode pPre = NULL;
  while (pCur->_PNext) {
   pPre = pCur;
   pCur = pCur->_PNext;
  }
  free(pCur);
  pPre->_PNext = NULL;
 }
}

4.头插

void SListPushFront(SList* s, SDataType data) {
 assert(s);
 PNode pNewNode = BuySListNode(data);
 if (s->_pHead == NULL) {//链表为空
  s->_pHead = pNewNode;
 }
 else {
  pNewNode->_PNext = s->_pHead;
  s->_pHead = pNewNode;
 }
}

5.头删

void SListPopFront(SList* s) {
 assert(s);
 if (s->_pHead == NULL) {//链表为空
  return;
 }
 else if (s->_pHead->_PNext == NULL) {//只有一个节点
  free(s->_pHead);
  s->_pHead = NULL;
 }
 else {
  PNode pCur = s->_pHead;
  s->_pHead = pCur->_PNext;
  free(pCur);
 }
}

6.在给定pos位置插入值为data的节点,分两步完成:首先找到pos位置的节点,然后再插入,所以要实现这一个功能需要两个函数来共同完成。

在这里插入图片描述
注意:应该先连接好新节点,再断开原来的指针指向。
插入:

void SListInsert(PNode pos, SDataType data) {
 PNode pNewNode = NULL;
 if (pos == NULL) {
  return;
 }
 pNewNode = BuySListNode(data);
 
 pNewNode->_PNext = pos->_PNext;
 pos->_PNext = pNewNode;
}

查找:

PNode SListFind(SList* s, SDataType data) {
 assert(s);
 PNode pCur = s->_pHead;
 while (pCur) {
  if (pCur->_data == data) {
   return pCur;
  }
  pCur = pCur->_PNext;
 }
 return NULL;
}

7.删除给定pos位置的节点。
在这里插入图片描述

void SListErase(SList* s, PNode pos) {
 assert(s);
 if (pos == NULL || s->_pHead == NULL) {
  return;
 }
 if (pos== s->_pHead) {
  s->_pHead = pos->_PNext;
 }
 else {
  PNode pPrePos = s->_pHead;
  while (pPrePos&&pPrePos->_PNext != pos) {
   pPrePos = pPrePos->_PNext;
  }
  pPrePos->_PNext = pos->_PNext;
 }
 free(pos);
}

8.删除第一个值为data的节点。要分三种情况:链表为空直接返回、要删除的节点为第一个节点、其它位置的节点。

void SListRemove(SList*s, SDataType data) {
 assert(s);
 if (s->_pHead == NULL) {
  return;
 }
 PNode pPre = NULL;
 PNode pCur = s->_pHead;
 while (pCur) {
  if (pCur->_data == data) {
   if (pCur == s->_pHead) {         //要删除的是第一个位置的节点
    s->_pHead = pCur->_PNext;
   }
   else {
    pPre->_PNext = pCur->_PNext;      //其它位置的情况,让前一个节点指向其后一个节点
   }
   free(pCur);
   return;
  }
  else {
   pPre = pCur;
   pCur = pCur->_PNext;
  }
 }
}

其它:

int SListSize(SList* s) {            //获取链表有效节点的个数
 assert(s);
 int count = 0;
 PNode pCur = s->_pHead;
 while (pCur) {
  count++;
  pCur = pCur->_PNext;
 }
 return count;
}

int SListEmpty(SList* s) {              //检测链表是否为空
 assert(s);
 if (s->_pHead == NULL) {
  return -1;
 }
 return 0;
}

void SListClear(SList* s) {             //清空链表
 assert(s);
 if (s->_pHead == NULL) {
  return;
 }
 PNode pCur = s->_pHead;
 while (pCur->_PNext) {    //循环清空链表中的节点
  PNode Tmp = pCur->_PNext;
  free(pCur);
  pCur = Tmp;
 }
 if (pCur) {      //清空最后一个节点
  free(pCur);
  pCur = NULL;
 }
}

void SListDestroy(SList* s) {            //销毁链表
 assert(s);
 if (s->_pHead == NULL) {
  free(s->_pHead);
  return;
 }
 while (s->_pHead) {    
  PNode Tmp = s->_pHead->_PNext;
  free(s->_pHead);
  s->_pHead = Tmp;
 }
}

void SListPrint(SList* s) {             //打印链表
 assert(s);
 PNode pCur = s->_pHead;
 while (pCur) {
  printf("%d--->", pCur->_data);
  pCur = pCur->_PNext;
 }
 printf("\n");
}
void main() {
 SList s;
 SListInit(&s);
 SListPushBack(&s, 1);
 SListPushBack(&s, 2);
 SListPushBack(&s, 3);
 printf("size=%d\n", SListSize(&s));
 SListPrint(&s);
 SListInsert(SListFind(&s, 2), 0);
 SListPrint(&s);
 SListRemove(&s, 2);
 SListPrint(&s);
  system("pause");
 return;
}

运行结果:
在这里插入图片描述

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【C语言】链表及单链表基本操作 的相关文章

  • MS5611气压传感器手册勘误

    说是勘误其实也不能完全算是勘误 xff0c 只能说是防止各位看官对手册的错误解读 前几天调试MS5611这款气压计 xff0c 按照手册来计算发现无论如何气压值都是不对的 xff0c 比如说我这的1020mbar xff08 前几天用BMP
  • 异常处理方式——抛出处理

    异常的处理方式2 抛出处理 throw throws 抛出处理注意的细节 xff1a 1 如果一个方法内部抛出了一个异常对象 xff0c 那麽必须在方法上声明抛出 2 如果调用了一个声明抛出异常类型的方法 xff0c 那么调用者必须要进行处
  • socket实现UDP通信

    UDP与TCP不同 xff0c 是一种无连接的通信方式 xff0c 相比TCP而言更加灵活 利用socket实现UDP的方式相比TCP而言也更加简单 发送方 xff1a 1 初始化套接字 2 创建socket 3 利用sendto发送数据
  • C语言之#define用法入门详解

    一 define的基本语法 在C语言中 xff0c 常量是使用频率很高的一个量 常量是指在程序运行过程中 xff0c 其值不能被改变的量 常量常使用 define来定义 使用 define定义的常量也称为符号常量 xff0c 可以提高程序的
  • 棋盘格自动生成器——四种格式(格雷码棋盘格、圆点、二维码棋盘格)

    棋盘格生成器可以生成上面四种格式的标定板 想要多大想要几行几列都可以动态设置 非常好用 对于自己写代码或用cad画都比较浪费时间 这个生成器可以立刻生成pdf 只要打印机不设置缩放 即可正常尺寸打印 非常非常好用 介绍给大家这个好用的地址
  • python爬虫-验证码的处理

    在爬取网页数据时 xff0c 经常出现需要登录账户且要输入验证码的情况 以http www santostang com wp login php action 61 register该网页为例 xff0c 需要先使用浏览器的检查功能找到f
  • HTTP协议的解码和编码

    HTTP协议的解码和编码 编码规范URL的编码与解码 编码 规范实战 xff1a 使用fiddler来抓住http请求 相当于各省各地的人说不同的话 xff0c 大家互相听不懂 xff0c 那么http就相当于有一个翻译器 xff0c 能够
  • Linux服务器上请求接口说明

    Linux服务器上请求接口说明 一 参数指令说明 X 指定请求方法 x 指定HTTP请求的代理 H 指定请求标头 d 发送POST请求提交的数据 xff0c 使用 d参数后 xff0c 会自动将请求转为POST xff0c HTTP请求会自
  • 编写一个程序,将两个字符串连接起来,不要用stracat 函数

    可能写的不好 xff0c 希望对你们有帮助 include lt stdio h gt int main int a 61 0 b 61 0 c 61 0 m 61 0 i j char str1 80 str2 80 printf 请输入
  • Linux ulimit命令详解

    ulimit 是一个计算机命令 xff0c 用于shell启动进程所占用的资源 xff0c 可用于修改系统资源限制 命令常用参数 H 设置硬资源限制 S 设置软资源限制 a 显示当前所有的资源限制 c size 设置core文件的最大值 单
  • 几种CAN应用层协议介绍

    一 CanOpen n CAL 提供了所有的网络管理服务和报文传送协议 xff0c 但并 没有定义 CMS 对象的内容或者正在通讯的对象的类 型 而这正是 CANopen 切入点 n CANopen 是在 CAL 基础上开发的 xff0c
  • CImage类

    我们知道 xff0c Visual C 43 43 中的CBitmap类的功能简直太弱小了 xff0c 这曾经让Visual C 43 43 在图像处理方面的功能比较尴尬 之前笔记里面 xff0c 我们采用的CBitmap配合GDI进行透明
  • PTA 7-20 表达式转换 (25分)

    算术表达式有前缀表示法 中缀表示法和后缀表示法等形式 日常使用的算术表达式是采用中缀表示法 xff0c 即二元运算符位于两个运算数中间 请设计程序将中缀表达式转换为后缀表达式 输入格式 输入在一行中给出不含空格的中缀表达式 xff0c 可包
  • Template Mode(模板方法)

    结构化程序 程序库开发人员 class Library public void step1 void step3 void step5 应用程序开发人员 class Application piblic bool Step2 bool St
  • Strategy 模式

    enum TaxBase CN Tax US Tax DE Tax class SaleOrder TaxBase tax public if tax 61 61 CN Tax else if tax 61 61 US Tax else i
  • 观察者模式

    在软件的构建过程中 xff0c 我们需要为某些对象建立一种通知依赖关系 一个对象 xff08 目标对象 xff09 发生改变 所有的依赖对象 xff08 观察者对象 xff09 都将得到通知 xff0c 如果依赖关系过于紧密 xff0c 将
  • matlab数据分类 画直方图

    我是刚刚接触matlab的小白 xff0c 在度娘和广大网友的帮助下终于完成了这个小任务 所以想记录下 xff0c 也希望可以帮助那些学习matlab的人 小任务 xff1a 主要对txt文本里的数据 进行处理下 xff0c 然后通过mat
  • 树莓派跑一个简单c++小程序教程

    我用的是树莓派3代b型 xff0c 所使用的是Debian系统的衍生系统raspbian 对系统不太了解不清楚 树莓派开发c 43 43 程序需要的工具有编辑器vim 调试器gdb 编译器gcc或者g 43 43 xff08 大神飘过就行
  • typedef 函数指针用法

    进入正文 xff1a 代码简化 促进跨平台开发的目的 typedef 行为有点像 define 宏 xff0c 用其实际类型替代同义字 不同点 xff1a typedef 在编译时被解释 xff0c 因此让编译器来应付超越预处理器能力的文本

随机推荐