不带头节点的单链表

  • 前言
  • 一、结构体设计
  • 二、函数实现
    • 1. 初始化
    • 2. 购买一个新节点
    • 3. 头插
    • 4. 尾插
    • 5. 按位置插入
    • 6. 头删
    • 7. 尾删
    • 8. 按位置删
  • 总结
    • 补充代码

前言

单链表分为:带头节点的单链表、不带头节点的单链表
链表不存在 ”满“ 这个概念,所以凡是链表的结构体中,其函数实现时均不需要执行判满操作


一、结构体设计

不带头节点的单链表,结构体应该怎样设计?

// 不带头节点的结构体设计
typedef int ELEM_TYPE;// 有效数据节点结构体设计
typedef struct Node
{ELEM_TYPE data;  // 数据域 -- 保存有效值struct Node* next;  // 指针域 -- 保存下一个有效数据元素的地址
}Node, PNode;

二、函数实现

1. 初始化

由于不带头节点的单链表不存在头节点,因此初始化只需要对头指针进行赋初值,将其置为NULL即可
代码如下

//初始化函数(对于头指针进行赋初值)
void no_head_Init_list(struct Node **phead)//struct Node ** == PNode *
{//assert  phead!=NULL*phead = NULL;//修改一个指针,如果没有有效节点的话,将其指针指向NULL//这个指针保存第一个有效数据节点的地址   phead   *phead(保存的第一个有效数据的地址)   (*phead).next
}

2. 购买一个新节点

因为链表不存在满这个概念,因此无需判满操作
从堆区申请一个节点大小的内存,并将申请好内存的地址返回。
代码如下

//购买一个新节点
struct Node *no_head_BuyNode(ELEM_TYPE val)
{struct Node*pnewnode = (struct Node*)malloc(1 * sizeof(struct Node));assert(pnewnode != NULL);if(pnewnode == NULL){return NULL;}pnewnode->data = val;pnewnode->next = NULL; return pnewnode;
}

3. 头插

*phead == 第一个元素的地址

代码如下

//头插
bool no_head_Insert_head(PNode *phead, ELEM_TYPE val)
{//assertassert(phead != NULL);if(NULL == phead){return false;}//1.创建新节点struct Node* pnewnode = (struct Node *)malloc(1*sizeof(struct Node));assert(pnewnode != NULL);pnewnode->data = val;pnewnode->next = NULL;//2.找到合适的插入位置 (头插函数 已经找到插入位置)//3.插入pnewnode->next = *phead;*phead = pnewnode;return true;
}

4. 尾插

  1. 正常情况下,只需要正常插入即可。

    但是需要将for循环修改,p不再指向头节点,而是指向首元素的地址

  2. 此时有一个问题,如果在尾插之前,单链表中已经有数据节点,则正常插入;但是在尾插之前,如果单链表是一个空链,那么尾插就可以理解为头插操作,当然,执行尾插操作时,可以直接替换成头插操作

代码如下

//尾插
bool no_head_Insert_tail(struct Node **phead, ELEM_TYPE val)
{//assertif(no_head_IsEmpty(phead))//如果我是一个空链,则执行头插函数 不要执行尾插函数{return no_head_Insert_head(phead, val);}//1.创建新节点struct Node* pnewnode = no_head_BuyNode(val);assert(pnewnode!= NULL);//2.找到合适的插入位置struct Node *p;for( p= *phead; p->next!=NULL; p=p->next);//这里存在一个bug:如果是空链的话,*phead == p == NULL,那么语句2:p->next会报写入异常(在上面处理一下这个bug即可)//此时 指针p停留在尾结点,而不是尾结点的下一个节点//3.插入pnewnode->next = p->next;p->next = pnewnode;return true;
}

5. 按位置插入

pos == 0 相当于头插,pos ==length 相当于尾插

代码如下

//按位置插入(pos=0 相当于头插  pos==length 相当于尾插)
bool no_head_Insert_pos(struct Node **phead, int pos, ELEM_TYPE val)
{//assert   phead  posassert(phead != NULL);assert(pos >=0 && pos<=no_head_Get_length(phead));//pos == length合法  相当于尾插 但是这个位置不能用于删除if(pos == 0){return no_head_Insert_head(phead, val);}//1.创建新节点struct Node* pnewnode = no_head_BuyNode(val);assert(pnewnode!= NULL);//2.找到合适的插入位置    struct Node *p = *phead;  for(int i=1; i<pos; i++)这里存在一个bug:如果pos = 0,p没有办法跑到合适的位置,提前处理掉即可{p=p->next;}//3.插入pnewnode->next = p->next;p->next = pnewnode;return true;
}

6. 头删

链表删除元素需要对其进行判空操作
代码如下

bool no_head_Del_head(struct Node **phead)
{//assert//删除操作:需要判空if(no_head_IsEmpty(phead)) {return false;}struct Node *p =*phead;*phead = p->next;free(p);return true;
}

7. 尾删

  1. 链表删除元素需要对其进行判空操作
  2. 尾删需要申请两个临时指针p、q
    p:指向待删除节点
    q:指向待删除节点的上一个节点

【注】单链表有一个特点:可以通过上一个节点找到下一个节点

3. 临时指针p、q怎样找到自己合适的指向位置
第一种方案:p先通过NULL找;q再通过NULL找
第二种方案:q直接通过q-next-next判断是否为NULL来直接找到q的合适的位置;p就直接等于q->next
4. 但是申请两个临时指针,其指向可能存在异常情况:
第一种异常:空链
第二种异常:有节点存在,但是只有一个

代码如下

bool no_head_Del_head(struct Node **phead)
{//assert//删除操作:需要判空if(no_head_IsEmpty(phead)) {return false;}struct Node *p =*phead;*phead = p->next;free(p);return true;
}

8. 按位置删

按位置删除元素需要额外判断删除位置是否合法,需要对特殊位置特殊处理

代码如下

//按位置删(pos==0 相当于头删   pos==length-1 相当于尾删(pos==length非法))
bool no_head_Del_pos(struct Node **phead, int pos)
{assert(phead != NULL);assert(pos >=0 && pos<no_head_Get_length(phead));if(no_head_IsEmpty(phead)){return false;}if(pos == 0){return no_head_Del_head(phead);}struct Node *q = *phead;for(int i=1; i<pos; i++){q = q->next;}struct Node *p = q->next;q->next = p->next;free(p);return true;
}

总结

  1. 不带头节点的单链表要区别于带头节点的单链表
  2. 不带头节点的单链表的结构体设计
  3. 不带头节点的函数实现

补充代码

#include <stdio.h>

【不带头节点的单链表】相关推荐

  1. 【数据结构】8. 队列(带头节点的单链表实现)(完整代码实现:初始化、入队列、出队列、获取队头元素、获取队尾元素、获取队列中有效元素的个数、判空、销毁)

    目录 Queue.h Queue.c test.c Queue.h #pragma once //采用带头节点的单链表实现队列typedef int DataType;typedef struct Q ...

  2. java带头节点的单链表_自己实现集合框架(五):带头结点单链表的实现

    这是系列文章,每篇文章末尾均附有源代码地址.目的是通过模拟集合框架的简单实现,从而对常用的数据结构和java集合有个大概的了解.当然实现没有java集合的实现那么复杂,功能也没有那么强大,但是可以通过 ...

  3. 不带头节点的单链表如何头插(多图易懂)

    文章目录 缘起 带头节点的头插 不带头节点的头插 错误的代码 为什么错误 如何修改 返回新的头指针 二级指针 缘起 本文想说的是单向非循环链表的头插.单向非循环链表,可以是带头节点的,也可以是不带头节 ...

  4. 数据结构-带头节点的单链表(C语言)超详细讲解

    前面我们学到线性表的顺序存储结构(顺序表),发现它有着明显的缺点:插入和删除元素时需要频繁的移动元素,运算效率低.必须按事先估计的最大元素个数申请连续的存储空间.存储空间估计大了,造成浪费空间:估计小 ...

  5. 头插法和尾插法建立带头节点的单链表

    有两种方法建立单链表,尾插法和头插法,他们的区别是:头插法是按照输入元素倒序建立,为尾插法为顺序插入,并且多一个尾节点,我们一般使用尾插法. 一.头插法 代码为: pCurr -> next = ...

  6. 数据结构不带头节点跟带头节点的单链表区别,C语言代码展示

    单链表头插法 不带头结点 void FronttList1(List *L) {List p;ElemType x;printf_s("请输入一组数据,以'0'为结束符\n");s ...

  7. 带头节点的单链表逆置

    #include <stdio.h> #include <stdlib.h> typedef struct node { int data; struct node *next ...

  8. 借助栈将一个带头节点的单链表倒置

    分析: 先理解倒置: 倒置前:1->2->3 倒置后:3->2->1 思路:先沿着链表从头到尾扫一遍 将链表的每个结点的data的值依次入栈;  在沿着链表扫一遍 将栈中的元素 ...

  9. 不带头结点的单链表------C语言实现

    1 /****************************************************/ 3 File name:no_head_link.c4 Author:SimonKly ...

最新文章

  1. 跳过IE7beta2版的XP正版检测!
  2. 电话号码 【trie树】
  3. Storm【压力测试】- 系列1: 进行简单的压力测试
  4. HTML文件撰写的注意事项有哪些,CSS及HTML 常见误区和注意事项(一)
  5. AutoMapper之投影
  6. html:(4):认识html文件基本结构和认识head标签
  7. ubuntu18.04安装python3_如何在 Ubuntu 18.04上安装 Python3.7
  8. krpano漫游加方向性3D声音(这篇文章已被移到krpano中国网站 krpano360.com)
  9. 开机后系统时间被恶意修改
  10. android 4.2 安全新特性(I)
  11. Lua介绍极其在C#项目中的应用
  12. 0基础学python做什么工作好-转行零基础该如何学习python?很庆幸,三年前的我选对了...
  13. 数据库SQL语言学习--上机练习3(插入 更新 删除)
  14. jvm虚拟机规范官方文档入口
  15. 安装pytorch1.10.0/cu111时报错:no matching distribution found for torchvision==0.11.0+cu111
  16. 怎么查询IP段所对应的IP总数、网络地址、可用IP数量及范围、网关、子网掩码、广播地址呢?/29 服务器包含多少IP地址?
  17. 介绍一下Emily----大一
  18. LCD屏的TCON、Source Driver、Gate Driver 、Gamma概念
  19. 计算机原理与应用第六章——总线技术
  20. 语义解析Parser用户手册

热门文章

  1. vue——图片懒加载和禁止图片使用缓存方法
  2. 哈理工大学ACM程序设计全国邀请赛D D Pairs(FFT)
  3. linphone-LinphoneManager.java文件分析
  4. MFC 组合框的用法大全
  5. Linux环境变量设置(临时+永久)
  6. MybatisPlus中and和or的组合使用
  7. Win7系统提示对于目标文件系统文件过大
  8. 使用docker简单编译k20pro内核
  9. 学生管理系统(奖学金系统)
  10. 【别人的原创】上点、离点、内点