顺序表--链表实现

本文介绍了链表的基础知识,包括单向无头链表和带头双向循环链表的特性。重点讲解了链表的常见操作,如尾插、尾删、头插、头删、插入、删除、查找等,并提供了相应的C语言实现。此外,还包含了链表的打印和销毁功能。示例代码展示了如何在实际应用中使用这些操作。
摘要由CSDN通过智能技术生成

链表

链表是一种在物理存储上无规则的存储结构,由指针将每个数据元素来串联起来。

链表可以从单向双向、带头不带头、循环非循环来进行分类,最常用的是无头单向非循环链表和带头双向链表。

无头单向链表:结构简单实现容易,但是一般不会用来存储数据,更多的是用来实现一些其他数据结构的子结构,如哈希桶、邻接表等。

在这里插入图片描述

带头双向循环链表:结构复杂,一般用来存储数据,其数据结构带来许多操作的优势。

在这里插入图片描述

单向链表结构定义:

typedef int SLTypeData;
typedef struct SListNode 
{
	SLTypeData data;
	struct SListNode* next;
}SListNode,SLn;
void SListPrint(SListNode* phead);//打印数据
void SListPushBack(SListNode** pphead, SLTypeData x);//尾插
void SListPushFront(SListNode** pphead, SLTypeData x);//头插
void SListPopBack(SListNode** pphead);//尾删
void SListPopFront(SListNode** pphead);//头删
SListNode* SListFind(SListNode* phead, SLTypeData x);//寻找数据
void SListInsert(SListNode** pphead, SListNode* pos, SLTypeData x);//在pos之前插入
void SListErase(SListNode** pphead, SListNode* pos);//删除数据
SListNode* BuySListNode(SLTypeData x);//建立数据
void SListEraseAfter(SListNode* pos);//删除pos后数据

尾删和尾插实现

void SListPushBack(SListNode**  pphead, SLTypeData x) {
	assert(pphead);//检查数据是否为空
	SListNode* newnode = (SListNode*)malloc(sizeof(SListNode));
	if (newnode == NULL) {
		printf("malloc fail\n");
		exit(-1);
	}
	else {
		newnode->data = x;
		newnode->next = NULL;
	}//如果malloc成功就插入数据

	if (*pphead == NULL) {
		*pphead = newnode;
	}//头节点为空直接在其后插入
	else{
		SListNode* tail = *pphead;
		while (tail->next != NULL) {
			tail = tail->next;
		}
		tail->next = newnode;
	}//若头节点不为空则找到最后一个节点在其后插入
}

void SListPopBack(SListNode** pphead) {
	assert(pphead);//检查是否为空
	
	if (*pphead == NULL) {//头节点为空
		return;
	}
	else if ((*pphead)->next == NULL) {//只有一个结点
		free(*pphead);
		*pphead = NULL;
	}
	else {//多个结点
		SListNode* prev = NULL;
		SListNode* tail = *pphead;
		while (tail->next != NULL) {
			prev = tail;
			tail = tail->next;
		}

		free(tail);
		tail = NULL;
		prev->next = NULL;
	}
}

!!!一定要传入二级指针,形参其实是实参的复制,而传入指针相当于传入指针的复制,如果没有传回指针的话在函数结束后函数栈帧会自动删除形参,此时找不到已经操作好的数据,所以要传入二级指针,对指针进行直接操作。

头插头删

void SListPushFront(SListNode** pphead, SLTypeData x) {
	assert(pphead);//检查是否为空
	SListNode* newnode = (SListNode*)malloc(sizeof(SListNode));
	if (newnode == NULL) {
		printf("malloc fail\n");
		exit(-1);
	}
	else {
		newnode->data = x;
		newnode->next = NULL;
	}//建立节点
	newnode->next = *pphead;
	*pphead = newnode;
}

void SListPopFront(SListNode** pphead) {
	assert(pphead);//检查是否为空

	if (*pphead == NULL) {
		return;
	}
	else {
		SListNode* next = (*pphead)->next;
		free(*pphead);
		*pphead = next;
	}
}

插入节点

void SListInsert(SListNode** pphead, SListNode* pos, SLTypeData x) {
	assert(pphead);
	assert(pos);//检查是否为空

	if (pos == *pphead) {
		SListPushFront(pphead, x);
	}//pos为头节点
	else {
		SListNode* prev = *pphead;
		while (prev->next != pos) {
			prev = prev->next;
		}
		SListNode* newnode = BuySListNode(x);
		prev->next = newnode;
		newnode->next = prev->next;

	}
}//在pos前插入

void SListInsertAfter(SListNode* pos, SLTypeData x)  {
	assert(pos);
	SListNode* next = pos->next;
	SListNode* newnode = BuySListNode(x);

	pos->next = newnode;
	newnode = next;
}//在pos后插入

删除节点

void SListErase(SListNode** pphead, SListNode* pos) {
	assert(pphead);
	assert(pos);
	if (*pphead == pos) {
		SListPopFront(pphead);
	}
	else {
		SListNode* prev = *pphead;
		while (prev->next != pos) {
			prev = prev->next;
		}

		prev->next = pos->next;
		free(pos);
		pos = NULL;
	}
}//删除pos处数据

void SListEraseAfter(SListNode* pos) {
	assert(pos);
	SListNode* next = pos->next;
	if (next) {
		pos->next = next->next;
		free(next);
		next = NULL;
	}
}//删除pos后数据

按值寻找节点

SListNode* SListFind(SListNode* phead, SLTypeData x) {
	SListNode* cur = phead;
	while (cur != NULL) {
		if (cur->data == x) {
			return cur;
		}
		cur = cur->next;
	}

	return NULL;
}

打印链表

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

销毁链表

void SListDestroy(SListNode** pphead) {
	assert(pphead);

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

	pphead = NULL;
}

主函数

#include"SList.h"

int main() {
	SListNode* head = NULL;
	SListNode* s1 = malloc(sizeof(SListNode));
	SListNode* s2 = malloc(sizeof(SListNode));
	SListNode* s3 = malloc(sizeof(SListNode));

	head = s1;
	s1->data = 1;
	s2->data = 2;
	s3->data = 3;
	s1->next = s2;
	s2->next = s3;
	s3->next = NULL;

	SListPushBack(&s3, 4);
	SListPrint(head);
	SListPopBack(&head);
	printf("\n");
	SListPrint(head);
	SListNode* pos = SListFind(s1, 3);
	if (pos)
	{
		SListInsert(&s1, pos, 30);
	}
	SListPrint(head);
	pos = SListFind(head, 3);
	if (pos)
	{
		SListErase(&head, pos);
	}
	SListPrint(head);
	return 0;
}

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值