【单链表】大数据,请把它推给还不会单链表的人(下)

本文涉及的产品
云原生大数据计算服务 MaxCompute,5000CU*H 100GB 3个月
云原生大数据计算服务MaxCompute,500CU*H 100GB 3个月
简介: 【单链表】大数据,请把它推给还不会单链表的人

4.尾删:删除单链表尾部的最后一个结点

void SListPopBack(SLTNode** pplist)
{
  if (*pplist == NULL)
  {
    return;
  }
  else if ((*pplist)->next == NULL)
  {
    free(*pplist);
    *pplist = NULL;
  }
  else
  {
    SLTNode* prev = NULL;
    SLTNode* tail = *pplist;
    while (tail->next != NULL)
    {
      prev = tail;
      tail = tail->next;
    }
    free(tail);
    tail = NULL;
    prev->next = NULL;
  }
}

ce9b3a41d610467c8e247985ce9ef49b.png

f056b2d7c6fe471699a4978fbb72470a.png


5.头插:在存储第一个元素的结点前插入一个结点

void SListPushFront(SLTNode** pplist, SLTDataType x)
{
  SLTNode* newnode = BuySLTNode(x);
  newnode->next = *pplist;
  *pplist = newnode;
}

6.头删:删除存储第一个元素的结点

void SListPopFront(SLTNode** pplist)
{
  if (*pplist == NULL)
  {
    return;
  }
  else
  {
    SLTNode* next = (*pplist)->next;
    free(*pplist);
    *pplist = next;
  }
}

ea59364cd36049d6849b1f3b1fe3f76b.png

7.在pos结点后插入一个结点

void SListInsertAfter(SLTNode* pos, SLTDataType x)
{
  assert(pos);
  SLTNode* newnode = BuySLTNode(x);
  newnode->next = pos->next;
  pos->next = newnode;
}

12381cc44d384c98865f6ea0614a0524.png

8.在pos结点后删除一个结点

void SListEraseAfter(SLTNode* pos)
{
  assert(pos);
  if (pos->next == NULL)
  {
    return;
  }
  else
  {
    SLTNode* next = pos->next;
    pos->next = next->next;
    free(next);
  }
}

74c800ca4af84485b68cde59c0629b72.png

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

279625c7eb844afcbf36672e2a174e05.png


10.单链表的销毁

void SLTNodeDestory(SLTNode** pphead)
{
 SLTNode* cur=*pphead;
 while(cur)
 {
  SLTNode* next=cur->next;
  free(cur);
  cur=next;
 }
}

有小伙伴看到这里就可能会问了,为什么单链表的接口这里没有单链表的初始化,那是因为,单链表的初始化和销毁也就是对头指针进行操作,那个一步就能完成,所以在主函数里面就可以完成,可以但没必要创建一个专门的接口去处理。


另外插一句,单链表的头很重要,


例一:如果要想清空一个结点,只用phead=NULL即可,只要头指针还在,队伍还可以重新拉起来,只要青山在,不怕没柴烧;但是要销毁单链表则需要将头指针free掉,这样这个单链表才真正的out了。


例二:只要找到了头指针,就可拉起整个单链表,遍历就可以找到每一个结点。(这就是为什么在一些操作时要始终秉承这不能修改phead这个原则的原因)


小小实战:

请写用无头单链表依次尾插五个数1,2,3,4,5,并且删掉2这个数,并将删除后的链表反转,(暂时还不会写的话合理利用到上面的接口实现哦,相信你能独立写出来)


反转:


before:1-->2-->3-->4-->5-->NULL;


after:5-->4-->3-->2-->1-->NULL;


代码参考:

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
typedef struct SLTNode
{
  int date;
  struct SLTNode* next;
}SLTNode;
SLTNode* BuySLTNode(int e)
{
  SLTNode* newnode = (SLTNode*)malloc(sizeof(SLTNode));
  newnode->date = e;
  newnode->next = NULL;
  return newnode;
}
void SLTNodePushBack(SLTNode** pphead, int e)
{
  SLTNode* newnode = BuySLTNode(e);
  if (*pphead == NULL)
  {
    *pphead = newnode;
  }
  else
  {
    SLTNode* tail = *pphead;
    //尾插找尾
    while (tail->next != NULL)
    {
      tail = tail->next;
    }
    tail->next = newnode;
  }
}
void SLTNodePrint(SLTNode* phead)
{
  SLTNode* cur = phead;
  while (cur != NULL)
  {
    printf("%d->", cur->date);
    cur = cur->next;
  }
  printf("NULL");
  printf("\n");
}
SLTNode* SLTNodeFind(SLTNode* phead, int n)
{
  SLTNode* cur = phead;
  for (int i = 0; i < n; i++)
  {
    cur = cur->next;
  }
  return cur;
}
void SLTNodeErase(SLTNode** pphead, SLTNode*  pos)
{
  SLTNode* prev = *pphead;
  while (prev->next != pos)
  {
    prev = prev->next;
  }
  prev->next = pos->next;
  free(pos);
}
SLTNode* SLT_Reverse(SLTNode* phead)
{
  SLTNode* newphead = NULL;
  SLTNode* cur = phead;
  while (cur)
  {
    SLTNode* next = cur->next;
    cur->next = newphead;
    newphead = cur;
    cur = next;
  }
  return newphead;
}
int main()
{
  SLTNode* phead = NULL;
  SLTNodePushBack(&phead, 1);
  SLTNodePushBack(&phead, 2);
  SLTNodePushBack(&phead, 3);
  SLTNodePushBack(&phead, 4);
  SLTNodePushBack(&phead, 5);
  SLTNodePrint(phead);
  SLTNode* pos=SLTNodeFind(phead, 1);
  SLTNodeErase(&phead, pos);
  SLTNodePrint(phead);
  SLTNode* newphead=SLT_Reverse(phead);
  SLTNodePrint(newphead);
  return 0;
}

打印结果:

78127b8e89a04d728e35a847170908b4.png


相关实践学习
基于Hologres轻松玩转一站式实时仓库
本场景介绍如何利用阿里云MaxCompute、实时计算Flink和交互式分析服务Hologres开发离线、实时数据融合分析的数据大屏应用。
SaaS 模式云数据仓库必修课
本课程由阿里云开发者社区和阿里云大数据团队共同出品,是SaaS模式云原生数据仓库领导者MaxCompute核心课程。本课程由阿里云资深产品和技术专家们从概念到方法,从场景到实践,体系化的将阿里巴巴飞天大数据平台10多年的经过验证的方法与实践深入浅出的讲给开发者们。帮助大数据开发者快速了解并掌握SaaS模式的云原生的数据仓库,助力开发者学习了解先进的技术栈,并能在实际业务中敏捷的进行大数据分析,赋能企业业务。 通过本课程可以了解SaaS模式云原生数据仓库领导者MaxCompute核心功能及典型适用场景,可应用MaxCompute实现数仓搭建,快速进行大数据分析。适合大数据工程师、大数据分析师 大量数据需要处理、存储和管理,需要搭建数据仓库?学它! 没有足够人员和经验来运维大数据平台,不想自建IDC买机器,需要免运维的大数据平台?会SQL就等于会大数据?学它! 想知道大数据用得对不对,想用更少的钱得到持续演进的数仓能力?获得极致弹性的计算资源和更好的性能,以及持续保护数据安全的生产环境?学它! 想要获得灵活的分析能力,快速洞察数据规律特征?想要兼得数据湖的灵活性与数据仓库的成长性?学它! 出品人:阿里云大数据产品及研发团队专家 产品 MaxCompute 官网 https://www.aliyun.com/product/odps&nbsp;
目录
相关文章
|
2月前
|
存储 缓存 算法
链表全景:探索单链表、双向链表与循环链表【实战演练】
链表全景:探索单链表、双向链表与循环链表【实战演练】
37 3
|
2月前
|
存储
【单链表】数据结构单链表的实现
【单链表】数据结构单链表的实现
|
2月前
leetcode:203. 移除链表元素(有哨兵位的单链表和无哨兵位的单链表)
leetcode:203. 移除链表元素(有哨兵位的单链表和无哨兵位的单链表)
24 0
|
17天前
|
存储
链表入门(单链表讲)
链表入门(单链表讲)
链表入门(单链表讲)
|
5天前
|
存储
【海贼王的数据航海】链表—单链表
【海贼王的数据航海】链表—单链表
8 0
|
2月前
|
存储 编译器
单链表与双链表实现
单链表与双链表实现
27 4
|
2月前
特殊链表(循环单链表,循环双链表,静态链表)
特殊链表(循环单链表,循环双链表,静态链表)
23 3
|
25天前
|
算法
数据结构和算法学习记录——线性表之单链表(下)-头插函数、尾删函数、头删函数、查找函数、pos位置插入&删除数据、单链表销毁
数据结构和算法学习记录——线性表之单链表(下)-头插函数、尾删函数、头删函数、查找函数、pos位置插入&删除数据、单链表销毁
23 0
|
25天前
|
存储 算法
数据结构和算法学习记录——线性表之单链表(上)-初始单链表及其尾插函数(顺序表缺陷、单链表优点、链表打印)
数据结构和算法学习记录——线性表之单链表(上)-初始单链表及其尾插函数(顺序表缺陷、单链表优点、链表打印)
16 0
|
2月前
|
Java
DAY-1 | Java数据结构之链表:删除无头单链表中等于给定值 val 的所有节点
力扣203题解:使用时间复杂度为O(n)的思路删除链表中所有值为key的元素。引入辅助指针pre,记录cur的前一个节点,遍历链表时,若cur.val!=key,pre和cur同时前进;若cur.val==key,则pre.next=cur.next,cur继续前进,确保pre不急于跟随以处理连续相同值的情况。遍历结束后,处理头节点可能需要删除的特殊情况。
30 0