数据结构——单链表1

1. 单链表

1.1 概念与结构

概念:链表是一种物理存储结构上非连续、非顺序的存储结构 ,数据元素的逻辑顺序 是通过链表中的指针链接次序实现的。

1.1.1 结点

  • 与顺序表不同的是,链表里的每节都是独立申请下来的空间,我们称之为**"节点/结点"**
  • 节点的组成部分主要有两个部分组成:当前节点要保存的数据(数据域)和保存下一个节点的地址(指针域)
  • 链表中每个节点都是独立申请的,(需要插入数据时才去申请一块节点的空间),需要指针变量来保存下一个节点的位置才可以从当前的节点找到下一个节点。

1.1.2 链表的性质

  • 链表结构在逻辑上时连续的,在物理结构上不一定是连续的
  • 节点一般是从堆上申请的
  • 从堆上申请来的空间,是按照一定的策略来分配的,每次申请的空间可能是连续的,也可能是不连续的

每个节点对应的结构体代码:

cs 复制代码
typedef int SLTDataType;
//定义链表节点的结构
typedef struct SListNode
{
	SLTDataType  data;       //节点数据
	struct SListNode* next;  //下一个节点的地址
}SLTNode;

1.1.3 链表的打印

cs 复制代码
//单链表的打印
void SLTPrint(SLTNode* phead) {
	SLTNode* pcur = phead;
	while (pcur)
	{
		printf("%d -> ",pcur->data);
		pcur = pcur->next;

	}
	printf("NULL\n");
}

1.2 实现单链表

cs 复制代码
SList.h
cs 复制代码
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>

//定义单链表就是定义节点,因为单链表是由节点组成的,所以定义单链表就是定义节点
typedef int SLTDataType;
//定义链表节点的结构
typedef struct SListNode
{
	SLTDataType  data;
	struct SListNode* next;
}SLTNode;

//单链表的打印
void SLTPrint(SLTNode* phead);

//单链表的尾插
void SLTPushBack(SLTNode** pphead, SLTDataType x);

//单链表的头插
void SLTPushFront(SLTNode** pphead, SLTDataType x);

//单链表的尾删
void SLTPopBack(SLTNode** pphead);
cs 复制代码
SList.c
cs 复制代码
#include"SList.h"

//单链表的打印
void SLTPrint(SLTNode* phead) {
	SLTNode* pcur = phead;
	while (pcur != NULL)
	{
		printf("%d -> ",pcur->data);
		pcur = pcur->next;

	}
	printf("NULL\n");
}


//新节点的申请
SLTNode* SLTBuyNode(SLTDataType x)
{
	SLTNode* node = (SLTNode*)malloc(sizeof(SLTNode));//申请新节点这里传的应该是节点类型而不是数据类型
	//单链表:每次插入一个节点时,需要分配一个节点(结构体)的内存,因此使用 `sizeof(节点类型)`。
	//顺序表:在扩容时,需要为多个数据元素分配一块连续的内存(即数组),因此使用 `元素个数 * sizeof(数据类型)`。
	if (node == NULL)
	{
		perror("malloc fail!\n");
		exit(1);
	}
	node->data= x;
	node->next = NULL;
	return node;
}

//单链表的尾插
void SLTPushBack(SLTNode** pphead, SLTDataType x) {
	//单链表为空
	assert(pphead);
	//SLTNode* Tail = *pphead; 不能在这里定义Tail 因为这里的Tail为空,后面循环中的Tail->next 就会报错,不会进入循环当中
	SLTNode* newnode = SLTBuyNode(x);
	if (*pphead == NULL)
	{
		*pphead = newnode;
	}
	else {
		//单链表不为空,找尾节点,插入新节点
		SLTNode* Tail = *pphead;
		while (Tail->next != NULL)
		{
			Tail = Tail->next;
		}
		//跳出循环,插入新节点
		Tail->next = newnode;
		//newnode->next = NULL; 不需要写是因为,newnode在初始化的时候就已经置为NULL了
	}
}

//单链表的头插
void SLTPushFront(SLTNode** pphead, SLTDataType x) 
{
	assert(pphead);
	SLTNode* newnode = SLTBuyNode(x);
	newnode->next = *pphead;
	*pphead = newnode;
}

//单链表尾删
void SLTPopBack(SLTNode** pphead)
{
	assert(pphead);
	//只有一个节点的情况
	if ((*pphead)->next == NULL)
	{
		free(*pphead);
		*pphead = NULL;
	}
	SLTNode* Tail = *pphead;
	SLTNode* prev = NULL;
	while (Tail->next)
	{
		prev = Tail;
		Tail = Tail->next;
	}
	//跳出循环
	prev->next = NULL;
	free(Tail);
	Tail = NULL;
}

后续还有其它的单链表的实现哦~~~

相关推荐
爱吃烤鸡翅的酸菜鱼几秒前
【Redis】常用数据结构之List篇:从常用命令到典型使用场景
数据结构·redis·后端·缓存·list
会豪1 小时前
数据结构-栈/队列
数据结构
fangzelin52 小时前
算法-滑动窗口
数据结构·算法
iナナ4 小时前
Java优选算法——二分查找
数据结构·算法·leetcode
l1t4 小时前
利用美团龙猫添加xlsx的sheet.xml读取sharedStrings.xml中共享字符串输出到csv功能
xml·c语言·数据结构·人工智能·算法·解析器
lifallen6 小时前
揭秘KafkaStreams 线程缓存:NamedCache深度解析
数据结构·算法·缓存·kafka·apache
菜就多练,以前是以前,现在是现在6 小时前
Codeforces Round 1048 (Div. 2)
数据结构·c++·算法
失散137 小时前
分布式专题——9 Redis7底层数据结构解析
java·数据结构·redis·分布式·缓存·架构
崎岖Qiu8 小时前
leetcode380:RandomizedSet - O(1)时间插入删除和获取随机元素(数组+哈希表的巧妙结合)
java·数据结构·算法·leetcode·力扣·散列表
ZLRRLZ8 小时前
【数据结构】图
数据结构·算法·图论