IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> 单链表基本功能的实现(C语言) -> 正文阅读

[数据结构与算法]单链表基本功能的实现(C语言)

链表:每个节点包含两部分,一部分存放数据变量的data,另一部分是指向下一节点的next指针。

以下来实现不带头节点的单链表。每一个节点是结构体类型的,如下所示:

typedef struct SListNode{
	DateType data;//数据域
	struct SListNode* next;//指针域
}SListNode;

单链表最基本的功能有:头插,头删,尾插,尾删.......等,在每次头插或者尾插时都需要申请一个新的节点,所以把单独申请节点封装成一个函数,将申请到的节点的地址返回即可,代码如下:

SListNode * BuySListNode(DateType x){//在堆上动态申请一个节点,并返回节点首的地址
	SListNode *cur =(SListNode *) malloc(sizeof(SListNode));//申请大小为sizeof(SListNode)的空间
	if (cur == NULL){//申请失败,直接退出程序
		perror("malloc");
		exit(0);
	}
	cur->data = x;//修改申请的节点的data的值
	cur->next = NULL;//将新申请的节点的next置为空
	return cur;
}

首先会定义一个结构体指针,让它先指向空,然后通过调用不同的函数来实现不同的功能。

SListNode *plist=NULL;

1.头插:

void SListPushFront(SListNode ** plist, DateType x){//头插
	assert(plist);//判断指针的合法性
	SListNode *cur = *plist;//赋值后,cur此时相当于头指针
	*plist = BuySListNode(x);//改变头指针的指向,使其指向新申请的节点
	(*plist)->next = cur;//让新申请的节点的next指向原来的链表头
}

为什么要使用二级指针?因为在这里的每一次头插都需要改变指针plist的指向,而且头插的这个函数没有返回值,所以只有对函数中的二级指针解引用才能拿到真正的函数头指针,从而对它进行操作,改变它的指向。如果不想使用二级指针,那么函数必须要有返回值,而且返回值为:SListNode *类型。

2.尾插:

void SListPushBack(SListNode ** plist, DateType x){//尾插
	if (*plist == NULL){//链表中没有节点,此时直接插入
		*plist = BuySListNode(x);
	}
	else{
		SListNode *cur = *plist;
		while (cur->next){//cur的next为空,说明找到了最后一个节点,为尾插做准备
			cur = cur->next;
		}
		cur->next = BuySListNode(x);//插入节点
	}
}

尾插也需要使用二级指针,因为如果链表中没有节点那么此时还是需要改变定义出来的头指针的指向,这是一种特殊情况。如果要插入的链表中的节点个数>=1,那么此时可以不使用二级指针,因为一定可以找到最后一个节点的next域。

3.头删:每次需要改变头指针的指向,所以必须使用二级指针。

4.尾删:当链表只有一个节点的时候,这也属于一种特殊情况,因为此时要让链表的头指针指向空,所以要使用二级指针。如果要删除的链表中的节点个数>1,此时可以不使用二级指针,因为不需要改变头指针的指向。

搞清楚了二级指针在什么情况下使用,那么写出单链表的增、删、改、查就容易了,以下是完整代码和测试用例,使用多文件:

1.SListNode.h

#pragma once
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <windows.h>
#include <assert.h>
typedef int DateType;
typedef struct SListNode{
	DateType data;
	struct SListNode* next;
}SListNode;
extern SListNode * BuySListNode(DateType x);
extern void SListPushBack(SListNode ** plist, DateType x);
extern void SListPushFront(SListNode ** plist, DateType x);
extern void SListPopFront(SListNode **plist);
extern void SListPopBack(SListNode **plist);  
extern void SListInsertAfter(SListNode* pos, DateType x);
extern void SListPrint(SListNode *plist);

2.SListNode.c

#include "SListNode.h"
SListNode * BuySListNode(DateType x){//在堆上动态申请一个节点,并返回节点首的地址
	SListNode *cur =(SListNode *) malloc(sizeof(SListNode));//申请大小为sizeof(SListNode)的空间
	if (cur == NULL){//申请失败,直接退出程序
		perror("malloc");
		exit(0);
	}
	cur->data = x;//修改申请的节点的data的值
	cur->next = NULL;//将新申请的节点的next置为空
	return cur;
}
void SListPushFront(SListNode ** plist, DateType x){//头插
	assert(plist);//判断指针的合法性
	SListNode *cur = *plist;//赋值后,cur此时相当于头指针
	*plist = BuySListNode(x);//改变头指针的指向,使其指向新申请的节点
	(*plist)->next = cur;//让新申请的节点的next指向原来的链表头
}
void SListPopFront(SListNode **plist){//头删
	if (*plist == NULL){//链表中没有节点,不用删除
		return;
	}
	else{
		SListNode *cur = *plist;//赋值后,cur此时相当于头指针
		*plist = (*plist)->next;//让头指针指向原来链表中的第二个节点
		free(cur);//释放要删除的节点所占用的空间
	}
}
void SListPushBack(SListNode ** plist, DateType x){//尾插
    assert(plist);
	if (*plist == NULL){//链表中没有节点,此时直接插入
		*plist = BuySListNode(x);
	}
	else{
		SListNode *cur = *plist;
		while (cur->next){//cur的next为空,说明找到了最后一个节点,为尾插做准备
			cur = cur->next;
		}
		cur->next = BuySListNode(x);//插入节点
	}
}
void SListPopBack(SListNode **plist){//尾删
	if (*plist == NULL){//没有节点,直接返回
		return;
	}
	else if (((*plist)->next)==NULL){//只有一个节点,此时可以直接删除
		free(*plist);
		*plist = NULL;
	}
	else{
		SListNode *cur = *plist;//赋值后,cur此时相当于头指针
		SListNode *prev = cur;//赋值后,prev此时相当于头指针
		while (cur->next){//寻找最后一个节点,cur指向最后一个节点,而prev指向最后一个节点的前一个节点
			prev = cur;
			cur = cur->next;
		}
		prev->next = NULL;//把倒数第二个节点的next置空
		free(cur);//释放最后一个节点所占用的空间
	}
}
void SListPrint(SListNode *plist){//打印
	if (plist == NULL){
		printf("没有元素\n");
		return;
	}
	SListNode * cur = plist;
	while(cur){//遍历单链表,直到cur为空
		printf("->%d", cur->data);
		cur = cur->next;
	} 
	printf("\n");
}
SListNode* SListFind(SListNode* plist, DateType x){//查找
	if (plist == NULL){
		printf("没有元素\n");
		return NULL;
	}
	SListNode *cur = plist;
	while (cur!=NULL){
		if (cur->data == x){
			printf("找到了\n");
			return cur;
		}
		cur = cur->next;
	}
	return NULL;
}
void SListInsertAfter(SListNode* pos, DateType x){//在pos位置之后插入
	if (pos == NULL){
		return;
	}
	SListNode *cur = BuySListNode(x);
	cur->next = pos->next;
	pos->next = cur;
	/*SListNode *cur = pos->next;
	pos->next = BuySListNode(x);
	pos->next->next = cur;*/

}
void SListEraseAfter(SListNode* pos){//删除pos位置之后的节点
	if (pos == NULL||(pos->next)==NULL){
		return;
	}
	SListNode *cur = pos->next;
	pos->next = cur->next;
	free(cur);
}

3.main.c

#include "SListNode.h"
int main(){
	SListNode *plist=NULL;
	SListPushFront(&plist, 7);
	SListPushFront(&plist, 9);
	SListPrint(plist);
	SListPushBack(&plist, 5);
	SListPushBack(&plist, 4);
	SListPrint(plist);
	SListPopFront(&plist);
	SListPrint(plist);
	SListPopBack(&plist);
	SListPrint(plist);
	SListInsertAfter(plist,85);
	SListPrint(plist);
	system("pause");
	return 0;
}

运行程序后,结果如下:

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2021-11-28 11:32:46  更:2021-11-28 11:33:00 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2025年1日历 -2025/1/9 15:29:32-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码