C语言实现无头单向链表的示例代码

目录
  • 一、易错的接口实现
    • 1.1 新节点开辟函数
    • 1.2 尾插
    • 1.3 尾删
  • 二、常见简单接口
    • 2.1 打印链表
    • 2.2 节点计数器
    • 2.3 判断是否为空链表
    • 2.4 通过值查找节点
    • 2.5 头插
    • 2.6 头删
    • 2.7 在任意节点后插入节点
    • 2.8 在任意节点后删除节点
    • 2.9 销毁链表
  • 三、头文件相关内容
    • 3.1 引用的库函数
    • 3.2 结构体声明

一、易错的接口实现

1.1 新节点开辟函数

由于创建一个新节点是频繁的操作,所以封装为一个接口最佳。

链表节点的属性有:(1)数值。(2)指向下一个节点的地址。(3)自身地址。

static SLTNode* BuySListNode(SLTDataType x)
{
 SLTNode* newnode = (SLTNode*)malloc(sizeof(SLTNode));
 //开辟失败
 if (newnode == NULL)
 {
  printf("malloc fail\n");
  exit(-1);
 }
 //初始化
 newnode->data = x;
 newnode->next = NULL;
 return newnode;
}

数值和next地址都由此函数初始化,自身地址则由函数的返回值返回。

要注意使用malloc函数时,可能存在开辟空间失败的情况,这时会返回NULL。

1.2 尾插

尾插的难点在于存在特殊情况。

当对非空链表和空链表进行尾插时,所需代码不同。

对非空链表尾插时,算法是:找到此链表的尾部,即遍历此链表,直至自定义的结构体指针tail的下一个节点为NULL,结束遍历。在tail的后面插入一个新节点。

对空链表尾插时,算法是:直接把新节点作为链表的头节点。

void SListPushBack(SLTNode** pphead, SLTDataType x)
{
 assert(pphead);
 //找尾
 SLTNode* tail = *pphead;
 if (tail == NULL)
 {
  tail = BuySListNode(x);
  *pphead = tail;
 }
 else
 {
  while (tail->next != NULL)
  {
   tail = tail->next;
  }
  SLTNode* newnode = BuySListNode(x);
  tail->next = newnode;
 }
}

1.3 尾删

此接口也有特殊情况处理。

当链表有一个以上的节点时,算法:遍历链表到尾部,free掉tail所在内存,改变tail之前一个节点的next,为NULL。

需要一个结构体指针变量prev来记录tail的前一个节点。

当链表只有一个节点时,算法:tail一开始就在尾部,直接free掉tail,再把prev指针(初值为NULL)赋值给头节点*pphead。

如果不单独考虑这种情况的话,会因为NULL->next而出现内存错误。

当链表没有节点时,是不可以调用尾删的,直接用assert函数报错。

void SListPopBack(SLTNode** pphead)
{
 assert(pphead);
 assert(*pphead);//没有节点断言报错
 SLTNode* prev = NULL;
 SLTNode* tail = *pphead;
 while (tail->next != NULL)
 {
  prev = tail;
  tail = tail->next;
 }
 free(tail);
 tail = NULL;
 if (prev != NULL)
  prev->next = NULL;
 else
  *pphead = prev;
}

二、常见简单接口

2.1 打印链表

void SListPrint(SLTNode* phead)
{
 SLTNode* cur = phead;
 while (cur)
 {
  printf("%d->", cur->data);
  cur = cur->next;
 }
 printf("NULL\n");
}

2.2 节点计数器

int SListSize(SLTNode* phead)
{
 //计数器
 int count = 0;
 SLTNode* cur = phead;
 while (cur)
 {
  count++;
  cur = cur->next;
 }
 return count;
}

2.3 判断是否为空链表

bool SListEmpty(SLTNode* phead)
{
 return phead == NULL;
}

2.4 通过值查找节点

SLTNode* SListFind(SLTNode* phead, SLTDataType data)
{
 //通过数据查找节点-遍历节点,判断值是否相等
 SLTNode* cur = phead;
 while (cur)
 {
  if (cur->data == data)
   return cur;
  cur = cur->next;
 }
 return NULL;
}

2.5 头插

void SListPushFront(SLTNode** pphead, SLTDataType x)
{
 assert(pphead);
 SLTNode* newnode = BuySListNode(x);
 newnode->next = *pphead;
 *pphead = newnode;
}

2.6 头删

void SListPopFront(SLTNode** pphead)
{
 assert(pphead);
 assert(*pphead);
 SLTNode* next = (*pphead)->next;
 free(*pphead);
 *pphead = NULL;
 *pphead = next;
}

2.7 在任意节点后插入节点

void SListInsert(SLTNode* pos, SLTDataType x)
{
 assert(pos);
 SLTNode* newnode = BuySListNode(x);
 SLTNode* next = pos->next;
 pos->next = newnode;
 newnode->next = next;
}

2.8 在任意节点后删除节点

void SListErase(SLTNode* pos)
{
 assert(pos);
 assert(pos->next);
 SLTNode* next = pos->next;
 pos->next = next->next;
 free(next);
 next = NULL;
}

2.9 销毁链表

void SListDestroy(SLTNode** pphead)
{
 assert(pphead);
 SLTNode* cur, * nextnode;
 cur = *pphead;
 nextnode = NULL;
 while (cur)
 {
  nextnode = cur->next;
  free(cur);
  cur = nextnode;
 }
 *pphead = NULL;
}

三、头文件相关内容

3.1 引用的库函数

#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
#include<stdbool.h>

3.2 结构体声明

typedef int SLTDataType;//重定义可便于修改值的数据类型
1
typedef struct SListNode
{
 SLTDataType data;
 struct SListNode* next;
}SLTNode;//重定义可减少代码冗余

到此这篇关于C语言实现无头单向链表的示例代码的文章就介绍到这了,更多相关C语言无头单向链表内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • C语言之单向链表详解及实例代码

    1,单向链简洁. 单向链表(单链表)是链表的一种,其特点是链表的链接方向是单向的,对链表的访问要通过顺序读取从头部开始:链表是使用指针进行构造的列表:又称为结点列表,因为链表是由一个个结点组装起来的:其中每个结点都有指针成员变量指列表中的下一个结点:列表是由结点构成,由head指针指向第一个成为表头的结点而终止于最后一个指向nuLL的指针: 2,例子要求: 根据示例代码中的例子,完成单向链表(single linked list)中的以字符串为数据的链表的插入.删除以及查找,并支持单向链表的反转

  • C语言单向链表的表示与实现实例详解

    1.概述: C语言中的单向链表(单链表)是链表的一种,其特点是链表的链接方向是单向的,对链表的访问要通过顺序读取从头部开始. 链表中最简单的一种是单向链表,它包含两个域,一个信息域和一个指针域.这个链接指向列表中的下一个节点,而最后一个节点则指向一个空值. 如下图所示: 一个单向链表包含两个值: 当前节点的值和一个指向下一个节点的链接 一个单向链表的节点被分成两个部分.第一个部分保存或者显示关于节点的信息,第二个部分存储下一个节点的地址.单向链表只可向一个方向遍历. 链表最基本的结构是在每个节点

  • C语言解字符串逆序和单向链表逆序问题的代码示例

    字符串逆序 上次面试碰到一个单向链表逆序的题目,幸好对字符串逆序比较熟悉,类比做出来了.字符串逆序比较简单,直接上代码: void stringReverse(char* p1,char* p2) { if(p1==p2)return; //swap the value of p1 ,p2 *p1=(*p1)+(*p2); *p2=(*p1)-(*p2); *p1=(*p1)-(*p2); if(p1==p2-1)return; else stringReverse(++p1,--p2); }

  • C语言实现无头单向链表的示例代码

    目录 一.易错的接口实现 1.1 新节点开辟函数 1.2 尾插 1.3 尾删 二.常见简单接口 2.1 打印链表 2.2 节点计数器 2.3 判断是否为空链表 2.4 通过值查找节点 2.5 头插 2.6 头删 2.7 在任意节点后插入节点 2.8 在任意节点后删除节点 2.9 销毁链表 三.头文件相关内容 3.1 引用的库函数 3.2 结构体声明 一.易错的接口实现 1.1 新节点开辟函数 由于创建一个新节点是频繁的操作,所以封装为一个接口最佳. 链表节点的属性有:(1)数值.(2)指向下一个

  • C语言实现线性动态(单向)链表的示例代码

    目录 什么是链表 为什么不用结构体数组 链表的操作 创建表 删除元素 插入元素 代码及运行结果 什么是链表 链表是数据结构里面的一种,线性链表是链表的一种,线性链表的延伸有双向链表和环形链表.在编程语言中优化数据结构可以在处理大数据时大大降低程序的空间复杂性和时间复杂性.这里我只用一个简单的例子——线性单向链表为例,说明C语言是如何实现该结构的. 链表的元素是由结构体来实现struct table *p.结构体中有一个成员是结构体指针struct table *next,而这个结构体指针的类型和

  • JavaScript封装单向链表的示例代码

    使用JavaScript封装单向链表: 1. 封装LinkList的类,用于表示我们的链表结构. 2. 在LinkList类中有一个Node类,用于封装每一个节点上的信息(data与next). 3. 在链表中保存两个属性,一个是链表的长度,一个是链表中的第一个节点. 4.封装一些链表的常用方法: append(element):想列表尾部添加一个新的项: insert(position,element):向列表的特定位置插入一个新的项: get(position):获取对应位置的元素: ind

  • C语言数据结构之单向链表详解分析

    链表的概念:链表是一种动态存储分布的数据结构,由若干个同一结构类型的结点依次串连而成. 链表分为单向链表和双向链表. 链表变量一般用指针head表示,用来存放链表首结点的地址. 每个结点由数据部分和下一个结点的地址部分组成,即每个结点都指向下一个结点.最后一个结点称为表尾,其下一个结点的地址部分的值为NULL(表示为空地址). 特别注意:链表中的各个结点在内存中是可以不连续存放的,具体存放位置由系统分配. 例如:int *ptr ; 因此不可以用ptr++的方式来寻找下一个结点. 使用链表的优点

  • C语言实现无头单链表详解

    目录 链表的结构体描述(节点) 再定义一个结构体(链表) 断言处理 & 判空处理 创建链表 创建节点 头插法 打印链表 尾插法 指定位置插入 头删法 尾删法 指定位置删除 查找链表 删除所有指定相同的元素 总结 再封装的方式,用 c++ 的思想做无头链表 链表的结构体描述(节点) #include <stdio.h> #include <stdlib.h> #include <assert.h> typedef int DataType; //节点 typede

  • C语言实现动态链表的示例代码

    目录 结构体定义已经函数声明 函数实现 创建一个链表 判断链表是否为空 获得链表中节点的个数 在某个特定的位置插入一个元素 获得指定下标的节点的元素 删除一个节点 链表逆序 链表的清空 链表的销毁 链表的遍历 按特定的元素查找节点 按某些特定的条件删除所有符合情况的节点 链表的排序 总结 链表是一种物理存储单元上非连续.非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的.链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行时动态生成.每个结点包括两个部分:一个是存储

  • C语言中数据结构之链表归并排序实例代码

    C语言中数据结构之链表归并排序实例代码 问题 设有两个无头结点的单链表,头指针分别为ha,hb,链中有数据域data,链域next,两链表的数据都按递增排序存放,现要求将hb表归到ha表中,且归并后ha仍递增序,归并中ha表中已有的数据若hb中也有,则hb中的数据不归并到ha中,hb的链表在算法中不允许破坏. 源程序 #include <stdio.h> #include<stdlib.h> #define N1 6 /*链表La的长度*/ #define N2 6 /*链表Lb的

  • C语言编程入门必背的示例代码整理大全

    目录 一.C语言必背代码前言 二.一部分C语言必背代码 一.C语言必背代码前言 对于c语言来说,要记得东西其实不多,基本就是几个常用语句加一些关键字而已.你所看到的那些几千甚至上万行的代码,都是用这些语句和关键词来重复编写的.只是他们逻辑功能不一样,那如何快速的上手C语言代码,建议多看多写,下面是小编整理的C语言必背代码. 二.一部分C语言必背代码 1.输出9*9成法口诀,共9行9列,i控制行,j控制列. #include "stdio.h" main() {int i,j,resul

  • C/C++实现线性单链表的示例代码

    目录 线性单链表简介 C语言实现代码 C++语言实现代码 线性单链表简介 使用链存储结构的线性存储结构为线性单链表,线性存储结构是元素逻辑结构一对一,链存储结构是元素物理结构不连续,线性单链表操作没有限制,线性单链表优点是可以直接插入和删除元素,线性单链表缺点是不可以使用下标获取和修改元素. C语言实现代码 #include<stdio.h>//包含标准输入输出文件 #include<stdlib.h>//包含标准库文件 typedef struct element//元素 { i

  • C语言实现经典排序算法的示例代码

    目录 一.冒泡排序 1.原理 2.实现 3.算法分析 二.选择排序 1.原理 2.实现 3.算法分析 三.插入排序 1.原理 2.实现 3.算法分析 四.希尔排序 1.原理 2.实现 3.算法分析 总结 一.冒泡排序 1.原理 从数组的头开始不断比较相邻两个数的大小,不断将较大的数右移,一个循环后,最大数移至最后一位,无序数组规模减一.不断重复前面动作,知道数组完全有序. 2.实现 void swap(int* a, int* b) { int temp = *a; *a = *b; *b =

随机推荐