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

宠物出售的网站怎么做网站开发 图片服务器

宠物出售的网站怎么做,网站开发 图片服务器,怎么做产品网站,足球最新比赛消息🔥个人主页:草莓熊Lotso 🎬作者简介:C研发方向学习者 📖个人专栏: 《C语言》 《数据结构与算法》《C语言刷题集》《Leetcode刷题指南》 ⭐️人生格言:生活是默默的坚持,毅力是永久的…

🔥个人主页:@草莓熊Lotso

🎬作者简介:C++研发方向学习者

📖个人专栏: 《C语言》 《数据结构与算法》《C语言刷题集》《Leetcode刷题指南》

⭐️人生格言:生活是默默的坚持,毅力是永久的享受。  

前言:前面我们完成了顺序表的学习以及代码实现,大家一定要自己去实现一遍试试看并且画图理解。那么这篇博客我将会继续为大家分享单链表的定义以及其中打印,尾插,头擦,尾删,头删等接口的实现。还是一样,先分部分实现,最后展式总的代码。


目录

一.单链表的概念

二.单链表的打印

三.单链表的尾插

四.单链表的头插 

五.单链表的尾删

六.单链表的头删

七.代码展现

SList.h:

SList.c:

 test.c:


一.单链表的概念

--在之前我们学习了逻辑结构和物理结构都是线性的顺序表,但是我们会发现顺序表有以下3个比较明显的缺陷

  1. 中间/头部的插入删除,时间复杂度为O(N)
  2. 增容需要申请新空间,拷贝数据,释放旧空间,有不小的消耗
  3. 增容一般呈两倍的增长,会有一定的空间浪费

那么我们的链表刚好可以使头部插入删除的时间复杂度为O(1),不需要增容也不存在空间的浪费。但是这里需要声明一下,每个数据结构都是有它的优势和缺陷的。

链表:链表是一种是一种物理存储结构上非连续,非顺序的存储结构,但它的逻辑结构还是线性的。我们可以把链表想象成火车的一节节车厢链接在一起,具体形式如同所示这里不过多的去讲解了,这里的图是逻辑结构,正常来说链表不一定是这样连续的,而是在堆区中随意存放的,通过存储的地址找到下一个结点。

我们今天一起来实现一个单链表,链表是由一个一个节点组成的,它的节点由两个组成部分

  1. 保存的数据
  2. 指针,存放的是下一个结点的地址 

我们先在.h文件中定义一个单链表,分3个文件以及重命名的好处啥的在顺序表中都讲过了,这里就不说了。

#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>typedef int SLTDataType;
typedef struct SListNode
{SLTDataType data;struct SListNode* next;
}SLTNode;

二.单链表的打印

 --为了方便后续的观察,我们先来实现一个单链表的打印

SList.c:

//打印
void SLTPrint(SLTNode* phead)
{SLTNode* pcur = phead;//移动pcur,保证头指针phead位置不变while (pcur!= NULL){printf("%d -> ", pcur->data);pcur = pcur->next;//pcur往前走}printf("NULL\n");
}

重点提示:

 打印的实现还是很简单的,这里先用一个pcur指针存下头指针,移动它去打印,打印完一个数据后就利用pcur->next往前走,直到pcur==NULL。

--我们在test.c文件中创建几个节点,并且把它们打印出来看看吧,一定注意看注释 

test.c: 

#include"SList.h"int test1()
{//创建节点SLTNode* node1 = (SLTNode*)malloc(sizeof(SLTNode));//申请一个节点大小的空间SLTNode* node2 = (SLTNode*)malloc(sizeof(SLTNode));SLTNode* node3 = (SLTNode*)malloc(sizeof(SLTNode));SLTNode* node4 = (SLTNode*)malloc(sizeof(SLTNode));node1->data = 1;node2->data = 2;node3->data = 3;node4->data = 4;node1->next = node2;node2->next = node3;node3->next = node4;node4->next = NULL;//打印SLTNode* plist = node1;//头结点SLTPrint(plist);
}int main()
{test1();return 0;
}

--测试完成没问题,能正确打印出想要的链表 ,退出码为0。


三.单链表的尾插

--在实现单链表的尾插之前,我们先封装一个申请新节点的函数,后续头插等接口的实现也会用上

//申请新节点
SLTNode* SLTBuyNode(SLTDataType x)
{SLTNode* newcode = (SLTNode*)malloc(sizeof(SLTNode));newcode->data = x;newcode->next = NULL;return newcode;
}

SList.c:

//尾插
void SLTPushBack(SLTNode** pphead, SLTDataType x)
{//申请新节点SLTNode* newcode =SLTBuyNode(x);//如果头节点为空if (*pphead == NULL){*pphead = newcode;}else {SLTNode* ptail = *pphead;//找到尾节点while (ptail->next != NULL){ptail = ptail->next;}//找到了之后链接新节点ptail->next = newcode;}
}

重点提示: 

  • 我们先判断当头结点为空时,是无法直接尾插的,我们直接令新节点为头结点就行了
  • 再就是我们需要找到尾结点,利用ptail从头开始往后找,如图所示,直到ptail->next==NULL时结束
  • 找到尾结点后,将新节点链接上去就行了
  • 还有就是传参数的时候,一定要传的是plist的地址,用二级指针接收。这样形参的修改才能影响实参的修改

test.c:

#include"SList.h"int test1()
{//创建节点SLTNode* node1 = (SLTNode*)malloc(sizeof(SLTNode));//申请一个节点大小的空间SLTNode* node2 = (SLTNode*)malloc(sizeof(SLTNode));SLTNode* node3 = (SLTNode*)malloc(sizeof(SLTNode));SLTNode* node4 = (SLTNode*)malloc(sizeof(SLTNode));node1->data = 1;node2->data = 2;node3->data = 3;node4->data = 4;node1->next = node2;node2->next = node3;node3->next = node4;node4->next = NULL;//打印SLTNode* plist = node1;//头结点SLTPrint(plist);
}void test2()
{//头结点SLTNode* plist =NULL;//尾插SLTPushBack(&plist, 1);SLTPushBack(&plist, 2);SLTPushBack(&plist, 3);SLTPushBack(&plist, 4);SLTPrint(plist);
}
int main()
{//test1();test2();return 0;
}

--测试完成,打印没有问题,退出码为0。 


四.单链表的头插 

SList.c:

//头插
void SLTPushFront(SLTNode** pphead, SLTDataType x)
{assert(pphead);//申请新节点SLTNode* newcode = SLTBuyNode(x);newcode->next = *pphead;*pphead = newcode;
}

重点提示:

先断言一下pphead不能为空,再就是先用申请的新节点链接上原来的头指针,再令新节点成为头指针就可以了

test.c: 

#include"SList.h"int test1()
{//创建节点SLTNode* node1 = (SLTNode*)malloc(sizeof(SLTNode));//申请一个节点大小的空间SLTNode* node2 = (SLTNode*)malloc(sizeof(SLTNode));SLTNode* node3 = (SLTNode*)malloc(sizeof(SLTNode));SLTNode* node4 = (SLTNode*)malloc(sizeof(SLTNode));node1->data = 1;node2->data = 2;node3->data = 3;node4->data = 4;node1->next = node2;node2->next = node3;node3->next = node4;node4->next = NULL;//打印SLTNode* plist = node1;//头结点SLTPrint(plist);
}void test2()
{//头结点SLTNode* plist =NULL;//尾插SLTPushBack(&plist, 1);SLTPushBack(&plist, 2);SLTPushBack(&plist, 3);SLTPushBack(&plist, 4);SLTPrint(plist);//头插SLTPushFront(&plist, 5);SLTPrint(plist);
}
int main()
{//test1();test2();return 0;
}

--测试完成,打印没有问题,退出码为0


五.单链表的尾删

SList.c:

//尾删
void SLTPopBack(SLTNode** pphead)
{//链表不能为空assert(pphead && *pphead);//只有一个节点时if ((*pphead)->next == NULL){free(*pphead);*pphead = NULL;}else {SLTNode* prev = NULL;SLTNode* ptail = *pphead;//找到尾结点以及尾节点的前一个节点while (ptail->next != NULL){prev = ptail;ptail = ptail->next;}//prev ptailprev->next = NULL;free(ptail);ptail = NULL;}
}

重点提示: 

  • 首先是断言,pphead不能为空,链表也不可以为空
  • 特别判断只有一个节点的情况,这题我们还需要找到尾结点的前一个结点,如果只有一个节点的话直接释放掉就好了
  • 找尾节点的同时找到尾节点的前一个节点,每次尾节点向前走之前,先让prev指向其原来的位置
  • 最后直接让prev->next=NULL,释放掉ptail就好了

test.c:

#include"SList.h"int test1()
{//创建节点SLTNode* node1 = (SLTNode*)malloc(sizeof(SLTNode));//申请一个节点大小的空间SLTNode* node2 = (SLTNode*)malloc(sizeof(SLTNode));SLTNode* node3 = (SLTNode*)malloc(sizeof(SLTNode));SLTNode* node4 = (SLTNode*)malloc(sizeof(SLTNode));node1->data = 1;node2->data = 2;node3->data = 3;node4->data = 4;node1->next = node2;node2->next = node3;node3->next = node4;node4->next = NULL;//打印SLTNode* plist = node1;//头结点SLTPrint(plist);
}void test2()
{//头结点SLTNode* plist =NULL;//尾插SLTPushBack(&plist, 1);SLTPushBack(&plist, 2);SLTPushBack(&plist, 3);SLTPushBack(&plist, 4);SLTPrint(plist);//头插SLTPushFront(&plist, 5);SLTPrint(plist);//尾删SLTPopBack(&plist);SLTPrint(plist);
}
int main()
{//test1();test2();return 0;
}

--测试完成,删掉了4,打印没有问题,退出码为0


六.单链表的头删

SList.c:

//头删
void SLTPopFront(SLTNode** pphead)
{//链表不能为空assert(pphead && *pphead);SLTNode* next = (*pphead)->next;free(*pphead);*pphead = next;
}

重点提示: 

断言和尾删一样,这里主要就是先定义一个next记录phead的下一个节点,再直接free掉*pphead。最后让next成为新的头节点就可以了

test.c:

#include"SList.h"int test1()
{//创建节点SLTNode* node1 = (SLTNode*)malloc(sizeof(SLTNode));//申请一个节点大小的空间SLTNode* node2 = (SLTNode*)malloc(sizeof(SLTNode));SLTNode* node3 = (SLTNode*)malloc(sizeof(SLTNode));SLTNode* node4 = (SLTNode*)malloc(sizeof(SLTNode));node1->data = 1;node2->data = 2;node3->data = 3;node4->data = 4;node1->next = node2;node2->next = node3;node3->next = node4;node4->next = NULL;//打印SLTNode* plist = node1;//头结点SLTPrint(plist);
}void test2()
{//头结点SLTNode* plist =NULL;//尾插SLTPushBack(&plist, 1);SLTPushBack(&plist, 2);SLTPushBack(&plist, 3);SLTPushBack(&plist, 4);SLTPrint(plist);//头插SLTPushFront(&plist, 5);SLTPrint(plist);//尾删SLTPopBack(&plist);SLTPrint(plist);//头删SLTPopFront(&plist);SLTPrint(plist);}
int main()
{//test1();test2();return 0;
}

--测试完成,删掉了头的5打印没问题,退出码为0


七.代码展现

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 SLTPushBack(SLTNode** pphead, SLTDataType x);
//头插
void SLTPushFront(SLTNode** pphead, SLTDataType x);
//尾删
void SLTPopBack(SLTNode * *pphead);
//头删
void SLTPopFront(SLTNode * *pphead);

SList.c:

#include"SList.h"//打印
void SLTPrint(SLTNode* phead)
{SLTNode* pcur = phead;//移动pcur,保证头指针phead位置不变while (pcur!= NULL){printf("%d -> ", pcur->data);pcur = pcur->next;}printf("NULL\n");
}
//申请新节点
SLTNode* SLTBuyNode(SLTDataType x)
{SLTNode* newcode = (SLTNode*)malloc(sizeof(SLTNode));newcode->data = x;newcode->next = NULL;return newcode;
}
//尾插
void SLTPushBack(SLTNode** pphead, SLTDataType x)
{//申请新节点SLTNode* newcode =SLTBuyNode(x);//如果头节点为空if (*pphead == NULL){*pphead = newcode;}else {SLTNode* ptail = *pphead;//找到尾节点while (ptail->next != NULL){ptail = ptail->next;}//找到了之后链接新节点ptail->next = newcode;}
}
//头插
void SLTPushFront(SLTNode** pphead, SLTDataType x)
{assert(pphead);//申请新节点SLTNode* newcode = SLTBuyNode(x);newcode->next = *pphead;*pphead = newcode;
}
//尾删
void SLTPopBack(SLTNode** pphead)
{//链表不能为空assert(pphead && *pphead);//只有一个节点时if ((*pphead)->next == NULL){free(*pphead);*pphead = NULL;}else {SLTNode* prev = NULL;SLTNode* ptail = *pphead;//找到尾结点以及尾节点的前一个节点while (ptail->next != NULL){prev = ptail;ptail = ptail->next;}//prev ptailprev->next = NULL;free(ptail);ptail = NULL;}
}
//头删
void SLTPopFront(SLTNode** pphead)
{//链表不能为空assert(pphead && *pphead);SLTNode* next = (*pphead)->next;free(*pphead);*pphead = next;
}

 test.c:

#include"SList.h"int test1()
{//创建节点SLTNode* node1 = (SLTNode*)malloc(sizeof(SLTNode));//申请一个节点大小的空间SLTNode* node2 = (SLTNode*)malloc(sizeof(SLTNode));SLTNode* node3 = (SLTNode*)malloc(sizeof(SLTNode));SLTNode* node4 = (SLTNode*)malloc(sizeof(SLTNode));node1->data = 1;node2->data = 2;node3->data = 3;node4->data = 4;node1->next = node2;node2->next = node3;node3->next = node4;node4->next = NULL;//打印SLTNode* plist = node1;//头结点SLTPrint(plist);
}void test2()
{//头结点SLTNode* plist =NULL;//尾插SLTPushBack(&plist, 1);SLTPushBack(&plist, 2);SLTPushBack(&plist, 3);SLTPushBack(&plist, 4);SLTPrint(plist);//头插SLTPushFront(&plist, 5);SLTPrint(plist);//尾删SLTPopBack(&plist);SLTPrint(plist);//头删SLTPopFront(&plist);SLTPrint(plist);}
int main()
{//test1();test2();return 0;
}

往期回顾: 

【数据结构初阶】--算法复杂度的深度解析

【数据结构初阶】--顺序表(一)

【数据结构初阶】--顺序表(二)

【数据结构初阶】--顺序表(三)

结语:在这篇博客中,我们完成了单链表的打印,尾/头插,尾/头删这些接口的实现,但是我们单链表还有部分接口没有实现,由于篇幅原因,博主将在下一篇中继续带大家实现单链表指定位置插入,删除,查找,修改等接口。如果文章对你有帮助的话,欢迎评论,点赞,收藏加关注,感谢大家的支持。

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

相关文章:

  • 做任务赚q币的网站深圳企业主页制作
  • 钟表 东莞网站建设脚上起小水泡还很痒是怎么回事
  • CMake学习篇[2]---CMake进阶+非同级目录构建+静态库/动态库链接
  • 手机怎么制作网站教程视频教程网站原图怎么做
  • 天津网站制作报价wordpress get page
  • 网站建设所需的硬软件兰州自媒体公司有哪些
  • 请将已备案网站接入访问主要怎么学的呢
  • 做静态网站有什么建议ui设计的网站
  • 网站开发广告怎么写长春财经学院全国排名
  • 义乌城市建设规划网站合肥网站排名
  • 网站首页策划怎么做明星网页设计范例
  • asp.net mvc 统计网站流量数据jsp做网站组件
  • 泰安百度做网站的wordpress深入浅出
  • 东软实训网站开发学做网站难吗
  • 舆情网站设计wordpress文章阅读数更改
  • 做高考题的网站好看开源企业网站模板
  • 服装网站案例怎么修改网站的源代码
  • wordpress 编辑器引用团购网站seo
  • 做的最好的视频教学网站公司网络推广培训
  • 价格合理的网站建设学生心理健康网站建设论文
  • 福田网站建设标准数据网络营销的流程和方法
  • 医疗网站建设效果中国跨境电商出口平台
  • 贸易公司网站案例做网站公司松江
  • 东莞市建设规划局网站进一步加强舆情管控
  • 济南网站推广¥做下拉去118crwordpress单页下载
  • 技术支持 湖州网站建设即时通讯app开发
  • 网站建设需要在网络上如何实现推荐网站建设公司
  • 微信文章转网站wordpress品牌建设和渠道建设哪个更重要
  • 广东品牌网站建设平台域名空间网站建设
  • 目前我们的网站正在建设中在线做网页的网站