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

如何选择品牌网站建设网络推广入门教程

如何选择品牌网站建设,网络推广入门教程,wordpress主题 反盗版,网站开发前景如何前言顺序表要求是具有连续的物理空间,并且数据的话是在这些空间当中是连续的存储。但这样会带来很多问题,比如说在头部或者说中间插入的话,效率不是很高;并且申请空间可能需要扩容,并且越往后一般来说都是异地扩容&…

前言

  1. 顺序表要求是具有连续的物理空间,并且数据的话是在这些空间当中是连续的存储。但这样会带来很多问题,比如说在头部或者说中间插入的话,效率不是很高;并且申请空间可能需要扩容,并且越往后一般来说都是异地扩容,虽然看起来的话是简单的调用了一下realloc,但是从底层来看的话,这个代价很大。而且扩容的话也会存在一定程度的浪费,因此就需要链表的存在。

  1. 链表的话是一个数据存一个内存块。这些内存块之间并不一定要求是物理上连续的,这些内存块之间用指针进行相关的链接,链表实际上具有八种结构。

  1. 链表其实就是用指针这么链接起来的一些个内存块。

链表当中各个节点在物理上不一定是连续的,这个节点之间也并没有任何的顺序关系(都是各自随意malloc出来的),根本就不需要去考虑顺序,孤岛之间只需要有一根桥梁即可

单链表就关注这三个有机组成部分:

  1. 节点 SLTNode

  1. 节点地址(指向节点的指针) SLTNode*

  1. 一级指针(指向链表第一个节点) phead

  1. 二级指针(指向上面的一级指针) pphead


逻辑结构与物理结构

  1. 虽然有时候平时画图的时候,画链表的时候可能会带一些箭头之类的,但是真正在内存里面是不可能有箭头这些东西的。内存里面是不可能存着箭头→这些东西的。我们把这些箭头叫做逻辑结构,是我们想象出来的,因为这些箭头比指针更为直观。

  1. 在内存里面实实在在怎么存的被称为物理结构。

  1. 我们画图的时候看起来好像指针啊什么呀都是在动的,但实际上在内存里面的话,一切都是死的,没有动,无非就是不断的给指针变量进行赋值。然后在我们脑海中直观的形象表现就是:该指针变量不断的指来指去。

  1. 逻辑结构就是我们为了方便理解,形象化画出来的;但是在计算机内存里面是十分枯燥的,实实在在数据在内存中的变化是物理结构。


单链表节点(结构体类型)的创建

  1. 从语言的角度来讲,凡是有多个数据,都需要存到结构体里面去。链表的每一个节点就是通过结构体来表示。结构体里面有当前的数值data,并且还需要一个指针。因为上一个节点需要存下一个节点的地址,这样我才有寻找的依据,这样的话,各个内存块之间才可以像链条一样这么串起来。

  1. 并且我们已经知道每一个节点实际上就是一个结构体。既然上一个节点需要存下一个节点的地址。那么因此显而易见,无非就是一个结构体指针罢了,我们叫做next。

  1. 之前在c语言当中我们也讲过,结构体里面是不能够嵌套结构体的,就是无穷套娃了。但我们刚才结构体里面并没有结构体,是一个结构体指针,大小是确定的,就是四个字节。

//节点结构体的创建
typedef int SLTDataType;
typedef struct SLTNode
{SLTDataType data;struct SLTNode* next;
}SLTNode;

单链表的打印

1. 空的顺序表可以打印,当然一样道理,空的链表也可以打印,给我显示为空不就可以了

2. phead就是链表第一个节点的地址,如果这个链表是空链表,那么phead就是NULL

3. 当我为空链表的时候,phead就为NULL,在打印链表的时候不能够进行断言,不然的话空链表我就打印不出来了,直接把我程序终止了。

4. 链表的话在物理上并不是连续的,它的每一个节点都是malloc出来的

5. 每一个节点(说白了就是结构体)都会存放下一个节点的地址,因此就需要这一很关键的一步:cur = cur -> next

6. 0就是假,非0就是真,NULL本质就是0。

//单链表的打印
void SLTPrint(SLTNode* phead)
{SLTNode* cur = phead;while (cur != NULL){printf("%d->",cur->data);cur = cur->next;}printf("NULL\n");
}

单链表malloc一个新节点并赋值

//单链表malloc一个新节点并赋值
SLTNode* BuySLTNode(SLTDataType x)
{SLTNode* newnode = (SLTNode*)malloc(sizeof(SLTNode));if (newnode == NULL){perror("BuySLTNode::Malloc");return NULL;}newnode->data = x;;newnode->next = NULL;return newnode;
}

单链表的尾插

1. 由于之前一样的,在这个地方是不能够进行空指针断言的,因为如果是断言的话,我在空链表的情形下想要去尾插,但是断言了的话,给我程序提前终止了,这还玩个屁啊。

2. 尾插的第一步是先得搞一个节点出来,这个地方就不像顺序表一样了,要考虑什么空间够不够啊,要不要扩容啊之类的就不需要考虑了。在这边的话就自己去malloc新创建一个节点。

3. 然后对于这个新节点newnode的值给进去,next指针为NULL。

4. 然后就是找到原先的尾巴,原尾节点的next成员要存储新尾节点的地址。

5. 刚才讲的情况都是链表不为空的情况,如果链表是空的话,这种情况需要额外处理。这时候只需要把phead指向新节点newnode就可以了。

//单链表的尾插
void SLTPushBack(SLTNode** pphead, SLTDataType x)
{SLTNode* newnode = BuySLTNode(x);if (*pphead == NULL){*pphead = newnode;}else{SLTNode* tail = *pphead;while (tail->next != NULL){tail = tail->next;}tail->next = newnode;}
}

单链表的头插

1. 这个也需要分两种情况,以总是链表为空的情况,第二种就是链表非空。但是发现仅有的三行代码可以完全解决空的情况。

2. 然后发现在这个函数内部也需要创建一个新的节点。那么就是说可以把创建新的节点这个过程给他单独的提取出来。

//单链表的头插
void SLTPushFront(SLTNode** pphead, SLTDataType x)
{SLTNode* newnode = BuySLTNode(x);newnode->next = *pphead;*pphead = newnode;
}

单链表的尾删

1. 删除的时候也是需要用二级指针。因为万一你要把指针置空的时候,如果你传一级指针的话,就完蛋了。那么原先那个指针就变成野指针了。

2. 链表在尾删的时候要注意分几种特殊情况,第一种情况是当前只有一个节点,第二种特殊情况就是整个链表都是空的。对于第一种情况直接free,然后把指针置空就完事儿了。对于第二种情况,直接暴力assert检查就可以。

//单链表的尾删
void SLTPopBack(SLTNode** pphead)
{assert(*pphead);if ((*pphead)->next == NULL){free(*pphead);*pphead = NULL;}else{SLTNode* prev = NULL;SLTNode* tail = *pphead;while (tail->next != NULL){prev = tail;tail = tail->next;}prev->next = NULL;free(tail);tail = NULL;}
}

单链表的头删

1. 首先也可以暴力检查一下这个链表是不是空的。但头删不需要特判链表只有一个节点的情况。

//单链表的头删
void SLTPopFront(SLTNode** pphead)
{assert(*pphead);SLTNode* first = *pphead;*pphead = (*pphead)->next;free(first);first = NULL;
}

单链表的初始化

这个非常简单,直接初始化就可以,因为只有一个值。直接创建一个结构体指针赋为NULL就可以

SLTNode* plist = NULL;

关于单链表函数操作中的有关于assert断言的问题

不是在参数里面碰到一个指针就assert一下,不是这么一根筋的。像这边单链表的话,当phead为NULL时我们都知道此时此刻表示一个空链表,但是空链表我就不能头插,尾插插入了吗?我照样可以这么插入;空链表难道我就不能打印了吗?我照样可以打印,只是什么都没有而已。但是对于删除而言,如果此时此刻你已经是一个空链表了,那么你还删个毛线啊?所以此时此刻呢又需要用assert断言一下,这种东西都是具体问题具体分析。

关于参数为二级指针的问题

1. 尤其要注意形参的改变不会影响实参,这个其实底层要理解的话,就是得通过函数栈帧。当传址调用的时候,实际上地址也是在拷贝,但由于你是在函数里面对指针进行解引用操作,因此产生的影响是持久性的,即使调用的函数退出回来了。

2. malloc向堆区动态申请内存的时候,是随机在内存里面划分一块区域的。

3. 当你的实参是一个指针的时候,虽然这时候函数传参看起来好像也是传址调用,但实际上调用函数内部执行的各种操作,对于函数外头的这个参数指针不会发生任何影响。因为实际上无论如何都会有拷贝这个环节会发生。

4. 在这边想要着重说明的是:我们在进行函数传参的时候,这时候就必须传二级指针。我们在函数体外已经先有一个指针,我们的函数内部操作都离不开要改变该指针的指向位置,要实现这个操作,就不能传一级指针,因为这样只有我这个一级指针自己在捣鼓;如果我传指针的地址(也就是二级指针),这样子我才能在函数体内去改变函数体外这个指针所指向的位置。

5. 我这个phead是一个实实在在的结构体指针,各种有关于单链表的操作,其中都需要phead指向的位置发生变化,如果在函数里面传一级指针的话,函数里面的各种乱七八糟的运转,跟我函数外面的phead指针一点关系都没有,因为你在函数内部自己有一个参数指针(形参),也许这个形参与phead指向的地址是一样的,但是当你传一级指针的时候,在函数里面各种捣鼓运算改变的都是你形参指向的位置。如果想要改变我这个phead指针指向的位置,就必须把phead的地址当成参数传给函数,因此这个参数也就是指针的地址,显而易见即为二级指针。

http://www.dt0577.cn/news/53933.html

相关文章:

  • 企业网站建设课件百度pc网页版登录入口
  • 网站建设策划书的编制惠州seo推广公司
  • 东营市两学一做考试网站今日国内热点新闻头条事件
  • java web网站开发结果百度认证官网申请
  • .red域名做网站好不好陕西网络推广公司
  • 学校网站建设汇报ppt刚开的店铺怎么做推广
  • 网站运营部门职责湖南网站seo公司
  • wamp可以做视频网站吗百度知道问答平台
  • 网站关键词布局百度一下马上知道
  • 合肥网站搭建工作室网上互联网推广
  • 网站模板源码平台沧州做网络推广的平台
  • 星子网优化内容
  • 做网站需学什么凡科网微信小程序
  • 招聘网站建设流程图windows优化大师好吗
  • 徐州市制作网站微信朋友圈推广文案
  • 房产信息网官网查询百度seo优化推广
  • linux类似wordpress合肥seo推广公司
  • 医学类的网站做Google在线外链推广
  • 邯郸企业网站团队常用的seo查询工具
  • php企业网站开发框架合肥关键词排名提升
  • 营销型网站建设网站建设营销如何交换优质友情链接
  • 沃尔玛seo站外推广有哪些
  • 政府网站后台企业网站cms
  • 电子商务建设与网站规划百度品牌专区
  • 宜春做网站公司线上推广有哪些渠道
  • 学校网站开发图片素材上海搜索引擎优化seo
  • 衢州网站建设公司建网站的流程
  • 国家建设部官方培训网站营销策划方案ppt
  • 网站反连接广告策划方案范文
  • 宜州网站建设搜索引擎优化怎么做