【数据结构】单链表---C语言版(全网最最最最细!小白必必必必看!!!有图有真相!)(二)

简介: 【数据结构】单链表---C语言版(全网最最最最细!小白必必必必看!!!有图有真相!)(二)

⭕接口7:头删(SLTPopFront)

🚨要注意头删有三种情况:1.没有结点(空链表)、2.一个结点、3.多个结点

链表为空不能头删,所以要进行assert断言

🥰请看代码与注释👇

//头删
void SLTPopFront(SLTNode** pphead)
{
  //没有结点(空链表)
  assert(*pphead);  //链表为空,不能头删
  assert(pphead);
  //一个结点
  if ((*pphead)->next == NULL)
  {
    free(*pphead);
    *pphead = NULL;
  }
  //多个结点
  else
  {
    SLTNode* cur = *pphead;
    *pphead = cur->next;
    free(cur);
  }
}

可以有更简洁高效的写法👇

🥰请看代码与注释👇

//头删
void SLTPopFront(SLTNode** pphead)
{
  //没有结点(空链表)
  assert(*pphead);
  assert(pphead);
  //一个结点
  //多个结点
  SLTNode* cur = *pphead;
  *pphead = (*pphead)->next;
  free(cur);
}

⭕接口8:尾删(SLTPopBack)

🚨要注意尾删同样有三种情况:1.没有结点(空链表)、2.一个结点、3.多个结点

链表为空不能尾删,所以要进行assert断言

🥰请看代码与注释👇

//尾删
void SLTPopBack(SLTNode** pphead)
{
  //没有结点(空链表)
  assert(*pphead);
  assert(pphead);
  //一个结点
  if ((*pphead)->next == NULL)
  {
    free(*pphead);
    *pphead = NULL;
  }
  //多个结点
  else
  {
    SLTNode* tail = *pphead;
    //找尾
    while (tail->next->next)
    {
      tail = tail->next;
    }
    free(tail->next);
    tail->next = NULL;
  }
}

⭕接口9:查找(SLTFind)

通过遍历进行查找,通常与修改结合联系使用

🥰请看代码与注释👇

//查找
SLTNode* SLTFind(SLTNode* phead, SLTDataType x)
{
  assert(phead);
  SLTNode* cur = phead;
  while (cur)
  {
    if (cur->data == x)
    {
      return cur;
    }
    else
    {
      cur = cur->next;
    }
  }
  return NULL;
}

⭕接口10:修改(SLTModify)

🥰请看代码与注释👇

//修改
void SLTModify(SLTNode* phead, SLTNode* pos, SLTDataType x)
{
  assert(phead);
  assert(pos);
  pos->data = x;
}

⭕接口11:在pos位置之前插入数据(SLTInsert)

🥰请看代码与注释👇

//在pos位置之前插入数据
void SLTInsert(SLTNode** pphead, SLTNode* pos, SLTDataType x)
{
  assert(pphead);
  assert(pos);  //防止给的位置为 空
  if (*pphead == pos)
  {
    SLTPushFront(pphead, x);
  }
  else
  {
    SLTNode* prev = *pphead;
    while (prev->next != pos)
    {
      prev = prev->next;
    }
    SLTNode* newnode = BuyLTNode(x);
    prev->next = newnode;
    newnode->next = pos;
  }
}

⭕接口12:在pos位置之后插入数据(SLTInsertAfter)

🥰请看代码与注释👇

//在pos位置之后插入数据
void SLTInsertAfter(SLTNode* pos, SLTDataType x)
{
  assert(pos);  //防止给的位置为 空
  SLTNode* newnode = BuyLTNode(x);
  newnode->next = pos->next;
  pos->next = newnode;
}

⭕接口13:删除pos位置的值(SLTErase)

🥰请看代码与注释👇

//删除pos位置的值
void SLTErase(SLTNode** pphead, SLTNode* pos)
{
  assert(pphead);
  assert(pos);  //防止给的位置为 空
  if (*pphead == pos)
  {
    SLTPopFront(pphead);
  }
  else
  {
    SLTNode* prev = *pphead;
    while (prev->next != pos)
    {
      prev = prev->next;
    }
    prev->next = pos->next;
    free(pos);
  }
}

⭕接口14:删除pos位置之后的值(SLTEraseAfter)

🥰请看代码与注释👇

//删除pos位置之后的值
void SLTEraseAfter(SLTNode* pos)
{
  assert(pos);
  assert(pos->next);
  SLTNode* next = pos->next;
  pos->next = next->next;
  free(next);
}

🐸四、完整代码

🥝SList.h

#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
//自定义类型
typedef int SLTDataType;
//创建单链表
typedef struct SListNode
{
  SLTDataType data;
  struct SListNode* next;
}SLTNode;
//打印
void SLTPrint(SLTNode* phead);
//释放
void SLTDestroy(SLTNode** pphead);
//创建新结点
SLTNode* BuyLTNode(SLTDataType x);
//头插
void SLTPushFront(SLTNode** pphead, SLTDataType x);
//尾插
void SLTPushBack(SLTNode** pphead, SLTDataType x);
//头删
void SLTPopFront(SLTNode** pphead);
//尾删
void SLTPopBack(SLTNode** pphead);
//查找
SLTNode* SLTFind(SLTNode* phead, SLTDataType x);
//修改
void SLTModify(SLTNode* phead, SLTNode* pos, SLTDataType x);
//在pos位置之前插入数据
void SLTInsert(SLTNode** pphead, SLTNode* pos, SLTDataType x);
//在pos位置之后插入数据
void SLTInsertAfter(SLTNode* pos, SLTDataType x);
//删除pos位置的值
void SLTErase(SLTNode** pphead, SLTNode* pos);
//删除pos位置之后的值
void SLTEraseAfter(SLTNode* pos);

🥝SList.c

#include"SList.h"
//打印
void SLTPrint(SLTNode* phead)
{
  SLTNode* cur = phead;
  while (cur != NULL)
  {
    printf("%d-> ", cur->data);
    cur = cur->next;
  }
  printf("NULL\n");
}
//释放
void SLTDestroy(SLTNode** pphead)
{
  assert(pphead);
  SLTNode* cur = *pphead;
  while (cur)
  {
    SLTNode* next = cur->next;
    free(cur);
    cur = next;
  }
  *pphead = NULL;
}
//创建新结点
SLTNode* BuyLTNode(SLTDataType x)
{
  SLTNode* newnode = (SLTNode*)malloc(sizeof(SLTNode));
  if (newnode == NULL)
  {
    perror("mallic fail");
    return;
  }
  newnode->data = x;
  newnode->next = NULL;
  return newnode;
}
//头插
void SLTPushFront(SLTNode** pphead, SLTDataType x)
{ 
  assert(pphead);   //链表为空,pphead也不为空,因为他是头指针plist的地址
                    // *pphead 不能断言,链表为空,也需要能插入
  SLTNode* newnode = BuyLTNode(x);
  newnode->next = *pphead;
  *pphead = newnode;
}
//尾插
void SLTPushBack(SLTNode** pphead, SLTDataType x)
{
  assert(pphead);
  SLTNode* newnode = BuyLTNode(x);
  //1.空链表
  //2.非空链表
  if (*pphead == NULL)
  {
    *pphead = newnode;    //改变的结构体的指针plist(用结构体指针的地址)
  }
  else
  {
    SLTNode* tail = *pphead;
    while (tail->next != NULL)
    {
      tail = tail->next;
    }
    tail->next = newnode;    //改变的结构体尾结点
  }
}
//头删
void SLTPopFront(SLTNode** pphead)
{
  //没有结点(空链表)
  assert(*pphead);  //链表为空,不能头删
  assert(pphead);
  //一个结点
  if ((*pphead)->next == NULL)
  {
    free(*pphead);
    *pphead = NULL;
  }
  //多个结点
  else
  {
    SLTNode* cur = *pphead;
    *pphead = cur->next;
    free(cur);
  }
}
//头删
//void SLTPopFront(SLTNode** pphead)
//{
//  //没有结点(空链表)
//  assert(*pphead);
//  assert(pphead);
//
//  //一个结点
//  //多个结点
//  SLTNode* cur = *pphead;
//  *pphead = (*pphead)->next;
//  free(cur);
//}
//尾删
void SLTPopBack(SLTNode** pphead)
{
  //没有结点(空链表)
  assert(*pphead);
  assert(pphead);
  //一个结点
  if ((*pphead)->next == NULL)
  {
    free(*pphead);
    *pphead = NULL;
  }
  //多个结点
  else
  {
    SLTNode* tail = *pphead;
    //找尾
    while (tail->next->next)
    {
      tail = tail->next;
    }
    free(tail->next);
    tail->next = NULL;
  }
}
//查找
SLTNode* SLTFind(SLTNode* phead, SLTDataType x)
{
  assert(phead);
  SLTNode* cur = phead;
  while (cur)
  {
    if (cur->data == x)
    {
      return cur;
    }
    else
    {
      cur = cur->next;
    }
  }
  return NULL;
}
//修改
void SLTModify(SLTNode* phead, SLTNode* pos, SLTDataType x)
{
  assert(phead);
  assert(pos);
  pos->data = x;
}
//在pos位置之前插入数据
void SLTInsert(SLTNode** pphead, SLTNode* pos, SLTDataType x)
{
  assert(pphead);
  assert(pos);  //防止给的位置为 空
  if (*pphead == pos)
  {
    SLTPushFront(pphead, x);
  }
  else
  {
    SLTNode* prev = *pphead;
    while (prev->next != pos)
    {
      prev = prev->next;
    }
    SLTNode* newnode = BuyLTNode(x);
    prev->next = newnode;
    newnode->next = pos;
  }
}
//在pos位置之后插入数据
void SLTInsertAfter(SLTNode* pos, SLTDataType x)
{
  assert(pos);  //防止给的位置为 空
  SLTNode* newnode = BuyLTNode(x);
  newnode->next = pos->next;
  pos->next = newnode;
}
//删除pos位置的值
void SLTErase(SLTNode** pphead, SLTNode* pos)
{
  assert(pphead);
  assert(pos);  //防止给的位置为 空
  if (*pphead == pos)
  {
    SLTPopFront(pphead);
  }
  else
  {
    SLTNode* prev = *pphead;
    while (prev->next != pos)
    {
      prev = prev->next;
    }
    prev->next = pos->next;
    free(pos);
  }
}
//删除pos位置之后的值
void SLTEraseAfter(SLTNode* pos)
{
  assert(pos);
  assert(pos->next);
  SLTNode* next = pos->next;
  pos->next = next->next;
  free(next);
}

🥝Test.c

#include"SList.h"
//头插测试
void TestSList01()
{
  SLTNode* plist = NULL;
  SLTPushFront(&plist, 1);
  SLTPushFront(&plist, 2);
  SLTPushFront(&plist, 3);
  SLTPushFront(&plist, 4);
  SLTPrint(plist);
  SLTDestroy(&plist);
}
//尾插测试
void TestSList02()
{
  SLTNode* plist = NULL;
  SLTPushFront(&plist, 1);
  SLTPushFront(&plist, 2);
  SLTPushFront(&plist, 3);
  SLTPushFront(&plist, 4);
  SLTPushBack(&plist, 5);
  SLTPushBack(&plist, 6);
  SLTPushBack(&plist, 7);
  SLTPrint(plist);
  SLTDestroy(&plist);
}
//头删测试
void TestSList03()
{
  SLTNode* plist = NULL;
  SLTPushFront(&plist, 1);
  SLTPushFront(&plist, 2);
  SLTPushFront(&plist, 3);
  SLTPushFront(&plist, 4);
  SLTPrint(plist);
  SLTPopFront(&plist);
  SLTPrint(plist);
  SLTPopFront(&plist);
  SLTPrint(plist);
  SLTPopFront(&plist);
  SLTPrint(plist);
  SLTPopFront(&plist);
  SLTPrint(plist);
  SLTDestroy(&plist);
}
//尾删测试
void TestSList04()
{
  SLTNode* plist = NULL;
  SLTPushFront(&plist, 1);
  SLTPushFront(&plist, 2);
  SLTPushFront(&plist, 3);
  SLTPushFront(&plist, 4);
  SLTPrint(plist);
  SLTPopBack(&plist);
  SLTPrint(plist);
  SLTPopBack(&plist);
  SLTPrint(plist);
  SLTPopBack(&plist);
  SLTPrint(plist);
  SLTPopBack(&plist);
  SLTPrint(plist);
  SLTDestroy(&plist);
}
//查找修改测试
void TestSList05()
{
  SLTNode* plist = NULL;
  SLTPushFront(&plist, 1);
  SLTPushFront(&plist, 2);
  SLTPushFront(&plist, 3);
  SLTPushFront(&plist, 4);
  SLTPrint(plist);
  SLTNode* pos = SLTFind(plist, 3);
  if (pos)
  {
    SLTModify(plist, pos, 8);
  }
  SLTPrint(plist);
  SLTDestroy(&plist);
}
//在pos位置之前插入数据测试
void TestSList06()
{
  SLTNode* plist = NULL;
  SLTPushFront(&plist, 1);
  SLTPushFront(&plist, 2);
  SLTPushFront(&plist, 3);
  SLTPushFront(&plist, 4);
  SLTPrint(plist);
  SLTNode* pos = SLTFind(plist, 3);
  if (pos)
  {
    SLTInsert(&plist, pos, 30);
  }
  SLTPrint(plist);
  SLTDestroy(&plist);
}
//在pos位置之后插入数据测试
void TestSList07()
{
  SLTNode* plist = NULL;
  SLTPushFront(&plist, 1);
  SLTPushFront(&plist, 2);
  SLTPushFront(&plist, 3);
  SLTPushFront(&plist, 4);
  SLTPrint(plist);
  SLTNode* pos = SLTFind(plist, 2);
  if (pos)
  {
    SLTInsertAfter(pos, 20);
  }
  SLTPrint(plist);
  SLTDestroy(&plist);
}
//删除pos位置的值测试
void TestSList08()
{
  SLTNode* plist = NULL;
  SLTPushFront(&plist, 1);
  SLTPushFront(&plist, 2);
  SLTPushFront(&plist, 3);
  SLTPushFront(&plist, 4);
  SLTPrint(plist);
  SLTNode* pos = SLTFind(plist, 3);
  if (pos)
  {
    SLTErase(&plist,pos);
  }
  SLTPrint(plist);
  SLTDestroy(&plist);
}
//删除pos位置之后的值测试
void TestSList09()
{
  SLTNode* plist = NULL;
  SLTPushFront(&plist, 1);
  SLTPushFront(&plist, 2);
  SLTPushFront(&plist, 3);
  SLTPushFront(&plist, 4);
  SLTPrint(plist);
  SLTNode* pos = SLTFind(plist, 2);
  if (pos)
  {
    SLTEraseAfter(pos);
  }
  SLTPrint(plist);
  SLTDestroy(&plist);
}
int main()
{
  //TestSList01();
  //TestSList02();
  //TestSList03();
  //TestSList04();
  //TestSList05();
  //TestSList06();
  //TestSList07();
  //TestSList08();
  //TestSList09();
  return 0;
}

😍这期内容些许复杂,需要慢慢理解消化哦!

总结🥰
以上就是 【数据结构】单链表—C语言版 的全部内容啦🥳🥳🥳🥳
本文章所在【数据结构与算法】专栏,感兴趣的烙铁可以订阅本专栏哦🥳🥳🥳
前途很远,也很暗,但是不要怕,不怕的人面前才有路。💕💕💕
小的会继续学习,继续努力带来更好的作品😊😊😊
创作写文不易,还多请各位大佬uu们多多支持哦🥰🥰🥰

目录
相关文章
|
18天前
|
测试技术 C语言
数据结构学习记录——树习题—Tree Traversals Again(题目描述、输入输出示例、解题思路、解题方法C语言、解析)
数据结构学习记录——树习题—Tree Traversals Again(题目描述、输入输出示例、解题思路、解题方法C语言、解析)
15 1
|
11天前
|
C语言 C++
【数据结构】C语言实现:栈(Stack)与队列(Queue)
【数据结构】C语言实现:栈(Stack)与队列(Queue)
|
18天前
|
算法 C语言
数据结构和算法——归并排序(有序子列的归并、递归算法、非递归算法、思路图解、C语言代码)
数据结构和算法——归并排序(有序子列的归并、递归算法、非递归算法、思路图解、C语言代码)
11 0
|
18天前
|
存储 算法 安全
数据结构学习记录——图应用实例-拯救007(问题描述、解题思路、伪代码解读、C语言算法实现)
数据结构学习记录——图应用实例-拯救007(问题描述、解题思路、伪代码解读、C语言算法实现)
17 0
|
18天前
|
算法
数据结构和算法学习记录——线性表之单链表(下)-头插函数、尾删函数、头删函数、查找函数、pos位置插入&删除数据、单链表销毁
数据结构和算法学习记录——线性表之单链表(下)-头插函数、尾删函数、头删函数、查找函数、pos位置插入&删除数据、单链表销毁
10 0
|
18天前
|
存储 算法
数据结构和算法学习记录——线性表之单链表(上)-初始单链表及其尾插函数(顺序表缺陷、单链表优点、链表打印)
数据结构和算法学习记录——线性表之单链表(上)-初始单链表及其尾插函数(顺序表缺陷、单链表优点、链表打印)
15 0
|
19天前
数据结构——栈(C语言版)
数据结构——栈(C语言版)
11 0
|
10天前
数据结构——栈和队列
数据结构——栈和队列
12 1
|
13天前
|
存储 算法 调度
数据结构与算法-栈篇
数据结构与算法-栈篇
14 3
|
4天前
|
C++
【洛谷 P1044】[NOIP2003 普及组] 栈 题解(递归+记忆化搜索)
**NOIP2003普及组栈问题**:给定操作数序列1到n,仅允许push(进栈)和pop(出栈)操作。目标是计算所有可能的输出序列总数。输入包含一个整数n(1≤n≤18)。示例输入3,输出5。当队列空时返回1,栈空则只能入栈,栈非空时可入栈或出栈。AC C++代码利用记忆化搜索求解。
8 1

热门文章

最新文章