数据结构之单链表

什么是单链表

单链表线性链式存储结构 ,每个节点存数据下一个节点地址,节点不连续分布在内存。

单链表的结构

我们要先来构建结点的结构

节点分为数据域和指针域

数据域用来储存数据,指针域用来寻找下一个节点的位置

cpp 复制代码
typedef int LDataType;
typedef struct ListNode {
    LDataType data;         // 存储数据
    struct ListNode* next;  // 存放后继结点地址
}LNode, * LinkList;

初始化单链表

我们构建的链表是有哨兵位头节点的链表,初始化也就是将哨兵位头节点初始化,由于哨兵位节点并不用来储存数据,我们将其搞成-1.

链表节点的数量是不确定的,我们需要malloc来申请空间,然后我们将新建节点的操作单拎出来来实现,方便之后的使用

cpp 复制代码
// 创建一个新结点
LNode* BuyListNode(int data)
{
	LNode* newNode = (LNode*)malloc(sizeof(LNode));
	if (newNode == NULL)
	{
		printf("申请空间失败\n");
		return  NULL;

	}
	newNode->data = data;
	newNode->next = NULL;
	return newNode;
}


// 初始化链表
LNode* ListInit()
{
	LNode* head = BuyListNode(-1);
	return head;
}

插入数据

我们观察上面的图片,我们在插入时要记录插入位置的前面一个节点,然后new一个新的节点.

prev,new,next

这个时候我们由两种方式来解决,第一种就是将前面节点记录,将后面节点记录,然后在按照顺序对其进行连接

第二种就是不新起节点,但是这时必须要遵循操作的顺序,不然链表就断链了

先将new的next指向prev的next,再将prev的next指向new.

主要的操作就是这样,但真的实践起来我们还要考虑头插,尾插是否可以实现

边界的处理,要查看能不能实现头插,尾插这样的操作

cpp 复制代码
void ListInsert(LNode* L, int i, LDataType x)
{
	assert(L);
	assert(i >= 0);
	//先new一个新的节点出来
	LNode* cur = BuyListNode(x);
	LNode* prev = L;
	int count = -1;
	
	while (prev&&count<i-1)
	{
		prev = prev->next;
		count++;
	}
	
	if (prev == NULL || count != i - 1)
	{
		free(cur);
		return;
	}

	// prev   cur   next
	LNode* next = prev->next;
	prev->next = cur;
	cur->next = next;


}

删除数据

删除的逻辑

第一步也是要记录删除节点的前面一个位置的节点

后面也可以和插入哪里类似,这里不做过多的赘述,但是要注意删除的节点要free

主要的操作就是这样,但真的实践起来我们还要考虑头插,尾插是否可以实现

边界的处理

cpp 复制代码
// 删除链表中下标为i的结点,并用x带出结点的值
LDataType ListDelete(LNode* L, int i)
{
	//先找出删除位置的前一个位置
	assert(L);
	assert(i >= 0);
	LNode* prev = L;
	int count = -1;

	while (prev && count < i - 1)
	{
		prev = prev->next;
		count++;
	}

	if (prev == NULL || count != i - 1)
	{
		return;
	}
	//prev  cur  next
	LNode* next = prev->next->next;
	LNode* cur = prev->next;
	LDataType x = cur->data;
	prev->next = next;
	free(cur);
	return x;
}

销毁单链表

就是将整张表遍历一遍,并且删除节点,为了防止找不到下一个节点我们要记录下一个节点

cpp 复制代码
// 销毁链表
void ListDestroy(LNode* L)
{
	LNode* cur = L;

	while (cur)
	{
		LNode* next = cur->next;
		free(cur);
		cur = next;
	}
}

头删尾删,头插尾插,判空

比较简单,这里不多做赘述

cpp 复制代码
bool ListEmpty(LNode* L)
{
    assert(L);
    return L->next == NULL;
}

void ListPushFront(LNode* L, LDataType x)
{
    assert(L);
    LNode* newNode = BuyListNode(x);
    newNode->next = L->next;
    L->next = newNode;
}

void ListPushBack(LNode* L, LDataType x)
{
    assert(L);
    LNode* tail = L;
    while (tail->next)
    {
        tail = tail->next;
    }
    tail->next = BuyListNode(x);
}

LDataType ListPopFront(LNode* L)
{
    assert(L);
    assert(!ListEmpty(L));
    LNode* del = L->next;
    LDataType x = del->data;
    L->next = del->next;
    free(del);
    return x;
}

LDataType ListPopBack(LNode* L)
{
    assert(L);
    assert(!ListEmpty(L));
    LNode* prev = L;
    while (prev->next && prev->next->next)
    {
        prev = prev->next;
    }
    LNode* del = prev->next;
    LDataType x = del->data;
    prev->next = NULL;
    free(del);
    return x;
}

单链表与顺序表的对比

操作 顺序表 单链表
随机访问(下标取值 arr i O(1) 直接寻址 O(n) 必须从头遍历
头部插入 / 删除 O(n)(全体数据后移 / 前移) O(1)(头插只需改头指针)
尾部插入 / 删除(未满) O(1) O(n)(需要遍历找尾)
中间第 i 位插删 O(n)(大量搬数据) O(n)(找前驱,找到后修改指针O(1))
按值查找 无序O(n) 只能遍历O(n)
存储空间
  • 顺序表 :连续堆内存,预先分配容量,存在闲置空间浪费;存数据 + 无额外开销。
  • 单链表 :节点离散分布,按需malloc;每个节点多存 1 个next指针,额外空间开销大
扩容逻辑
  • 顺序表:空间满要重新开辟更大数组 + 拷贝全部元素,扩容代价高。
  • 链表:不用整体扩容,新增结点单独申请内存,无整体搬迁。
随机存取
  • 顺序表:依靠首地址 + 偏移量,支持[下标]随机访问。
  • 链表:无连续地址,不支持随机访问,想找第 i 个必须从头挨个走
增删本质区别
  • 顺序表:改位置 =移动大量元素(数据搬家)。
  • 单链表:找到前驱后 =修改 2 处指针指向,数据不移动。

顺序表适合,频繁的查询,在尾部插入和删除较多,随机访问较多的场景

单链表适合,频繁的头尾插入,删除.

相关推荐
凤凰院凶涛QAQ4 小时前
《Java版数据结构 & 集合类剖析》栈与队列:“push/pop 是栈的灵魂,offer/poll 是队列的骨架——四组 API,两种人生”
java·开发语言·数据结构
郝学胜-神的一滴5 小时前
算法实战:最小k个数——大顶堆的优雅解法
开发语言·数据结构·c++·python·程序人生·算法·排序算法
Irissgwe5 小时前
算法滑动窗口
数据结构·算法
LuminousCPP8 小时前
C 语言集中实践全记录:顺序表 + 单链表原理实现与通讯录项目实战【附可运行源码】
c语言·开发语言·数据结构·经验分享·笔记
兰令水8 小时前
hot100【acm版】【2026.7.13打卡-java版本】
java·开发语言·数据结构·算法·leetcode·面试
LuminousCPP11 小时前
单链表专题(应用篇):三道经典题吃透删除、反转与快慢指针
c语言·数据结构·笔记
:-)11 小时前
算法-希尔排序
数据结构·算法·排序算法
罗超驿1 天前
2.算法效率的核心密码:时间复杂度和空间复杂度详解
java·数据结构·算法
:-)1 天前
算法-堆排序
数据结构·算法·排序算法
j7~1 天前
【数据结构初阶】顺序表增删查改代码实现--详解
数据结构·顺序表·动态顺序表·静态顺序表