链表及详解

1.链表

1.1链表的介绍

链表是一种常见的数据结构,用于存储一系列的元素,它与数组不同,链表中的元素不一定是连续存储在内存中的。链表由一系列节点组成,每个节点包含两个部分:数据域和指针域。数据域用来存储数据,而指针域则用来指向下一个节点。链表的最后一个节点的指针域通常指向空(null),表示链表的结束。

1.2链表的主要类型:


1.单链表(Singly Linked List):每个节点只包含一个指针,指向下一个节点。
2.双链表(Doubly Linked List):每个节点包含两个指针,一个指向前一个节点,另一个指向下一个节点。
3.循环链表(Circular Linked List):链表的最后一个节点的指针域指向第一个节点,形成一个环。


1.3链表的主要操作包括:


1.插入:在链表的某个位置插入一个新的节点。
2.删除:从链表中移除某个节点。
3.查找:在链表中查找某个特定值的节点。
4.遍历:按顺序访问链表中的每个节点。
链表的优点在于插入和删除操作不需要移动大量的元素,只需要改变相关节点的指针即可。但是,链表的缺点是访问元素不如数组那样可以直接通过索引快速访问,需要从头节点开始依次遍历到目标节点。此外,链表的每个节点都需要额外的空间来存储指针。
在实际应用中,链表常用于实现栈、队列、哈希表等数据结构,也用于解决某些特定问题,如LRU缓存淘汰算法等。

2.代码的展示

2.1链表的生成及销毁

typedef int SLTINT;
//链表是由节点组成的
typedef struct Linklist//链表                      
{
	SLTINT data;
	struct Linklist* next;

}List;
void LIDestory(List** pphead)
{
	assert(pphead);
	assert(*pphead);


	List* pcur = *pphead;
	while (pcur)
	{
		List* next = pcur->next;
		free(pcur);
		pcur = next;
	}
	*pphead = NULL;
}

2.2链表的初始化

//void Slisttext01()
//{
//	List* node1 = (List*)malloc(sizeof(List));
//	node1->data = 1;
//	List* node2 = (List*)malloc(sizeof(List));
//	node2->data = 2;
//	List* node3 = (List*)malloc(sizeof(List));
//	node3->data = 3;
//	List* node4 = (List*)malloc(sizeof(List));
//	node4->data = 4;
//	node1->next = node2;
//	node2->next = node3;
//	node3->next = node4;
//	node4->next = NULL;
//	List* plist = node1;
//	LIprint(plist);
//}

2.3链表的打印及插入

void LIprint(List* phead)
{
	List* pucr = phead;
	while (pucr)
	{
		printf("%d->", pucr->data);
		pucr = pucr->next;
	}
	printf("NULL\n");
}
//申请空间
List* LIBuynode(SLTINT x)
{
	List* newnode = (List*)malloc(sizeof(List));
	if (newnode == NULL)
	{
		perror("malloc fail!");
		exit(1);
	}
	newnode->data = x;
	newnode->next = NULL;
	return newnode;
}
void LIPushBack(List** pphead, SLTINT x)
{
	assert(pphead);
	//链表为空,新节点作为phead
	List* newnode = LIBuynode(x);
	if (*pphead == NULL)
	{
		*pphead = newnode;
		return;
	}
	
	//链表不为空,找尾节点插入
	List* Pcur = *pphead;
	while (Pcur->next)
	{
		Pcur = Pcur->next;
	}
	//尾节点
	Pcur->next = newnode;
	
}

void LIPushFront(List** pphead, SLTINT x)
{
	assert(pphead);
	//链表为空,找节点作为phead
	List* newnode = LIBuynode(x);

	List* Pcur = *pphead;
	newnode->next = Pcur;
	*pphead = newnode;
	
	//链表不为空,找头节点插入
}

2.4链表的删除

void LIPopBack(List** pphead)
{
	assert(pphead);
	assert(*pphead);
	//链表有一个节点
	if ((*pphead)->next == NULL)
	{
		free(*pphead);
		*pphead = NULL;
		return;
	}
	else
	{
		//链表有多个节点
		List* Pcur = *pphead;
		List* prev = NULL;
		while (Pcur->next!=NULL)
		{
			prev = Pcur;
			Pcur = Pcur->next;
		}

		prev->next = NULL;
		//释放尾节点
		free(Pcur);
		Pcur = NULL;
	}
}
//头删
void LIPopFront(List** pphead)
{
	assert(pphead);
	assert(*pphead);
	List* po = (*pphead)->next;
	free(*pphead);
	*pphead = po;
}

2.5链表的指定位置的查找及删除插入

//查找链表
List* LIFind(List** pphead, SLTINT x)
{
	assert(pphead);
	List* pcur = *pphead;
	while (pcur)
	{
		if (pcur->data == x)
		{
			return pcur;
		}
		pcur = pcur->next;
	}
	//没有找到
	return NULL;
}


void LIInsert(List** pphead, List* pos, SLTINT x)
{
	assert(pphead);
	assert(*pphead);
	assert(pos);
	if (pos == *pphead)
	{
		LIPushFront(pphead,x);
		return;
	}
	//pos不是头结果的情况
	List* newnode = LIBuynode(x);
	List* prev = *pphead;
	while (prev->next != pos)
	{
		prev = prev->next;
	}
	prev->next = newnode;
	newnode->next = pos;
}


void LIInsertafter(List* pos, SLTINT x)
{

	assert(pos);
	List* newnode = LIBuynode(x);
	newnode->next = pos->next;
	pos->next = newnode;
}


void LIstrase(List** pphead, List*pos)
{
	assert(pphead);
	assert(*pphead);
	assert(pos);
	if (*pphead == pos)
	{
		//头删
		LIPopFront(pphead);
		return;
	}
	List* prev = *pphead;
	while (prev->next != pos)
	{
		prev = prev->next;
	}
	prev->next = pos->next;
	free(pos);
	pos = NULL;
}

void LIstraseafter( List* pos)
{
	assert(pos);
	assert(pos->next);
	List* dit = pos->next;
	pos->next = pos->next->next;
	free(dit);
	dit = NULL;
	
}

3.总代码的展示

.h头文件

#define _CRT_SECURE_NO_WARNINGS 
#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
typedef int SLTINT;
//链表是由节点组成的
typedef struct Linklist//链表                      
{
	SLTINT data;
	struct Linklist* next;

}List;
//链表的打印
void LIprint(List* phead);
//链表的尾部插入
void LIPushBack(List** pphead, SLTINT x);
//链表的头部插入
void LIPushFront(List** pphead, SLTINT x);
//链表申请空间
List* LIBuynode(List x);
//链表的尾部删除
void LIPopBack(List** pphead);
//链表的头部删除
void LIPopFront(List** pphead);
//查找链表
List* LIFind(List** pphead, SLTINT x);
//在指定位置之前插入数据
void LIInsert(List** pphead, List* pos, SLTINT x);
//在指定位置之后插入数据
void LIInsertafter(List* pos, SLTINT x);
//删除指定位置的节点
void LIstrase(List* pphead, List* pos);

//删除指定位置之后的节点
void LIstraseafter( List* pos);

//销毁链表
void LIDestory(List** pphead);

.c源代码

#define _CRT_SECURE_NO_WARNINGS 
#include "list.h"
//链表的打印
void LIprint(List* phead)
{
	List* pucr = phead;
	while (pucr)
	{
		printf("%d->", pucr->data);
		pucr = pucr->next;
	}
	printf("NULL\n");
}
List* LIBuynode(SLTINT x)
{
	List* newnode = (List*)malloc(sizeof(List));
	if (newnode == NULL)
	{
		perror("malloc fail!");
		exit(1);
	}
	newnode->data = x;
	newnode->next = NULL;
	return newnode;
}
void LIPushBack(List** pphead, SLTINT x)
{
	assert(pphead);
	//链表为空,新节点作为phead
	List* newnode = LIBuynode(x);
	if (*pphead == NULL)
	{
		*pphead = newnode;
		return;
	}
	
	//链表不为空,找尾节点插入
	List* Pcur = *pphead;
	while (Pcur->next)
	{
		Pcur = Pcur->next;
	}
	//尾节点
	Pcur->next = newnode;
	
}

void LIPushFront(List** pphead, SLTINT x)
{
	assert(pphead);
	//链表为空,找节点作为phead
	List* newnode = LIBuynode(x);

	List* Pcur = *pphead;
	newnode->next = Pcur;
	*pphead = newnode;
	
	//链表不为空,找头节点插入
}

void LIPopBack(List** pphead)
{
	assert(pphead);
	assert(*pphead);
	//链表有一个节点
	if ((*pphead)->next == NULL)
	{
		free(*pphead);
		*pphead = NULL;
		return;
	}
	else
	{
		//链表有多个节点
		List* Pcur = *pphead;
		List* prev = NULL;
		while (Pcur->next!=NULL)
		{
			prev = Pcur;
			Pcur = Pcur->next;
		}

		prev->next = NULL;
		//释放尾节点
		free(Pcur);
		Pcur = NULL;
	}
}
//头删
void LIPopFront(List** pphead)
{
	assert(pphead);
	assert(*pphead);
	List* po = (*pphead)->next;
	free(*pphead);
	*pphead = po;
}
//查找链表
List* LIFind(List** pphead, SLTINT x)
{
	assert(pphead);
	List* pcur = *pphead;
	while (pcur)
	{
		if (pcur->data == x)
		{
			return pcur;
		}
		pcur = pcur->next;
	}
	//没有找到
	return NULL;
}


void LIInsert(List** pphead, List* pos, SLTINT x)
{
	assert(pphead);
	assert(*pphead);
	assert(pos);
	if (pos == *pphead)
	{
		LIPushFront(pphead,x);
		return;
	}
	//pos不是头结果的情况
	List* newnode = LIBuynode(x);
	List* prev = *pphead;
	while (prev->next != pos)
	{
		prev = prev->next;
	}
	prev->next = newnode;
	newnode->next = pos;
}


void LIInsertafter(List* pos, SLTINT x)
{

	assert(pos);
	List* newnode = LIBuynode(x);
	newnode->next = pos->next;
	pos->next = newnode;
}


void LIstrase(List** pphead, List*pos)
{
	assert(pphead);
	assert(*pphead);
	assert(pos);
	if (*pphead == pos)
	{
		//头删
		LIPopFront(pphead);
		return;
	}
	List* prev = *pphead;
	while (prev->next != pos)
	{
		prev = prev->next;
	}
	prev->next = pos->next;
	free(pos);
	pos = NULL;
}

void LIstraseafter( List* pos)
{
	assert(pos);
	assert(pos->next);
	List* dit = pos->next;
	pos->next = pos->next->next;
	free(dit);
	dit = NULL;
	
}


void LIDestory(List** pphead)
{
	assert(pphead);
	assert(*pphead);


	List* pcur = *pphead;
	while (pcur)
	{
		List* next = pcur->next;
		free(pcur);
		pcur = next;
	}
	*pphead = NULL;
}

测试代码

#include "list.h"
//void Slisttext01()
//{
//	List* node1 = (List*)malloc(sizeof(List));
//	node1->data = 1;
//	List* node2 = (List*)malloc(sizeof(List));
//	node2->data = 2;
//	List* node3 = (List*)malloc(sizeof(List));
//	node3->data = 3;
//	List* node4 = (List*)malloc(sizeof(List));
//	node4->data = 4;
//	node1->next = node2;
//	node2->next = node3;
//	node3->next = node4;
//	node4->next = NULL;
//	List* plist = node1;
//	LIprint(plist);
//}
void Slisttext02()
{
	List* plist = NULL;
	LIPushBack(&plist, 1);
	LIPushBack(&plist, 2);
	LIPushBack(&plist, 3);
	LIPushBack(&plist, 4);
	LIprint(plist);
	LIPopBack(&plist);
	/*LIPopBack(&plist);
	LIPopBack(&plist);
	LIPopBack(&plist);
	LIPopBack(&plist);*/
	//LIPopFront(&plist);
	LIprint(plist);
}
void Slisttext03()
{
	List* plist = NULL;
	LIPushFront(&plist, 1);
	LIPushFront(&plist, 2);
	LIPushFront(&plist, 3);
	LIPushFront(&plist, 4);
	LIprint(plist);
	List*Findet= LIFind(&plist, 2);
	LIInsert(&plist, Findet, 6);
	LIprint(plist);
	List* Findert = LIFind(&plist, 1);
	LIInsertafter(Findert, 66);
	LIprint(plist);
	List* Findrt = LIFind(&plist, 1);
	LIstrase(&plist, Findrt);
	LIprint(plist);

	/*if (Findet)
	{
		printf("找到了!\n");
	}
	else
	{
		printf("没有找到\n");
	}*/
}
int main()
{
//	Slisttext01();
	Slisttext02();
	Slisttext03();
	return 0;
}

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值