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

单链表,咕咕咕

1.引入单链表

顺序表对于中间或者头部的删除,时间复杂度为O(N),增容需要申请新的空间,拷贝数据,释放就空间,消耗。增容一般是2倍的增长,会有空间的浪费。为了解决这些问题,引入了单链表。

2.单链表

链表是一种物理存储结构上非连续的,非顺序的存储结构,逻辑结构上通过链表中指针链接实现连续性。类似火车头,节。与顺序表不同的是,链表的每一结点都是独立申请的空间,结点一般包含当前结点要保存的数据与下一个结点的地址,一般是从堆上申请。

struct SListNode
{
int data;
struct SListNode* next;
};

这就是一个结点的结构体。

3.单链表的实现

#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
typedef int sl;
typedef struct slist
{sl data;struct slist* next;
}listnode;
//申请一个节点
listnode* buylistnode(sl x)
{listnode* node=(listnode*)malloc(sizeof(listnode));if(node==NULL){perror("buylistnode");exit(-1);}node->next=NULL;node->data=x;return node;
}
//单链表打印
void listprint(listnode* p)
{while(p){printf("%d",p->data);p=p->next;}
}
//单链表尾插,为了改变真正的链表,要用二重指针。
//一重指针保存了数据的地址,我们要改变的是指针本身,不是它保存的地址,而是它本身的地址
void slpushback(listnode** pp,sl x)
{assert(pp);//头结点本身的地址不能为空,但是头结点保存的地址可以为空(起初链表为空)listnode* newnode=buylistnode(x);
//如果只有一个节点,那么直接在后面插入if(*pp==NULL){
*pp=newnode;}else{listnode* tail=*pp;while(tail->next){tail=tail->next;}tail->next=newnode;}
}
//单链表头插
void slpushfront(listnode** pp,sl x)
{assert(pp);listnode* newnode=buylistnode(x);newnode->next=*pp;*pp=newnode;
}
//单链表尾删
void slpopback(listnode** pp)
{assert(pp&&*pp);listnode* prev=NULL;listnode* tail=*pp;while(tail->next){
prev=tail;
tail=tail->next;}if(prev==NULL){*pp=NULL;}else{prev->next=NULL;}free(tail);
}
//单链表头删
void slpopfront(listnode** pp)
{assert(pp&&*pp);
//头结点本身的地址不能为空,而且保存的地址也不能为空,不然
//(*pp)->next对空指针解引用就错了listnode* next=(*pp)->next;free(*pp);*pp=next;
}
//单链表查找
listnode* slfind(listnode* p,sl x)
{while(p){if(p->data==x){return p;}p=p->next;}return NULL;
}
//单链表在pos之后插入
void slinsertafter(listnode* pos,sl x)
{assert(pos);listnode* newnode=buylistnode(x);newnode->next=pos->next;pos->next=newnode;
}
//删除pos后的值
void sleraseafter(listnode* pos)
{assert(pos&&pos->next);listnode* n=pos->next;pos->next=n->next;free(n);
}
//pos之前插入
void slinsertfront(listnode** pp,listnode* pos,sl x)
{assert(pp);if(pos==NULL){slpushback(pp,x);return;}listnode* newnode=buylistnode(x);if(*pp==pos){newnode->next=*pp;*pp=newnode;}else{listnode* prev=*pp;while(prev!=NULL&&prev->next!=pos){prev=prev->next;}newnode->next=pos;prev->next=newnode;}
}
//删除pos位置
void slerasepos(listnode** pp,listnode* pos)
{assert(pp&&pos);if(*pp==pos){*pp=pos->next;free(pos);}else{listnode* prev=*pp;while(prev!=NULL&&prev->next!=pos){prev=prev->next;}assert(prev!=NULL);prev->next=pos->next;free(pos);}
}
//删除整个
void slerase(listnode**pp)
{assert(pp);listnode* p=NULL;while(*pp){p=*pp;*pp=(*pp)->next;free(p);}
}
int main()
{return 0;
}

http://www.dtcms.com/a/273954.html

相关文章:

  • 使用 Python 对本地图片进行图像分类
  • 镜像(Mirror/Image)
  • 飞算JavaAI:革新Java开发的智能助手
  • 100G系列光模块产品与应用场景介绍
  • 7.12 note
  • 【实时Linux实战系列】硬实时与软实时设计模式
  • Vue3 Pinia
  • 深入MyBatis:CRUD操作与高级查询实战
  • mac电脑的usr/libexec目录是干什么的?
  • 「Linux命令基础」文本模式系统关闭与重启
  • Linux 内存管理之LRU链表
  • 蓝牙协议栈高危漏洞曝光,攻击可入侵奔驰、大众和斯柯达车载娱乐系统
  • HTTPS安全机制:从加密到证书全解析
  • 意识边界的算法战争—脑机接口技术重构人类认知的颠覆性挑战
  • React 的常用钩子函数在Vue中是如何设计体现出来的。
  • 苹果UI 设计
  • 前端面试专栏-算法篇:23. 图结构与遍历算法
  • 4.丢出异常捕捉异常TryCatch C#例子
  • 使用gdal读取shp及filegdb文件
  • C/C++动态内存管理函数详解:malloc、calloc、realloc与free
  • Launcher3桌面页面布局结构
  • JavaScript加强篇——第四章 日期对象与DOM节点(基础)
  • 基于 HT 技术的智慧交通三维可视化技术架构与实践
  • 全球化 2.0 | 印尼金融科技公司通过云轴科技ZStack实现VMware替代
  • Spring的事务控制——学习历程
  • Kuberneres高级调度01
  • 如何使用Fail2Ban阻止SSH暴力破解
  • ICCV2025接收论文速览(1)
  • 导出word并且插入图片
  • 【C++ 深入解析 C++ 模板中的「依赖类型」】