C语言实现链表【一】(无头单向非循环链表)
无头单向非循环链表
看到这个标题,是不是有小伙伴已经懵了呢?
只学过链表,怎么还有个无头和有头呢?怎么还有个循环和非循环呢?怎么还有个单向和双向呢?一连串的疑问。。。
其实这些都是链表的表示形式,只不过大部分人只接触了最简单的单链表,也就是我们这里提到的无头单向非循环链表,最简单的链表结构表示形式
话不多说,直接上图更直观一些
单链表结构定义:
熟悉了单链表的结构,下面来考虑如何在链表中实现数据存储呢?
链表是由多个节点按照一定的逻辑顺序连接形成的,每一个节点都由两部分组成,一部分存储数据,一部分存放下一节点的地址
代码实现结构如下:
typedef int LDatatype;//单个节点数据结构
typedef struct listNode {LDatatype data;struct listNode* next;
}listNode;
此处我们需要区分单链表和双链表:
单链表只能在前驱节点中存放后继节点的地址,而双链表不仅能够在前驱节点存放后继节点地址,还可以在后继节点中存放前驱节点的地址
区分不带头单链表和带头带头单链表
带不带头不是说看有没有head,而是看head节点是否存放数据
对此,即便是无头的单链表在构建链表结构的过程中,依然在头结点存放第一个节点的地址,但头结点仅仅放地址,而不存放数据
typedef struct linklist {//保存第一个节点的地址listNode* head;
}linklist;
单链表接口声明:
单链表主要也是实现数据管理存储功能,即增删查改的操作,包括在头节点插入,尾结点插入,头结点删除,尾结点删除,指定节点后删除插入操作等
void linklistInit(linklist* lst);void linklistPushBack(linklist* lst,LDatatype val);listNode* createNode(LDatatype val);void linklistPopBack(linklist* lst);void linklistPushFront(linklist* lst,LDatatype val);void linklistPopFront(linklist* lst);void linkInsertAfter(listNode* node, LDatatype val);void linkPopAfter(listNode* node);listNode* linkFind(linklist* lst, LDatatype val);void linkDestory(linklist* lst);void linkPrint(linklist* lst);
单链表接口实现
链表初始化:
(1)初始化链表结构:
由于链表结构中有头结点,初始化只需要将头结点存放地址置为空
void linklistInit(linklist* lst)
{if (lst == NULL)return;lst->head = NULL;
}
(2)创建节点
当执行插入操作的过程中,根据节点结构需要先构造出一个可以存放数据的节点
listNode* createNode(LDatatype val)
{listNode* node = (listNode*)malloc(sizeof(listNode));if (node != NULL){node->data = val;node->next = NULL;}return node;
}
注意到在创建节点中,将该节点存放下一节点地址给NULL,如果尾插,将不需在尾部节点置NULL,其余位置插入,更新地址即可
单链表尾插
void linklistPushBack(linklist* lst, LDatatype val)
{//空 创建节点 赋值+next置空if (lst == NULL || lst->head == NULL){lst->head = createNode(val);}//非空 遍历找到尾结点 在其后插入else{listNode* tail=lst->head;while (tail->next != NULL){tail = tail->next;}tail->next = createNode(val);}
}
单链表尾删
只有一个头结点情况:
遍历找最后一个节点:
代码如下:
void linklistPopBack(linklist* lst)
{if (lst == NULL || lst->head == NULL)return;//只有一个头结点 if (lst->head->next == NULL){lst->head = NULL;}//否则,遍历找到最后一个节点listNode* prev = NULL;listNode* tail = lst->head;//两个指针同时后移查找while (tail->next!=NULL){prev = tail;tail = tail->next;}free(tail);prev->next = NULL;
}
单链表头插
void linklistPushFront(linklist* lst,LDatatype val)
{if (lst == NULL || lst->head == NULL)return;listNode* node = createNode(val);node->next = lst->head;lst->head = node;
}
- 单链表头删
void linklistPopFront(linklist* lst)
{if (lst == NULL||lst->head==NULL)return;listNode* next= lst->head->next;free(lst->head);lst->head = next;
}
- 单链表指定节点后插入
void linkInsertAfter(listNode* node, LDatatype val)
{if (node == NULL)return;listNode* newnode = createNode(val);listNode* next = node->next;node->next = newnode;newnode->next = next;
}
- 单链表指定节点后删除
void linkPopAfter(listNode* node)
{if (node == NULL)return;//listNode* newnode = createNode(val);listNode* next = node->next;listNode* newnext = next->next;free(next);node->next = newnext;
}
- 单链表遍历
listNode* linkFind(linklist* lst, LDatatype val)
{if (lst == NULL || lst->head == NULL){return NULL;}listNode* cur = lst->head;while (cur){if (cur->data == val){return cur;}cur = cur->next;}return NULL;
}
- 单链表销毁(删除所有节点,但需要从头开始删除,并保存后续节点)
void linkDestory(linklist* lst)
{if (lst == NULL || lst->head == NULL){return;}listNode* cur = lst->head;//listNode* next = cur->next;while (cur){listNode* next = cur->next;free(cur);cur = next;/*lst->head = next;cur = lst->head;next = next->next;*/}lst->head = NULL;
}
- 单链表某一指定节点删除
listNode* linkErase(linklist* lst,listNode* node)
{if (node == NULL)return;//listNode* newnode = createNode(val);listNode* tmp = (listNode*)malloc(sizeof(listNode));tmp->next = lst->head;listNode* prev = tmp;listNode* tail = lst->head;//两个指针同时后移查找while (tail){if (tail == node){prev->next = tail->next;tail = tail->next;}else{prev = prev->next;tail = tail->next;}}lst->head = tmp->next;free(tmp);return lst->head;
}
正所谓千言万语的解释,不如一张图解释的清楚,不理解的小伙伴可以根据图示来理解链表的指向变化,
今天分享就到这,下一次分享带头双向循环链表的增删改查实现!
C语言实现链表【一】(无头单向非循环链表)相关推荐
- c语言单向循环链表实现增删,C语言单向非循环链表增删查改实现
SList.h #ifndef _SLIST_H_ #define _SLIST_H_ #include#include#include// 1.无头单向非循环链表增删查改实现 typedef int ...
- C语言之链表探究之单向链表(List)、附双向循环链表参考博文地址
参考博文:C语言数据结构-创建链表的四种方法 链表结构图一 链表结构图二 链表结构图三 链表结构图四 一.静态链表 例1: 附例1代码: #include <stdio.h>typedef ...
- c语言不循环链表,无头单向不循环链表相关接口实现(C语言)
单链表相关接口介绍List.h #define _CRT_SECURE_NO_WARNINGS #ifndef __LIST_H__ #define __LIST_H__ #include #incl ...
- C语言数据结构——链表
目录 前言 一.什么是链表 1.1链表的结构和概念 1.2 链表的分类 二.无头单向非循环链表 2.1 创建结构体 2.2 动态申请一个节点 2.3 单链表打印 2.4 单链表尾插/尾删 2.4.1 ...
- Java数据结构之链表、树、堆、图手写双向非循环链表
数据结构.手写双向非循环链表 文章目录 数据结构.手写双向非循环链表 链表 1.链表的分类 2.链表的特点 二.手写双向非循环链表 2.1方法总结 2.2 环境搭建 2.3 add 添加结点 2.3. ...
- 【数据结构】你了解无间道吗?单链表之单向无头非循环链表
目录 1.摘要 2.顺序存储结构的缺点 3.什么是单链表 4.头指针与头节点(哨兵位) 5.单向无头非循环链表的代码实现 5.1.功能实现的需求 5.2.头文件 5.3.接口文 ...
- 数据结构无头结点单向不循环链表(C语言版)
main.c(负责测试) #include <stdlib.h> #include <stdio.h> #include <time.h> #include &qu ...
- C语言随笔小算法:单向链表
C语言随笔小算法:单向链表 参考链接: 代码参考:https://blog.csdn.net/go_sann/article/details/80508284 原理参考:https://blog.cs ...
- C语言之链表:单向链表,循环链表,双向链表
C语言之链表:单向链表,循环链表,双向链表 提起链式存储结构,其与数组是两个非常基础的数据结构,每当提到链式存储结构时,一般情况下我们都会将其与数组放到一块儿来比较. 对于数组与链表,从结构上来看,数 ...
最新文章
- linux脚本重定向到输入,linux shell输入输出重定向
- [整理]ADB命令行学习笔记
- 要锻炼二手交换的能力
- webbrowser抓取php网页源码,获取webbrowser控件 网页的源码(收藏)
- PAT甲级 -- 1106 Lowest Price in Supply Chain (25 分)
- Photoshop脚本 使用ExtendScript编写Ps脚本
- 在加利福尼亚州投资于新餐馆:一种数据驱动的方法
- MySQL的timestamp字段可以使用的范围是多少
- 普惠金融在印尼:GoPay会是东南亚的蚂蚁金服吗?
- JavaScript基础(六)面向对象
- android的交互方式,Android与js的交互方式
- centos mysql 5.5.57_centos 6.5装mysql5.7
- python虚拟环境配置文件_uwsgi 配置 python virtualenv 虚拟环境目录 ( ini 配置)
- C语言程序设计:现代方法(第2版)第二章全部习题答案
- 【转】UnityVS(Visual Studio Tools For Unity)的安装与使用
- VMware下安装CentOS
- sklearn 决策树例子_sklearn CART决策树分类
- 打印机服务器属性纸张自动改,“打印机设置自定义纸张”的解决方案
- 英语魔法师之语法俱乐部阅读笔记
- Innovus和ICC2中设置partial placement blockage的命令和区别
热门文章
- 爱旅行项目中实现支付宝支付
- 网站关键词排名下掉?快查下是否入坑了这6个SEO误区
- PS 考试案例 04笔记
- python进行各项统计检验_Python进行各项统计检验
- cad编辑节点快捷键是什么_CAD标注样式快捷键是什么?
- 几个shell初学者必会脚本
- 服务器虚拟化安装杀毒软件,服务器虚拟化部署_服务器虚拟化部署架构
- 解决java发邮件错误javax.net.ssl.SSLHandshakeException: No appropriate protocol
- JUL简介及组件介绍
- css显示组织架构图,纯CSS实现组织架构图