不带头结点的单链表(基于c语言)
本篇文章的代码大多使用无头结点的单链表:
相关定义:
#include <stdio.h>
#include <stdlib.h>
#include <assert.h> typedef int DataType;
typedef struct Linklist{
LDataType data;
struct Linklist *next;
}Linklist,*pLinklist;
相关函数的定义:
pLinklist BuyNewNode(LDataType data); //创建一个数据域为data的新结点
void InitLinklist(pLinklist *pL); //初始化单链表
void PushBackLinklist(pLinklist* pL,LDataType data); //尾插
void PushFrontLinklist(pLinklist *pL,LDataType data); //头插
void PopBackLinklist(pLinklist *pL); //尾删
void PopFrontLinklist(pLinklist *pL); //头删
void PrintLinklist(pLinklist pL); //打印出链表
pLinklist FindLinklist(Linklist *pL,LDataType data); //找到数据域为data的第一个结点
void InsertLinklist(pLinklist *pL,pLinklist p,LDataType data); //指定位置插入
void RemoveLinklist(pLinklist *pL,LDataType data); //删除第一个数据为data的结点
void RemoveAllLinklist(pLinklist *pL,LDataType data); //删除数据为data的全部结点
int IsEmpty(pLinklist pL); //判断单链表是否为空
void DestoryLinklist(pLinklist *pL); //删除整个链表,释放内存
由上面可以看出,只要是涉及到头指针发生改变的,我们在函数中都是传入指向头指针的指针。就像我们在swap函数中要交换a和b的值,我们是传入地址,而现在我们要改变头指针的值,也必须要传入指向头指针的一个指针来进行相关的操作。
此处借鉴了c语言函数传递参数的问题。
下面是对函数的展开,我会比较详细的分析一下函数实现:
0.动态生成新结点
pLinklist BuyNewNode(LDataType data){
pLinklist NewNode = (pLinklist)malloc(sizeof(Linklist));
if(pLinklist == NULL){
printf("空间开辟失败");
return NULL;
}
NewNode->data = data;
NewNode->next = NULL;
return NewNode;
}
1.初始化操作
void InitLinklist(pLinklist *pL){
assert(pL != NULL);
(*pL) = NULL;
}
2.尾插一个数据为data的结点
void PushBackLinklist(pLinklist *pL,LDataType data){
assert(pL != NULL); //大多数中都有这个,是为了防止使用空指针,书中经常会说,千万不要使用空指针,你应该有印象
pLinklist NewNode = BuyNewNode(data);
if(*pL == NULL){ //判断这个是否为空链表
*pL = NewNode;
return ;
}
pLinklist cur = *pL;
while(cur->next != NULL){ //其实这里也可以用cur != NULL,但是上面已经把把空链表大情况写出来了,如果再这样写会重复,不会错,但是复杂一点点
cur = cur->next;
}
cur->next = NewNode;
}
3.头插一个数据为data的结点
void PushFrontLinklist(pLinklsit *pL,LDataType data){
assert(pL != NULL);
pLinklist NewNode = BuyNewNode(data);
if(*pL == NULL){
*pL = NewNode;
return ;
}
NewNode->next = *pL;
*pL = NewNode;
}
4.判断无头链表是否为空
int IsEmptyLinklist(pLinklist pL){
//这里的pL是一个指向链表的指针,而不是一个指向链表指针的指针
return (pL == NULL);
}
5.尾删
void PopBackLinklist(pLinklist *pL){
assert(pL != NULL);
if(IsEmptyLinklist(*pL)){
//*pL是一个指向链表的指针
printf("链表为空");
return ;
}
//尾删需要找到前面那一个结点
pLinklist cur = *pL;
pLinklist pre;
if(cur->next == NULL){
*pL = NULL;
free(cur);
cur = NULL;
return ;
}
while(cur->next){
pre = cur;
cur = cur->next;
}
pre->next = NULL;
free(cur);
cur = NULL;
}
6.头删
void PopFrontLinklist(pLinklist *pL){
assert(pL != NULL);
if(*pL == NULL){
printf("链表为空");
return ;
}
pLinklist p = *pL;
*pL = p->next;
free(p);
p = NULL;
}
7.找到第一个数据为data的结点
pLinklist FindLinklist(pLinklist *pL,LDataType data){
assert(pL != NULL);
plinklist cur = *pL;
while(cur != NULL){
if(cur->data == data){
return cur;
}
cur = cur->next;
}
return NULL;
}
8.在给出的结点之前插入一个数据为data的结点
void InsertLinklist(pLinklist *pL,pLinklist p,LDataType data){
assert(pL != NULL);
pLinklist NewNode = BuyNewNode(data);
pLinklist cur = *pL;
while(cur->next != p){
cur = cur->next;
}
NewNode->next = cur->next;
cur->next = NewNode;
}
9.删除第一个数据为data的结点
void RemoveLinklist(pLinklist *pL,LDataType data){
assert(pL != NULL);
pLinklist cur = FindLinklist(pL,data);
if(cur == NULL){
printf("没找到");
return ;
}
if(cur == *pL){
//刚好在第一个结点
*pL = cur->next;
free(cur);
cur = NULL;
return ;
}
pLinklist p = *pL;
while(p->next != cur){
p = p->next;
}
p->next = cur->next;
free(cur);
cur = NULL;
}
10.删除每一个数据都是data的结点
void RemoveAllLinklist(pLinklist *pL,LDataType data){
assert(pL != NULL); //删除每一个数据域都是data的结点
pLinklist cur = NULL;
pLinklist p = *pL; //pre保存要删除结点的前一个结点
pLinklist pre = *pL;
while(p){
if (p->data == data && (*pL) == p){
//第一个结点是
pre = p;
p = p->next;
*pL = p;
free(pre);
pre = NULL;
}
else if(p->data == data){
//后续结点是
cur = p;
p = p->next;
pre->next = p;
free(cur);
cur = NULL;
}
else{
//此结点不是
pre = p;
p = p->next;
}
}
}
11.打印出链表
void PrintLinklist(Linklist *pL){
pLinklist cur = pL; //打印链表
while(cur){
printf("%d--->",cur->data);
cur = cur->next;
}
printf("NULL\n");
}
12.摧毁链表
void DestoryLinklist(pLinklist *pL){
assert(pL != NULL); //摧毁链表
pLinklist cur = *pL;
pLinklist pre = NULL;
if (*pL == NULL){
printf("链表为空");
return ;
}
if (cur->next = NULL){
*pL = NULL;
free(cur);
cur = NULL;
return ;
}
while(cur){
pre = cur;
cur = cur->next;
free(pre);
pre = NULL;
}
}
- 添加到短语集
- 没有此单词集:中文(简体) -> 英语...
- 创建新的单词集...
- 没有此单词集:中文(简体) -> 英语...
- 拷贝
不带头结点的单链表(基于c语言)的更多相关文章
- java编写带头结点的单链表
最近在牛客网上练习在线编程,希望自己坚持下去,每天都坚持下去练习,给自己一个沉淀,不多说了 我遇到了一个用java实现单链表的题目,就自己在做题中将单链表完善了一下,希望大家作为参考也熟悉一下,自己 ...
- C/C++中创建(带头结点、不带头结点的)单链表
1.带头结点的单链表(推荐使用带头结点的单链表)(采用尾插法) 了解单链表中节点的构成 从上图可知,节点包含数据域和指针域,因此,在对节点进行定义时,我们可以如下简单形式地定义: /* 定义链表 */ ...
- 链表习题(2)-一个集合用带头结点的单链表L表示,编写算法删除其值最大的结点。
/*一个集合用带头结点的单链表L表示,编写算法删除其值最大的结点.*/ /* 算法思想:使用pre,p,premax,max四个指针,pre和p进行比较,premax和max进行最后的删除操作 通过遍 ...
- 链表习题(1)-设计一个递归算法,删除不带头结点的单链表L中所有值为x的结点
/*设计一个递归算法,删除不带头结点的单链表L中所有值为x的结点*/ /* 算法思想:设f(L,x)的功能是删除以L为首结点指针的单链表中所有值等于x的结点, 则显然有f(L->next,x)的 ...
- c语言实现--不带头结点的单链表操作
1,不带头结点的单链表操作中,除了InitList(),GetElem(),ListInsert(),ListDelete()操作与带头结点的单链表有差别外,其它的操作基本上一样. 2,不带头结点单链 ...
- 有一个线性表,采用带头结点的单链表L来存储,设计一个算法将其逆置,且不能建立新节点,只能通过表中已有的节点的重新组合来完成。
有一个线性表,采用带头结点的单链表L来存储,设计一个算法将其逆置,且不能建立新节点,只能通过表中已有的节点的重新组合来完成. 分析:线性表中关于逆序的问题,就是用建立链表的头插法.而本题要求不能建立新 ...
- 不带头结点的单链表------C语言实现
File name:no_head_link.c Author:SimonKly Version:0.1 Date: 2017.5.20 Description:不带头节点的单链表 Funcion L ...
- 无头结点的单链表(C语言)
1.单链表: 在顺序表中,用一组地址连续的存储单元来一次存放线性表的结点,因此结点的逻辑顺序与物理顺序是一致的.但链表却不同,链表是用一组任意的存储单元来存放 线性表的结点,这组存储单元可以是连续的, ...
- Python实现不带头结点的单链表
1 # 创建一个节点类 2 class Node: 3 def __init__(self, item): 4 self.item = item 5 self.next = None 6 7 8 # ...
随机推荐
- PRML 基础知识
1 一个经典例子 一个经典的例子就是Polynomial Curve Fitting问题,现在将以此为基础介绍一些基本概念和方法.该问题的主要思路是针对给定的训练集\(\mathbf{x}\equ ...
- .NET 云原生架构师训练营(权限系统 代码实现 ActionAccess)--学习笔记
目录 开发任务 代码实现 开发任务 DotNetNB.Security.Core:定义 core,models,Istore:实现 default memory store DotNetNB.Secu ...
- 《PHP程序员面试笔试宝典》——如何回答快速估算类问题?
如何巧妙地回答面试官的问题? 本文摘自<PHP程序员面试笔试宝典> 有些大企业的面试官,总喜欢出一些快速估算类问题,对他们而言,这些问题只是手段,不是目的,能够得到一个满意的结果固然是他们 ...
- Vue2.0源码学习(3) - 组件的创建和patch过程
组件化 组件化是vue的另一个核心思想,所谓的组件化就,就是说把页面拆分成多个组件(component),每个组件依赖的css.js.图片等资源放在一起开发和维护.组件是资源独立的,在内部系统中是可以 ...
- Spring Cloud之服务注册中心搭建Eureka Server服务注册中⼼
Spring Cloud并不与Spring MVC类似是一个开源框架,而是一组解决问题的规范(个人理解).解决哪些问题呢?如下: 1)服务管理:⾃动注册与发现.状态监管 2)服务负载均衡 3)熔断 4 ...
- python2写ping监控,自动发现ip
玩了hostmonitor,老外写的很好.但是不符合国情,只有邮件适合发送. 今天用python 写一个自动发现ip,ping失败报警的程序.(微信和邮件报警) 以前用python写的发微信,发邮件直 ...
- Nginx 配置apple-app-site-association
ios突然给我发了如上链接和一个json,说他那边需要放一个 apple-app-site-association 文件用来支持他那边的功能,文件不需要后缀. 先说一下要求:线上官网的地址后面跟上他所 ...
- python中特殊参数self的作用
特殊参数self的作用:self会接收实例化过程中传入的数据,当实例对象创建后,实例便会代替 self,在代码中运行. self代表的是类的实例本身,方便数据的流转.对此,我们需要记住两点: 第一点: ...
- [题解]第十一届北航程序设计竞赛预赛——I.神奇宝贝大师
题目描述 一张n*m的地图,每个格子里面有一定数量的神奇宝贝,求一个最优位置,使得所有神奇宝贝到该位置的曼哈顿距离最小. 一共有T组数据,每组数据包含两行,第一行是n和m(1<=n,m<= ...
- 国内专业web报表工具,完美解决中国式报表难题
近几年报表工具的热度不断上升,很多企业都用上了全新的报表工具,主要是企业数据化转型已经成为趋势.在进行选型的时候,很多企业最好都选择国内的报表工具,相信一些人不知道为什么国内的报表工具表现比国外的好. ...