链表(一) 单链表操作详解

简介: 链表(一) 单链表操作详解

一、什么是链表

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

逻辑结构

物理结构:

  • 链式结构在逻辑上是连续的,但在物理上不一定连续
  • 节点是从堆上申请的空间,按策略分配的,可能连续也可能不连续

二、链表的分类

按照单双链表是否有头是否循环,可以将链表分为八种

1、单向或者双向

2、带头或不带头

3、循环或不循环

三、无头单向不循环链表的实现

代码结构设计:

  • SList.h: 存放链表结构及需要用到的头文件,函数声明等
  • SList.c: 各种操作函数的具体实现

SList.h

#pragma once
#include <stdio.h>
#include<stdlib.h>
#include<assert.h>
typedef int SLTDateType;
typedef struct SListNode
{
  SLTDateType data;
  struct SListNode* next;
}SListNode;
// 动态申请一个节点
SListNode* BuySListNode(SLTDateType x);
// 单链表打印
void SListPrint(SListNode* plist);
// 单链表尾插
void SListPushBack(SListNode** pplist, SLTDateType x);
// 单链表的头插
void SListPushFront(SListNode** pplist, SLTDateType x);
// 单链表的尾删
void SListPopBack(SListNode** pplist);
// 单链表头删
void SListPopFront(SListNode** pplist);
// 单链表查找
SListNode* SListFind(SListNode* plist, SLTDateType x);
// 单链表在pos位置之后插入x
void SListInsertAfter(SListNode* pos, SLTDateType x);
// 单链表删除pos位置之后的值
void SListEraseAfter(SListNode* pos);

SList.c

#include "SList.h"

动态申请一个节点

SListNode* BuySListNode(SLTDateType x)
{
  SListNode* newNode = (SListNode*)malloc(sizeof(SListNode));
  if (newNode == NULL)
  {
    perror("malloc fail");
    exit(-1);
  }
  newNode->data = x;
  newNode->next = NULL;
  return newNode;
}

单链表打印

void SListPrint(SListNode* plist)
{
  SListNode* cur = plist;
  while (cur != NULL)
  {
    printf("%d->", cur->data);
    cur = cur->next;
  }
  printf("NULL\n");
}

单链表尾插

void SListPushBack(SListNode** pplist, SLTDateType x)
{
  //pplist不能为空
  assert(pplist);
  //创建要插入的节点
  SListNode* newNode = BuySListNode(x);
  //链表没有节点时
  if (*pplist == NULL)
  {
    *pplist = newNode;
  }
  //链表有节点时
  else
  {
    SListNode* cur = *pplist;
    //找到链表的最后一个节点
    while (cur->next != NULL)
    {
      cur = cur->next;
    }
    cur->next = newNode;
  }
}

单链表头插

void SListPushFront(SListNode** pplist, SLTDateType x)
{
  //pplist不能为空
  assert(pplist);
  SListNode* newNode = BuySListNode(x);
  newNode->next = *pplist;
  *pplist = newNode;
}

单链表的尾删

void SListPopBack(SListNode** pplist)
{
  assert(pplist);
  //检查链表是否为空
  assert(*pplist);
  //链表只有一个节点
  if ((*pplist)->next == NULL)
  {
    free(*pplist);
    *pplist = NULL;
  }
  else
  {
    SListNode* cur = *pplist;
    //找到倒数第二个节点
    while (cur->next->next != NULL)
    {
      cur = cur->next;
    }
    free(cur->next);
    cur->next = NULL;
  }
}

单链表头删

void SListPopFront(SListNode** pplist)
{
  assert(pplist);
  //检查链表是否为空
  assert(*pplist);
  SListNode* cur = *pplist;
  *pplist = cur->next;
  free(cur);
}

单链表查找

SListNode* SListFind(SListNode* plist, SLTDateType x)
{
  SListNode* cur = plist;
  while (cur != NULL)
  {
    if (cur->data == x)
    {
      return cur;
    }
    cur = cur->next;
  }
  return cur;
}

在pos位置前插入

void SLTInsert(SListNode** pplist, SListNode* pos, SLTDateType x)
{
  assert(pplist);
  assert(pos);
  if (pos == *pplist)
  {
    //在第一个节点前插入即头插
    SLTPushFront(pplist, x);
  }
  else
  {
    SListNode* prev = *pplist;
    while (prev->next != pos)
    {
      prev = prev->next;
    }
    SListNode* newnode = BuySListNode(x);
    prev->next = newnode;
    newnode->next = pos;
  }
}
}

单链表在pos位置之后插入x

void SListInsertAfter(SListNode* pos, SLTDateType x)
{
  assert(pos);
  SListNode* newNode = BuySListNode(x);
  newNode->next = pos->next;
  pos->next = newNode;
}

删除pos位置

void SLTErase(SListNode** pplist, SListNode* pos)
{
  assert(pplist);
  assert(pos);
  if (pos == *pplist)
  {
    //删除第一个节点即头删
    SLTPopFront(pplist);
  }
  else
  {
    SListNode* prev = *pplist;
    while (prev->next != pos)
    {
      prev = prev->next;
    }
    prev->next = pos->next;
    free(pos);
  }
}

单链表删除pos位置之后的值

void SListEraseAfter(SListNode* pos)
{
  assert(pos);
  assert(pos->next);
  SListNode* cur = pos->next->next;
  free(pos->next);
  pos->next = cur;
}

目录
相关文章
|
7月前
|
存储 缓存 算法
链表全景:探索单链表、双向链表与循环链表【实战演练】
链表全景:探索单链表、双向链表与循环链表【实战演练】
87 3
|
7月前
|
存储
【单链表】数据结构单链表的实现
【单链表】数据结构单链表的实现
|
7月前
leetcode:203. 移除链表元素(有哨兵位的单链表和无哨兵位的单链表)
leetcode:203. 移除链表元素(有哨兵位的单链表和无哨兵位的单链表)
43 0
|
3月前
|
存储 算法 C语言
C语言手撕实战代码_循环单链表和循环双链表
本文档详细介绍了用C语言实现循环单链表和循环双链表的相关算法。包括循环单链表的建立、逆转、左移、拆分及合并等操作;以及双链表的建立、遍历、排序和循环双链表的重组。通过具体示例和代码片段,展示了每种算法的实现思路与步骤,帮助读者深入理解并掌握这些数据结构的基本操作方法。
|
6月前
|
存储
链表入门(单链表讲)
链表入门(单链表讲)
链表入门(单链表讲)
|
5月前
链表4(法二)------7-4 sdut-C语言实验-单链表中重复元素的删除
链表4(法二)------7-4 sdut-C语言实验-单链表中重复元素的删除
34 0
|
7月前
|
存储 编译器
单链表与双链表实现
单链表与双链表实现
|
6月前
|
存储
【海贼王的数据航海】链表—单链表
【海贼王的数据航海】链表—单链表
37 0
|
7月前
特殊链表(循环单链表,循环双链表,静态链表)
特殊链表(循环单链表,循环双链表,静态链表)
58 3
|
6月前
|
算法
数据结构和算法学习记录——线性表之单链表(下)-头插函数、尾删函数、头删函数、查找函数、pos位置插入&删除数据、单链表销毁
数据结构和算法学习记录——线性表之单链表(下)-头插函数、尾删函数、头删函数、查找函数、pos位置插入&删除数据、单链表销毁
66 0